summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-06-01 08:48:42 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-06-01 09:24:28 (GMT)
commit2812bddd81f8a1b804c7460f4e14cd0aa393d129 (patch)
treed46294f35150c4f0f43deaf2d31fceaf945ae715 /3rdParty/Boost/libs/thread
downloadswift-contrib-2812bddd81f8a1b804c7460f4e14cd0aa393d129.zip
swift-contrib-2812bddd81f8a1b804c7460f4e14cd0aa393d129.tar.bz2
Import.
Diffstat (limited to '3rdParty/Boost/libs/thread')
-rw-r--r--3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp124
-rw-r--r--3rdParty/Boost/libs/thread/src/pthread/once.cpp51
-rw-r--r--3rdParty/Boost/libs/thread/src/pthread/thread.cpp678
-rw-r--r--3rdParty/Boost/libs/thread/src/pthread/timeconv.inl130
-rw-r--r--3rdParty/Boost/libs/thread/src/tss_null.cpp34
-rw-r--r--3rdParty/Boost/libs/thread/src/win32/exceptions.cpp124
-rw-r--r--3rdParty/Boost/libs/thread/src/win32/thread.cpp597
-rw-r--r--3rdParty/Boost/libs/thread/src/win32/timeconv.inl130
-rw-r--r--3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp72
-rw-r--r--3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp287
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(&current_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)