diff options
| author | Remko Tronçon <git@el-tramo.be> | 2009-06-01 08:48:42 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2009-06-01 09:24:28 (GMT) | 
| commit | 2812bddd81f8a1b804c7460f4e14cd0aa393d129 (patch) | |
| tree | d46294f35150c4f0f43deaf2d31fceaf945ae715 /3rdParty/Boost/libs/thread/src | |
| download | swift-2812bddd81f8a1b804c7460f4e14cd0aa393d129.zip swift-2812bddd81f8a1b804c7460f4e14cd0aa393d129.tar.bz2 | |
Import.
Diffstat (limited to '3rdParty/Boost/libs/thread/src')
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp | 124 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/pthread/once.cpp | 51 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/pthread/thread.cpp | 678 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/pthread/timeconv.inl | 130 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/tss_null.cpp | 34 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/win32/exceptions.cpp | 124 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/win32/thread.cpp | 597 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/win32/timeconv.inl | 130 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp | 72 | ||||
| -rw-r--r-- | 3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp | 287 | 
10 files changed, 2227 insertions, 0 deletions
| diff --git a/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp b/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp new file mode 100644 index 0000000..8881303 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/exceptions.hpp> +#include <cstring> +#include <string> + +namespace boost { + +thread_exception::thread_exception() +    : m_sys_err(0) +{ +} + +thread_exception::thread_exception(int sys_err_code) +    : m_sys_err(sys_err_code) +{ +} + +thread_exception::~thread_exception() throw() +{ +} + +int thread_exception::native_error() const +{ +    return m_sys_err;  +} + +lock_error::lock_error() +{ +} + +lock_error::lock_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +lock_error::~lock_error() throw() +{ +} + +const char* lock_error::what() const throw() +{ +    return "boost::lock_error"; +} + +thread_resource_error::thread_resource_error() +{ +} + +thread_resource_error::thread_resource_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +thread_resource_error::~thread_resource_error() throw() +{ +} + +const char* thread_resource_error::what() const throw() +{ +    return "boost::thread_resource_error"; +} + +unsupported_thread_option::unsupported_thread_option() +{ +} + +unsupported_thread_option::unsupported_thread_option(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +unsupported_thread_option::~unsupported_thread_option() throw() +{ +} + +const char* unsupported_thread_option::what() const throw() +{ +    return "boost::unsupported_thread_option"; +} + +invalid_thread_argument::invalid_thread_argument() +{ +} + +invalid_thread_argument::invalid_thread_argument(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +invalid_thread_argument::~invalid_thread_argument() throw() +{ +} + +const char* invalid_thread_argument::what() const throw() +{ +    return "boost::invalid_thread_argument"; +} + +thread_permission_error::thread_permission_error() +{ +} + +thread_permission_error::thread_permission_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +thread_permission_error::~thread_permission_error() throw() +{ +} + +const char* thread_permission_error::what() const throw() +{ +    return "boost::thread_permission_error"; +} + +} // namespace boost diff --git a/3rdParty/Boost/libs/thread/src/pthread/once.cpp b/3rdParty/Boost/libs/thread/src/pthread/once.cpp new file mode 100644 index 0000000..6e3722a --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/once.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2007 Anthony Williams +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define __STDC_CONSTANT_MACROS +#include <boost/thread/once.hpp> +#include <boost/assert.hpp> +#include <pthread.h> +#include <stdlib.h> + +namespace boost +{ +    namespace detail +    { +        BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0); +        BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; +        BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; + +        namespace +        { +            pthread_key_t epoch_tss_key; +            pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; +             +            extern "C" void delete_epoch_tss_data(void* data) +            { +                free(data); +            } + +            extern "C" void create_epoch_tss_key() +            { +                BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); +            } +             +        } +         +        boost::uintmax_t& get_once_per_thread_epoch() +        { +            BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); +            void* data=pthread_getspecific(epoch_tss_key); +            if(!data) +            { +                data=malloc(sizeof(boost::uintmax_t)); +                BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); +                *static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0); +            } +            return *static_cast<boost::uintmax_t*>(data); +        } +    } +     +} diff --git a/3rdParty/Boost/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/libs/thread/src/pthread/thread.cpp new file mode 100644 index 0000000..cc71d97 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/thread.cpp @@ -0,0 +1,678 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#ifdef __linux__ +#include <sys/sysinfo.h> +#elif defined(__APPLE__) || defined(__FreeBSD__) +#include <sys/types.h> +#include <sys/sysctl.h> +#elif defined BOOST_HAS_UNISTD_H +#include <unistd.h> +#endif + +#include "timeconv.inl" + +namespace boost +{ +    namespace detail +    { +        thread_data_base::~thread_data_base() +        {} + +        struct thread_exit_callback_node +        { +            boost::detail::thread_exit_function_base* func; +            thread_exit_callback_node* next; + +            thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, +                                      thread_exit_callback_node* next_): +                func(func_),next(next_) +            {} +        }; + +        struct tss_data_node +        { +            void const* key; +            boost::shared_ptr<boost::detail::tss_cleanup_function> func; +            void* value; +            tss_data_node* next; + +            tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_, +                          tss_data_node* next_): +                key(key_),func(func_),value(value_),next(next_) +            {} +        }; + +        namespace +        { +            boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; +            pthread_key_t current_thread_tls_key; + +            extern "C" +            { +                void tls_destructor(void* data) +                { +                    boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data); +                    if(thread_info) +                    { +                        while(thread_info->tss_data || thread_info->thread_exit_callbacks) +                        { +                            while(thread_info->thread_exit_callbacks) +                            { +                                detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; +                                thread_info->thread_exit_callbacks=current_node->next; +                                if(current_node->func) +                                { +                                    (*current_node->func)(); +                                    delete current_node->func; +                                } +                                delete current_node; +                            } +                            while(thread_info->tss_data) +                            { +                                detail::tss_data_node* const current_node=thread_info->tss_data; +                                thread_info->tss_data=current_node->next; +                                if(current_node->func) +                                { +                                    (*current_node->func)(current_node->value); +                                } +                                delete current_node; +                            } +                        } +                        thread_info->self.reset(); +                    } +                } +            } +     + +            void create_current_thread_tls_key() +            { +                BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); +            } +        } +         +        boost::detail::thread_data_base* get_current_thread_data() +        { +            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); +            return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key); +        } + +        void set_current_thread_data(detail::thread_data_base* new_data) +        { +            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); +            BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); +        } +    } +     +    namespace +    { +        extern "C" +        { +            void* thread_proxy(void* param) +            { +                boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; +                thread_info->self.reset(); +                detail::set_current_thread_data(thread_info.get()); +                try +                { +                    thread_info->run(); +                } +                catch(thread_interrupted const&) +                { +                } +// Removed as it stops the debugger identifying the cause of the exception +// Unhandled exceptions still cause the application to terminate +//                 catch(...) +//                 { +//                     std::terminate(); +//                 } + +                detail::tls_destructor(thread_info.get()); +                detail::set_current_thread_data(0); +                boost::lock_guard<boost::mutex> lock(thread_info->data_mutex); +                thread_info->done=true; +                thread_info->done_condition.notify_all(); +                return 0; +            } +        } + +        struct externally_launched_thread: +            detail::thread_data_base +        { +            externally_launched_thread() +            { +                interrupt_enabled=false; +            } +             +            void run() +            {} + +        private: +            externally_launched_thread(externally_launched_thread&); +            void operator=(externally_launched_thread&); +        }; + +        detail::thread_data_base* make_external_thread_data() +        { +            detail::thread_data_base* const me(new externally_launched_thread()); +            me->self.reset(me); +            set_current_thread_data(me); +            return me; +        } + + +        detail::thread_data_base* get_or_make_current_thread_data() +        { +            detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); +            if(!current_thread_data) +            { +                current_thread_data=make_external_thread_data(); +            } +            return current_thread_data; +        } + +    } + + +    thread::thread() +    {} + +    void thread::start_thread() +    { +        thread_info->self=thread_info; +        int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get()); +        if (res != 0) +        { +            thread_info->self.reset(); +            throw thread_resource_error(); +        } +    } + +    thread::~thread() +    { +        detach(); +    } + +    detail::thread_data_ptr thread::get_thread_info() const +    { +        lock_guard<mutex> l(thread_info_mutex); +        return thread_info; +    } + +    void thread::join() +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            bool do_join=false; +             +            { +                unique_lock<mutex> lock(local_thread_info->data_mutex); +                while(!local_thread_info->done) +                { +                    local_thread_info->done_condition.wait(lock); +                } +                do_join=!local_thread_info->join_started; +                 +                if(do_join) +                { +                    local_thread_info->join_started=true; +                } +                else +                { +                    while(!local_thread_info->joined) +                    { +                        local_thread_info->done_condition.wait(lock); +                    } +                } +            } +            if(do_join) +            { +                void* result=0; +                BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); +                lock_guard<mutex> lock(local_thread_info->data_mutex); +                local_thread_info->joined=true; +                local_thread_info->done_condition.notify_all(); +            } +             +            lock_guard<mutex> l1(thread_info_mutex); +            if(thread_info==local_thread_info) +            { +                thread_info.reset(); +            } +        } +    } + +    bool thread::timed_join(system_time const& wait_until) +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            bool do_join=false; +             +            { +                unique_lock<mutex> lock(local_thread_info->data_mutex); +                while(!local_thread_info->done) +                { +                    if(!local_thread_info->done_condition.timed_wait(lock,wait_until)) +                    { +                        return false; +                    } +                } +                do_join=!local_thread_info->join_started; +                 +                if(do_join) +                { +                    local_thread_info->join_started=true; +                } +                else +                { +                    while(!local_thread_info->joined) +                    { +                        local_thread_info->done_condition.wait(lock); +                    } +                } +            } +            if(do_join) +            { +                void* result=0; +                BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); +                lock_guard<mutex> lock(local_thread_info->data_mutex); +                local_thread_info->joined=true; +                local_thread_info->done_condition.notify_all(); +            } +             +            lock_guard<mutex> l1(thread_info_mutex); +            if(thread_info==local_thread_info) +            { +                thread_info.reset(); +            } +        } +        return true; +    } + +    bool thread::joinable() const +    { +        return get_thread_info(); +    } + + +    void thread::detach() +    { +        detail::thread_data_ptr local_thread_info; +        { +            lock_guard<mutex> l1(thread_info_mutex); +            thread_info.swap(local_thread_info); +        } +         +        if(local_thread_info) +        { +            lock_guard<mutex> lock(local_thread_info->data_mutex); +            if(!local_thread_info->join_started) +            { +                BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle)); +                local_thread_info->join_started=true; +                local_thread_info->joined=true; +            } +        } +    } + +    namespace this_thread +    { +         +        void sleep(const system_time& st) +        { +            detail::thread_data_base* const thread_info=detail::get_current_thread_data(); +         +            if(thread_info) +            { +                unique_lock<mutex> lk(thread_info->sleep_mutex); +                while(thread_info->sleep_condition.timed_wait(lk,st)); +            } +            else +            { +                xtime const xt=get_xtime(st); +             +                for (int foo=0; foo < 5; ++foo) +                { +#   if defined(BOOST_HAS_PTHREAD_DELAY_NP) +                    timespec ts; +                    to_timespec_duration(xt, ts); +                    BOOST_VERIFY(!pthread_delay_np(&ts)); +#   elif defined(BOOST_HAS_NANOSLEEP) +                    timespec ts; +                    to_timespec_duration(xt, ts); +                 +                    //  nanosleep takes a timespec that is an offset, not +                    //  an absolute time. +                    nanosleep(&ts, 0); +#   else +                    mutex mx; +                    mutex::scoped_lock lock(mx); +                    condition cond; +                    cond.timed_wait(lock, xt); +#   endif +                    xtime cur; +                    xtime_get(&cur, TIME_UTC); +                    if (xtime_cmp(xt, cur) <= 0) +                        return; +                } +            } +        } + +        void yield() +        { +#   if defined(BOOST_HAS_SCHED_YIELD) +            BOOST_VERIFY(!sched_yield()); +#   elif defined(BOOST_HAS_PTHREAD_YIELD) +            BOOST_VERIFY(!pthread_yield()); +#   else +            xtime xt; +            xtime_get(&xt, TIME_UTC); +            sleep(xt); +#   endif +        } +    } + +    unsigned thread::hardware_concurrency() +    { +#if defined(PTW32_VERSION) || defined(__hpux) +        return pthread_num_processors_np(); +#elif defined(__linux__) +        return get_nprocs(); +#elif defined(__APPLE__) || defined(__FreeBSD__) +        int count; +        size_t size=sizeof(count); +        return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count; +#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) +        int const count=sysconf(_SC_NPROCESSORS_ONLN); +        return (count>0)?count:0; +#else +        return 0; +#endif +    } + +    thread::id thread::get_id() const +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            return id(local_thread_info); +        } +        else +        { +            return id(); +        } +    } + +    void thread::interrupt() +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            lock_guard<mutex> lk(local_thread_info->data_mutex); +            local_thread_info->interrupt_requested=true; +            if(local_thread_info->current_cond) +            { +                BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond)); +            } +        } +    } + +    bool thread::interruption_requested() const +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            lock_guard<mutex> lk(local_thread_info->data_mutex); +            return local_thread_info->interrupt_requested; +        } +        else +        { +            return false; +        } +    } + +    thread::native_handle_type thread::native_handle() +    { +        detail::thread_data_ptr const local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            lock_guard<mutex> lk(local_thread_info->data_mutex); +            return local_thread_info->thread_handle; +        } +        else +        { +            return pthread_t(); +        } +    } +     +     + +    namespace this_thread +    { +        thread::id get_id() +        { +            boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); +            return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr()); +        } + +        void interruption_point() +        { +            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); +            if(thread_info && thread_info->interrupt_enabled) +            { +                lock_guard<mutex> lg(thread_info->data_mutex); +                if(thread_info->interrupt_requested) +                { +                    thread_info->interrupt_requested=false; +                    throw thread_interrupted(); +                } +            } +        } +         +        bool interruption_enabled() +        { +            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); +            return thread_info && thread_info->interrupt_enabled; +        } +         +        bool interruption_requested() +        { +            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); +            if(!thread_info) +            { +                return false; +            } +            else +            { +                lock_guard<mutex> lg(thread_info->data_mutex); +                return thread_info->interrupt_requested; +            } +        } + +        disable_interruption::disable_interruption(): +            interruption_was_enabled(interruption_enabled()) +        { +            if(interruption_was_enabled) +            { +                detail::get_current_thread_data()->interrupt_enabled=false; +            } +        } +         +        disable_interruption::~disable_interruption() +        { +            if(detail::get_current_thread_data()) +            { +                detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled; +            } +        } + +        restore_interruption::restore_interruption(disable_interruption& d) +        { +            if(d.interruption_was_enabled) +            { +                detail::get_current_thread_data()->interrupt_enabled=true; +            } +        } +         +        restore_interruption::~restore_interruption() +        { +            if(detail::get_current_thread_data()) +            { +                detail::get_current_thread_data()->interrupt_enabled=false; +            } +        } +    } + +    namespace detail +    { +        void add_thread_exit_function(thread_exit_function_base* func) +        { +            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); +            thread_exit_callback_node* const new_node= +                new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks); +            current_thread_data->thread_exit_callbacks=new_node; +        } + +        tss_data_node* find_tss_data(void const* key) +        { +            detail::thread_data_base* const current_thread_data(get_current_thread_data()); +            if(current_thread_data) +            { +                detail::tss_data_node* current_node=current_thread_data->tss_data; +                while(current_node) +                { +                    if(current_node->key==key) +                    { +                        return current_node; +                    } +                    current_node=current_node->next; +                } +            } +            return NULL; +        } + +        void* get_tss_data(void const* key) +        { +            if(tss_data_node* const current_node=find_tss_data(key)) +            { +                return current_node->value; +            } +            return NULL; +        } +         +        void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing) +        { +            if(tss_data_node* const current_node=find_tss_data(key)) +            { +                if(cleanup_existing && current_node->func) +                { +                    (*current_node->func)(current_node->value); +                } +                current_node->func=func; +                current_node->value=tss_data; +            } +            else +            { +                detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); +                tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data); +                current_thread_data->tss_data=new_node; +            } +        } +    } + +//     thread_group::thread_group() +//     { +//     } + +//     thread_group::~thread_group() +//     { +//         // We shouldn't have to scoped_lock here, since referencing this object +//         // from another thread while we're deleting it in the current thread is +//         // going to lead to undefined behavior any way. +//         for (std::list<thread*>::iterator it = m_threads.begin(); +//              it != m_threads.end(); ++it) +//         { +//             delete (*it); +//         } +//     } + +//     thread* thread_group::create_thread(const function0<void>& threadfunc) +//     { +//         // No scoped_lock required here since the only "shared data" that's +//         // modified here occurs inside add_thread which does scoped_lock. +//         std::auto_ptr<thread> thrd(new thread(threadfunc)); +//         add_thread(thrd.get()); +//         return thrd.release(); +//     } + +//     void thread_group::add_thread(thread* thrd) +//     { +//         mutex::scoped_lock scoped_lock(m_mutex); + +//         // For now we'll simply ignore requests to add a thread object multiple +//         // times. Should we consider this an error and either throw or return an +//         // error value? +//         std::list<thread*>::iterator it = std::find(m_threads.begin(), +//                                                     m_threads.end(), thrd); +//         BOOST_ASSERT(it == m_threads.end()); +//         if (it == m_threads.end()) +//             m_threads.push_back(thrd); +//     } + +//     void thread_group::remove_thread(thread* thrd) +//     { +//         mutex::scoped_lock scoped_lock(m_mutex); + +//         // For now we'll simply ignore requests to remove a thread object that's +//         // not in the group. Should we consider this an error and either throw or +//         // return an error value? +//         std::list<thread*>::iterator it = std::find(m_threads.begin(), +//                                                     m_threads.end(), thrd); +//         BOOST_ASSERT(it != m_threads.end()); +//         if (it != m_threads.end()) +//             m_threads.erase(it); +//     } + +//     void thread_group::join_all() +//     { +//         mutex::scoped_lock scoped_lock(m_mutex); +//         for (std::list<thread*>::iterator it = m_threads.begin(); +//              it != m_threads.end(); ++it) +//         { +//             (*it)->join(); +//         } +//     } + +//     void thread_group::interrupt_all() +//     { +//         boost::lock_guard<mutex> guard(m_mutex); +             +//         for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end(); +//             it!=end; +//             ++it) +//         { +//             (*it)->interrupt(); +//         } +//     } +         + +//     size_t thread_group::size() const +//     { +//         return m_threads.size(); +//     } + +} diff --git a/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl b/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl new file mode 100644 index 0000000..5ec3b17 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl @@ -0,0 +1,130 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// boostinspect:nounnamed + +namespace { +const int MILLISECONDS_PER_SECOND = 1000; +const int NANOSECONDS_PER_SECOND = 1000000000; +const int NANOSECONDS_PER_MILLISECOND = 1000000; + +const int MICROSECONDS_PER_SECOND = 1000000; +const int NANOSECONDS_PER_MICROSECOND = 1000; + +inline void to_time(int milliseconds, boost::xtime& xt) +{ +    int res = 0; +    res = boost::xtime_get(&xt, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); +    xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * +        NANOSECONDS_PER_MILLISECOND); + +    if (xt.nsec >= NANOSECONDS_PER_SECOND) +    { +        ++xt.sec; +        xt.nsec -= NANOSECONDS_PER_SECOND; +    } +} + +#if defined(BOOST_HAS_PTHREADS) +inline void to_timespec(const boost::xtime& xt, timespec& ts) +{ +    ts.tv_sec = static_cast<int>(xt.sec); +    ts.tv_nsec = static_cast<int>(xt.nsec); +    if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) +    { +        ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; +        ts.tv_nsec %= NANOSECONDS_PER_SECOND; +    } +} + +inline void to_time(int milliseconds, timespec& ts) +{ +    boost::xtime xt; +    to_time(milliseconds, xt); +    to_timespec(xt, ts); +} + +inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +    { +        ts.tv_sec = 0; +        ts.tv_nsec = 0; +    } +    else +    { +        ts.tv_sec = xt.sec - cur.sec; +        ts.tv_nsec = xt.nsec - cur.nsec; + +        if( ts.tv_nsec < 0 ) +        { +            ts.tv_sec -= 1; +            ts.tv_nsec += NANOSECONDS_PER_SECOND; +        } +        if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) +        { +            ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; +            ts.tv_nsec %= NANOSECONDS_PER_SECOND; +        } +    } +} +#endif + +inline void to_duration(boost::xtime xt, int& milliseconds) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +        milliseconds = 0; +    else +    { +        if (cur.nsec > xt.nsec) +        { +            xt.nsec += NANOSECONDS_PER_SECOND; +            --xt.sec; +        } +        milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + +            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / +                NANOSECONDS_PER_MILLISECOND); +    } +} + +inline void to_microduration(boost::xtime xt, int& microseconds) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +        microseconds = 0; +    else +    { +        if (cur.nsec > xt.nsec) +        { +            xt.nsec += NANOSECONDS_PER_SECOND; +            --xt.sec; +        } +        microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) + +            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) / +                NANOSECONDS_PER_MICROSECOND); +    } +} +} + +// Change Log: +//    1 Jun 01  Initial creation. diff --git a/3rdParty/Boost/libs/thread/src/tss_null.cpp b/3rdParty/Boost/libs/thread/src/tss_null.cpp new file mode 100644 index 0000000..ff13b30 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/tss_null.cpp @@ -0,0 +1,34 @@ +// (C) Copyright Michael Glassford 2004. +// (C) Copyright 2007 Anthony Williams +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE)) + +    /* +    This file is a "null" implementation of tss cleanup; it's +    purpose is to to eliminate link errors in cases +    where it is known that tss cleanup is not needed. +    */ + +    extern "C" void tss_cleanup_implemented(void) +    { +        /* +        This function's sole purpose is to cause a link error in cases where +        automatic tss cleanup is not implemented by Boost.Threads as a +        reminder that user code is responsible for calling the necessary +        functions at the appropriate times (and for implementing an a +        tss_cleanup_implemented() function to eliminate the linker's +        missing symbol error). + +        If Boost.Threads later implements automatic tss cleanup in cases +        where it currently doesn't (which is the plan), the duplicate +        symbol error will warn the user that their custom solution is no +        longer needed and can be removed. +        */ +    } + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER) diff --git a/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp b/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp new file mode 100644 index 0000000..8881303 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/exceptions.hpp> +#include <cstring> +#include <string> + +namespace boost { + +thread_exception::thread_exception() +    : m_sys_err(0) +{ +} + +thread_exception::thread_exception(int sys_err_code) +    : m_sys_err(sys_err_code) +{ +} + +thread_exception::~thread_exception() throw() +{ +} + +int thread_exception::native_error() const +{ +    return m_sys_err;  +} + +lock_error::lock_error() +{ +} + +lock_error::lock_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +lock_error::~lock_error() throw() +{ +} + +const char* lock_error::what() const throw() +{ +    return "boost::lock_error"; +} + +thread_resource_error::thread_resource_error() +{ +} + +thread_resource_error::thread_resource_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +thread_resource_error::~thread_resource_error() throw() +{ +} + +const char* thread_resource_error::what() const throw() +{ +    return "boost::thread_resource_error"; +} + +unsupported_thread_option::unsupported_thread_option() +{ +} + +unsupported_thread_option::unsupported_thread_option(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +unsupported_thread_option::~unsupported_thread_option() throw() +{ +} + +const char* unsupported_thread_option::what() const throw() +{ +    return "boost::unsupported_thread_option"; +} + +invalid_thread_argument::invalid_thread_argument() +{ +} + +invalid_thread_argument::invalid_thread_argument(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +invalid_thread_argument::~invalid_thread_argument() throw() +{ +} + +const char* invalid_thread_argument::what() const throw() +{ +    return "boost::invalid_thread_argument"; +} + +thread_permission_error::thread_permission_error() +{ +} + +thread_permission_error::thread_permission_error(int sys_err_code) +    : thread_exception(sys_err_code) +{ +} + +thread_permission_error::~thread_permission_error() throw() +{ +} + +const char* thread_permission_error::what() const throw() +{ +    return "boost::thread_permission_error"; +} + +} // namespace boost diff --git a/3rdParty/Boost/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/libs/thread/src/win32/thread.cpp new file mode 100644 index 0000000..a72f053 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/thread.cpp @@ -0,0 +1,597 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins + +#define _WIN32_WINNT 0x400 +#define WINVER 0x400 + +#include <boost/thread/thread.hpp> +#include <algorithm> +#include <windows.h> +#ifndef UNDER_CE +#include <process.h> +#endif +#include <stdio.h> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#include <boost/assert.hpp> +#include <boost/thread/detail/tss_hooks.hpp> +#include <boost/date_time/posix_time/conversion.hpp> + +namespace boost +{ +    namespace +    { +        boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; +        DWORD current_thread_tls_key=0; + +        void create_current_thread_tls_key() +        { +            tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in +            current_thread_tls_key=TlsAlloc(); +            BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES); +        } + +        void cleanup_tls_key() +        { +            if(current_thread_tls_key) +            { +                TlsFree(current_thread_tls_key); +                current_thread_tls_key=0; +            } +        } + +        detail::thread_data_base* get_current_thread_data() +        { +            if(!current_thread_tls_key) +            { +                return 0; +            } +            return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); +        } + +        void set_current_thread_data(detail::thread_data_base* new_data) +        { +            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); +            BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); +        } + +#ifdef BOOST_NO_THREADEX +// Windows CE doesn't define _beginthreadex + +        struct ThreadProxyData +        { +            typedef unsigned (__stdcall* func)(void*); +            func start_address_; +            void* arglist_; +            ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {} +        }; + +        DWORD WINAPI ThreadProxy(LPVOID args) +        { +            ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args); +            DWORD ret=data->start_address_(data->arglist_); +            delete data; +            return ret; +        } +         +        typedef void* uintptr_t; + +        inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), +                                              void* arglist, unsigned initflag, unsigned* thrdaddr) +        { +            DWORD threadID; +            HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy, +                                        new ThreadProxyData(start_address,arglist),initflag,&threadID); +            if (hthread!=0) +                *thrdaddr=threadID; +            return reinterpret_cast<uintptr_t const>(hthread); +        } + +#endif + +    } + +    namespace detail +    { +        struct thread_exit_callback_node +        { +            boost::detail::thread_exit_function_base* func; +            thread_exit_callback_node* next; + +            thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, +                                      thread_exit_callback_node* next_): +                func(func_),next(next_) +            {} +        }; + +        struct tss_data_node +        { +            void const* key; +            boost::shared_ptr<boost::detail::tss_cleanup_function> func; +            void* value; +            tss_data_node* next; + +            tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_, +                          tss_data_node* next_): +                key(key_),func(func_),value(value_),next(next_) +            {} +        }; + +    } + +    namespace +    { +        void run_thread_exit_callbacks() +        { +            detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); +            if(current_thread_data) +            { +                while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) +                { +                    while(current_thread_data->thread_exit_callbacks) +                    { +                        detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; +                        current_thread_data->thread_exit_callbacks=current_node->next; +                        if(current_node->func) +                        { +                            (*current_node->func)(); +                            boost::detail::heap_delete(current_node->func); +                        } +                        boost::detail::heap_delete(current_node); +                    } +                    while(current_thread_data->tss_data) +                    { +                        detail::tss_data_node* const current_node=current_thread_data->tss_data; +                        current_thread_data->tss_data=current_node->next; +                        if(current_node->func) +                        { +                            (*current_node->func)(current_node->value); +                        } +                        boost::detail::heap_delete(current_node); +                    } +                } +                 +                set_current_thread_data(0); +            } +        } +         +        unsigned __stdcall thread_start_function(void* param) +        { +            detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); +            set_current_thread_data(thread_info); +            try +            { +                thread_info->run(); +            } +            catch(thread_interrupted const&) +            { +            } +// Removed as it stops the debugger identifying the cause of the exception +// Unhandled exceptions still cause the application to terminate +//             catch(...) +//             { +//                 std::terminate(); +//             } +            run_thread_exit_callbacks(); +            return 0; +        } +    } + +    thread::thread() +    {} + +    void thread::start_thread() +    { +        uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); +        if(!new_thread) +        { +            throw thread_resource_error(); +        } +        intrusive_ptr_add_ref(thread_info.get()); +        thread_info->thread_handle=(detail::win32::handle)(new_thread); +        ResumeThread(thread_info->thread_handle); +    } + +    thread::thread(detail::thread_data_ptr data): +        thread_info(data) +    {} + +    namespace +    { +        struct externally_launched_thread: +            detail::thread_data_base +        { +            externally_launched_thread() +            { +                ++count; +                interruption_enabled=false; +            } +             +            void run() +            {} +        private: +            externally_launched_thread(externally_launched_thread&); +            void operator=(externally_launched_thread&); +        }; + +        void make_external_thread_data() +        { +            externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); +            set_current_thread_data(me); +        } + +        detail::thread_data_base* get_or_make_current_thread_data() +        { +            detail::thread_data_base* current_thread_data(get_current_thread_data()); +            if(!current_thread_data) +            { +                make_external_thread_data(); +                current_thread_data=get_current_thread_data(); +            } +            return current_thread_data; +        } +         +    } + +    thread::~thread() +    { +        detach(); +    } +     +    thread::id thread::get_id() const +    { +        return thread::id(get_thread_info()); +    } + +    bool thread::joinable() const +    { +        return get_thread_info(); +    } + +    void thread::join() +    { +        detail::thread_data_ptr local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel()); +            release_handle(); +        } +    } + +    bool thread::timed_join(boost::system_time const& wait_until) +    { +        detail::thread_data_ptr local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until))) +            { +                return false; +            } +            release_handle(); +        } +        return true; +    } +     +    void thread::detach() +    { +        release_handle(); +    } + +    void thread::release_handle() +    { +        lock_guard<mutex> l1(thread_info_mutex); +        thread_info=0; +    } +     +    void thread::interrupt() +    { +        detail::thread_data_ptr local_thread_info=get_thread_info(); +        if(local_thread_info) +        { +            local_thread_info->interrupt(); +        } +    } +     +    bool thread::interruption_requested() const +    { +        detail::thread_data_ptr local_thread_info=get_thread_info(); +        return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); +    } +     +    unsigned thread::hardware_concurrency() +    { +        SYSTEM_INFO info={0}; +        GetSystemInfo(&info); +        return info.dwNumberOfProcessors; +    } +     +    thread::native_handle_type thread::native_handle() +    { +        detail::thread_data_ptr local_thread_info=get_thread_info(); +        return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value; +    } + +    detail::thread_data_ptr thread::get_thread_info() const +    { +        boost::mutex::scoped_lock l(thread_info_mutex); +        return thread_info; +    } + +    namespace this_thread +    { +        namespace +        { +            LARGE_INTEGER get_due_time(detail::timeout const&  target_time) +            { +                LARGE_INTEGER due_time={0}; +                if(target_time.relative) +                { +                    unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start; +                    LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); +                    LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; + +                    if(remaining_milliseconds>0) +                    { +                        due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond); +                    } +                } +                else +                { +                    SYSTEMTIME target_system_time={0}; +                    target_system_time.wYear=target_time.abs_time.date().year(); +                    target_system_time.wMonth=target_time.abs_time.date().month(); +                    target_system_time.wDay=target_time.abs_time.date().day(); +                    target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours(); +                    target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes(); +                    target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds(); + +                    if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time))) +                    { +                        due_time.QuadPart=0; +                    } +                    else +                    { +                        long const hundred_nanoseconds_in_one_second=10000000; +                        due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second()); +                    } +                } +                return due_time; +            } +        } +         + +        bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) +        { +            detail::win32::handle handles[3]={0}; +            unsigned handle_count=0; +            unsigned wait_handle_index=~0U; +            unsigned interruption_index=~0U; +            unsigned timeout_index=~0U; +            if(handle_to_wait_for!=detail::win32::invalid_handle_value) +            { +                wait_handle_index=handle_count; +                handles[handle_count++]=handle_to_wait_for; +            } +            if(get_current_thread_data() && get_current_thread_data()->interruption_enabled) +            { +                interruption_index=handle_count; +                handles[handle_count++]=get_current_thread_data()->interruption_handle; +            } + +            detail::win32::handle_manager timer_handle; +             +#ifndef UNDER_CE +            unsigned const min_timer_wait_period=20; +             +            if(!target_time.is_sentinel()) +            { +                detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); +                if(time_left.milliseconds > min_timer_wait_period) +                { +                    // for a long-enough timeout, use a waitable timer (which tracks clock changes) +                    timer_handle=CreateWaitableTimer(NULL,false,NULL); +                    if(timer_handle!=0) +                    { +                        LARGE_INTEGER due_time=get_due_time(target_time); +                         +                        bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; +                        if(set_time_succeeded) +                        { +                            timeout_index=handle_count; +                            handles[handle_count++]=timer_handle; +                        } +                    } +                } +                else if(!target_time.relative) +                { +                    // convert short absolute-time timeouts into relative ones, so we don't race against clock changes +                    target_time=detail::timeout(time_left.milliseconds); +                } +            } +#endif +         +            bool const using_timer=timeout_index!=~0u; +            detail::timeout::remaining_time time_left(0); +             +            do +            { +                if(!using_timer) +                { +                    time_left=target_time.remaining_milliseconds(); +                } +                 +                if(handle_count) +                { +                    unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); +                    if(notified_index<handle_count) +                    { +                        if(notified_index==wait_handle_index) +                        { +                            return true; +                        } +                        else if(notified_index==interruption_index) +                        { +                            detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); +                            throw thread_interrupted(); +                        } +                        else if(notified_index==timeout_index) +                        { +                            return false; +                        } +                    } +                } +                else +                { +                    detail::win32::Sleep(time_left.milliseconds); +                } +                if(target_time.relative) +                { +                    target_time.milliseconds-=detail::timeout::max_non_infinite_wait; +                } +            } +            while(time_left.more); +            return false; +        } + +        thread::id get_id() +        { +            return thread::id(get_or_make_current_thread_data()); +        } + +        void interruption_point() +        { +            if(interruption_enabled() && interruption_requested()) +            { +                detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); +                throw thread_interrupted(); +            } +        } +         +        bool interruption_enabled() +        { +            return get_current_thread_data() && get_current_thread_data()->interruption_enabled; +        } +         +        bool interruption_requested() +        { +            return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); +        } + +        void yield() +        { +            detail::win32::Sleep(0); +        } +         +        disable_interruption::disable_interruption(): +            interruption_was_enabled(interruption_enabled()) +        { +            if(interruption_was_enabled) +            { +                get_current_thread_data()->interruption_enabled=false; +            } +        } +         +        disable_interruption::~disable_interruption() +        { +            if(get_current_thread_data()) +            { +                get_current_thread_data()->interruption_enabled=interruption_was_enabled; +            } +        } + +        restore_interruption::restore_interruption(disable_interruption& d) +        { +            if(d.interruption_was_enabled) +            { +                get_current_thread_data()->interruption_enabled=true; +            } +        } +         +        restore_interruption::~restore_interruption() +        { +            if(get_current_thread_data()) +            { +                get_current_thread_data()->interruption_enabled=false; +            } +        } +    } + +    namespace detail +    { +        void add_thread_exit_function(thread_exit_function_base* func) +        { +            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); +            thread_exit_callback_node* const new_node= +                heap_new<thread_exit_callback_node>(func, +                                                    current_thread_data->thread_exit_callbacks); +            current_thread_data->thread_exit_callbacks=new_node; +        } + +        tss_data_node* find_tss_data(void const* key) +        { +            detail::thread_data_base* const current_thread_data(get_current_thread_data()); +            if(current_thread_data) +            { +                detail::tss_data_node* current_node=current_thread_data->tss_data; +                while(current_node) +                { +                    if(current_node->key==key) +                    { +                        return current_node; +                    } +                    current_node=current_node->next; +                } +            } +            return NULL; +        } + +        void* get_tss_data(void const* key) +        { +            if(tss_data_node* const current_node=find_tss_data(key)) +            { +                return current_node->value; +            } +            return NULL; +        } +         +        void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing) +        { +            if(tss_data_node* const current_node=find_tss_data(key)) +            { +                if(cleanup_existing && current_node->func.get()) +                { +                    (*current_node->func)(current_node->value); +                } +                current_node->func=func; +                current_node->value=tss_data; +            } +            else +            { +                detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); +                tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data); +                current_thread_data->tss_data=new_node; +            } +        } +    } +} + + +extern "C" BOOST_THREAD_DECL void on_process_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_thread_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_process_exit() +{ +    boost::cleanup_tls_key(); +} + +extern "C" BOOST_THREAD_DECL void on_thread_exit() +{ +    boost::run_thread_exit_callbacks(); +} + diff --git a/3rdParty/Boost/libs/thread/src/win32/timeconv.inl b/3rdParty/Boost/libs/thread/src/win32/timeconv.inl new file mode 100644 index 0000000..5ec3b17 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/timeconv.inl @@ -0,0 +1,130 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +//  Distributed under the Boost Software License, Version 1.0. (See accompanying  +//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// boostinspect:nounnamed + +namespace { +const int MILLISECONDS_PER_SECOND = 1000; +const int NANOSECONDS_PER_SECOND = 1000000000; +const int NANOSECONDS_PER_MILLISECOND = 1000000; + +const int MICROSECONDS_PER_SECOND = 1000000; +const int NANOSECONDS_PER_MICROSECOND = 1000; + +inline void to_time(int milliseconds, boost::xtime& xt) +{ +    int res = 0; +    res = boost::xtime_get(&xt, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); +    xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * +        NANOSECONDS_PER_MILLISECOND); + +    if (xt.nsec >= NANOSECONDS_PER_SECOND) +    { +        ++xt.sec; +        xt.nsec -= NANOSECONDS_PER_SECOND; +    } +} + +#if defined(BOOST_HAS_PTHREADS) +inline void to_timespec(const boost::xtime& xt, timespec& ts) +{ +    ts.tv_sec = static_cast<int>(xt.sec); +    ts.tv_nsec = static_cast<int>(xt.nsec); +    if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) +    { +        ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; +        ts.tv_nsec %= NANOSECONDS_PER_SECOND; +    } +} + +inline void to_time(int milliseconds, timespec& ts) +{ +    boost::xtime xt; +    to_time(milliseconds, xt); +    to_timespec(xt, ts); +} + +inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +    { +        ts.tv_sec = 0; +        ts.tv_nsec = 0; +    } +    else +    { +        ts.tv_sec = xt.sec - cur.sec; +        ts.tv_nsec = xt.nsec - cur.nsec; + +        if( ts.tv_nsec < 0 ) +        { +            ts.tv_sec -= 1; +            ts.tv_nsec += NANOSECONDS_PER_SECOND; +        } +        if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) +        { +            ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; +            ts.tv_nsec %= NANOSECONDS_PER_SECOND; +        } +    } +} +#endif + +inline void to_duration(boost::xtime xt, int& milliseconds) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +        milliseconds = 0; +    else +    { +        if (cur.nsec > xt.nsec) +        { +            xt.nsec += NANOSECONDS_PER_SECOND; +            --xt.sec; +        } +        milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + +            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / +                NANOSECONDS_PER_MILLISECOND); +    } +} + +inline void to_microduration(boost::xtime xt, int& microseconds) +{ +    boost::xtime cur; +    int res = 0; +    res = boost::xtime_get(&cur, boost::TIME_UTC); +    assert(res == boost::TIME_UTC); + +    if (boost::xtime_cmp(xt, cur) <= 0) +        microseconds = 0; +    else +    { +        if (cur.nsec > xt.nsec) +        { +            xt.nsec += NANOSECONDS_PER_SECOND; +            --xt.sec; +        } +        microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) + +            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) / +                NANOSECONDS_PER_MICROSECOND); +    } +} +} + +// Change Log: +//    1 Jun 01  Initial creation. diff --git a/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp b/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp new file mode 100644 index 0000000..0522a12 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp @@ -0,0 +1,72 @@ +// (C) Copyright Michael Glassford 2004. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) + +    #include <boost/thread/detail/tss_hooks.hpp> + +    #define WIN32_LEAN_AND_MEAN +    #include <windows.h> + +    #if defined(__BORLANDC__) +        extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) +    #elif defined(_WIN32_WCE) +        extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) +    #else +        extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) +    #endif +    { +        switch(dwReason) +        { +            case DLL_PROCESS_ATTACH: +            { +                on_process_enter(); +                on_thread_enter(); +                break; +            } + +            case DLL_THREAD_ATTACH: +            { +                on_thread_enter(); +                break; +            } + +            case DLL_THREAD_DETACH: +            { +                on_thread_exit(); +                break; +            } + +            case DLL_PROCESS_DETACH: +            { +                on_thread_exit(); +                on_process_exit(); +                break; +            } +        } + +        return TRUE; +    } + +    extern "C" void tss_cleanup_implemented(void) +    { +        /* +        This function's sole purpose is to cause a link error in cases where +        automatic tss cleanup is not implemented by Boost.Threads as a +        reminder that user code is responsible for calling the necessary +        functions at the appropriate times (and for implementing an a +        tss_cleanup_implemented() function to eliminate the linker's +        missing symbol error). + +        If Boost.Threads later implements automatic tss cleanup in cases +        where it currently doesn't (which is the plan), the duplicate +        symbol error will warn the user that their custom solution is no +        longer needed and can be removed. +        */ +    } + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) diff --git a/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp b/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp new file mode 100644 index 0000000..ae89bc4 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp @@ -0,0 +1,287 @@ +// $Id: tss_pe.cpp 49324 2008-10-13 20:30:13Z anthonyw $ +// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. +// (C) Copyright 2007 Roland Schwarz +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)  + +#if defined(__MINGW32__) && !defined(_WIN64) + +#include <boost/thread/detail/tss_hooks.hpp> + +#include <windows.h> + +#include <cstdlib> + +extern "C" void tss_cleanup_implemented(void) {} + +namespace { +    void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv) +    { +        switch (dwReason) +        { +        case DLL_THREAD_DETACH: +        { +            on_thread_exit(); +            break; +        } +        } +    } + +    void on_after_ctors(void) +    { +        on_process_enter(); +    } +     +    void on_before_dtors(void) +    { +        on_thread_exit(); +    } +     +    void on_after_dtors(void) +    { +        on_process_exit();         +    } +} + +extern "C" { + +    void (* after_ctors )(void) __attribute__((section(".ctors")))     = on_after_ctors; +    void (* before_dtors)(void) __attribute__((section(".dtors")))     = on_before_dtors; +    void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors; + +    ULONG __tls_index__ = 0; +    char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; +    char __tls_start__ __attribute__((section(".tls"))) = 0; + + +    PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; +    PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; +    PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; +} + +extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = +{ +        (DWORD) &__tls_start__, +        (DWORD) &__tls_end__, +        (DWORD) &__tls_index__, +        (DWORD) (&__crt_xl_start__+1), +        (DWORD) 0, +        (DWORD) 0 +}; + + +#elif  defined(_MSC_VER) && !defined(UNDER_CE) + +    #include <boost/thread/detail/tss_hooks.hpp> + +    #include <stdlib.h> + +    #define WIN32_LEAN_AND_MEAN +    #include <windows.h> + +    //Definitions required by implementation + +    #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 +        typedef void (__cdecl *_PVFV)(void); +        #define INIRETSUCCESS +        #define PVAPI void +    #else +        typedef int (__cdecl *_PVFV)(void); +        #define INIRETSUCCESS 0 +        #define PVAPI int +    #endif + +    typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); + +    //Symbols for connection to the runtime environment + +    extern "C" +    { +        extern DWORD _tls_used; //the tls directory (located in .rdata segment) +        extern _TLSCB __xl_a[], __xl_z[];    //tls initializers */ +    } + +    namespace +    { +        //Forward declarations + +        static PVAPI on_tls_prepare(void); +        static PVAPI on_process_init(void); +        static PVAPI on_process_term(void); +        static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); + +        //The .CRT$Xxx information is taken from Codeguru: +        //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ + +#if (_MSC_VER >= 1400) +#pragma section(".CRT$XIU",long,read) +#pragma section(".CRT$XCU",long,read) +#pragma section(".CRT$XTU",long,read) +#pragma section(".CRT$XLC",long,read) +        __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; +        __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; +        __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; +        __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; +#else +        #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +        #   pragma data_seg(push, old_seg) +        #endif +            //Callback to run tls glue code first. +            //I don't think it is necessary to run it +            //at .CRT$XIB level, since we are only +            //interested in thread detachement. But +            //this could be changed easily if required. + +            #pragma data_seg(".CRT$XIU") +            static _PVFV p_tls_prepare = on_tls_prepare; +            #pragma data_seg() + +            //Callback after all global ctors. + +            #pragma data_seg(".CRT$XCU") +            static _PVFV p_process_init = on_process_init; +            #pragma data_seg() + +            //Callback for tls notifications. + +            #pragma data_seg(".CRT$XLB") +            _TLSCB p_thread_callback = on_tls_callback; +            #pragma data_seg() +            //Callback for termination. + +            #pragma data_seg(".CRT$XTU") +            static _PVFV p_process_term = on_process_term; +            #pragma data_seg() +        #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +        #   pragma data_seg(pop, old_seg) +        #endif +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4189) +#endif + +        PVAPI on_tls_prepare(void) +        { +            //The following line has an important side effect: +            //if the TLS directory is not already there, it will +            //be created by the linker. In other words, it forces a tls +            //directory to be generated by the linker even when static tls +            //(i.e. __declspec(thread)) is not used. +            //The volatile should prevent the optimizer +            //from removing the reference. + +            DWORD volatile dw = _tls_used; + +            #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 +                _TLSCB* pfbegin = __xl_a; +                _TLSCB* pfend = __xl_z; +                _TLSCB* pfdst = pfbegin; +                //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; + +                //The following loop will merge the address pointers +                //into a contiguous area, since the tlssup code seems +                //to require this (at least on MSVC 6) + +                while (pfbegin < pfend) +                { +                    if (*pfbegin != 0) +                    { +                        *pfdst = *pfbegin; +                        ++pfdst; +                    } +                    ++pfbegin; +                } + +                *pfdst = 0; +            #endif + +            return INIRETSUCCESS; +        } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +        PVAPI on_process_init(void) +        { +            //Schedule on_thread_exit() to be called for the main +            //thread before destructors of global objects have been +            //called. + +            //It will not be run when 'quick' exiting the +            //library; however, this is the standard behaviour +            //for destructors of global objects, so that +            //shouldn't be a problem. + +            atexit(on_thread_exit); + +            //Call Boost process entry callback here + +            on_process_enter(); + +            return INIRETSUCCESS; +        } + +        PVAPI on_process_term(void) +        { +            on_process_exit(); +            return INIRETSUCCESS; +        } + +        void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) +        { +            switch (dwReason) +            { +            case DLL_THREAD_DETACH: +                on_thread_exit(); +                break; +            } +        } + +        BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID) +        { +            switch (dwReason) +            { +            case DLL_THREAD_DETACH: +                on_thread_exit(); +                break; +            case DLL_PROCESS_DETACH: +                on_process_exit(); +                break; +            } +            return true; +        } +    } //namespace + +extern "C" +{ +    extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback; +} + +    extern "C" void tss_cleanup_implemented(void) +    { +        /* +        This function's sole purpose is to cause a link error in cases where +        automatic tss cleanup is not implemented by Boost.Threads as a +        reminder that user code is responsible for calling the necessary +        functions at the appropriate times (and for implementing an a +        tss_cleanup_implemented() function to eliminate the linker's +        missing symbol error). + +        If Boost.Threads later implements automatic tss cleanup in cases +        where it currently doesn't (which is the plan), the duplicate +        symbol error will warn the user that their custom solution is no +        longer needed and can be removed. +        */ +    } +#endif //defined(_MSC_VER) && !defined(UNDER_CE) + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) | 
 Swift
 Swift