diff options
Diffstat (limited to '3rdParty/Boost/src/libs/thread')
-rw-r--r--[-rwxr-xr-x] | 3rdParty/Boost/src/libs/thread/src/future.cpp | 13 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/pthread/once.cpp | 14 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp | 90 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp | 339 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl | 21 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/win32/thread.cpp | 305 | ||||
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp | 43 |
7 files changed, 638 insertions, 187 deletions
diff --git a/3rdParty/Boost/src/libs/thread/src/future.cpp b/3rdParty/Boost/src/libs/thread/src/future.cpp index 33980f5..0b990c1 100755..100644 --- a/3rdParty/Boost/src/libs/thread/src/future.cpp +++ b/3rdParty/Boost/src/libs/thread/src/future.cpp @@ -7,7 +7,8 @@ #ifndef BOOST_NO_EXCEPTIONS -#include <boost/thread/future.hpp> +#include <boost/thread/future_error_code.hpp> +#include <string> namespace boost { @@ -19,12 +20,12 @@ namespace boost public boost::system::error_category { public: - virtual const char* name() const; //BOOST_NOEXCEPT; + virtual const char* name() const BOOST_NOEXCEPT; virtual std::string message(int ev) const; }; const char* - future_error_category::name() const //BOOST_NOEXCEPT + future_error_category::name() const BOOST_NOEXCEPT { return "future"; } @@ -48,14 +49,16 @@ namespace boost } return std::string("unspecified future_errc value\n"); } + future_error_category future_error_category_var; } + BOOST_THREAD_DECL const system::error_category& future_category() BOOST_NOEXCEPT { - static thread_detail::future_error_category f; - return f; + return thread_detail::future_error_category_var; } } #endif + diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp index d5fd656..2cfe7cd 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp @@ -3,18 +3,24 @@ // 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> +#ifdef BOOST_THREAD_ONCE_ATOMIC +#include "./once_atomic.cpp" +#else #define __STDC_CONSTANT_MACROS +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> #include <boost/thread/once.hpp> #include <boost/assert.hpp> +#include <boost/throw_exception.hpp> #include <pthread.h> #include <stdlib.h> #include <memory> namespace boost { - namespace detail + namespace thread_detail { - BOOST_THREAD_DECL thread_detail::uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; @@ -55,13 +61,14 @@ namespace boost #endif } - thread_detail::uintmax_atomic_t& get_once_per_thread_epoch() + uintmax_atomic_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(thread_detail::uintmax_atomic_t)); + if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; } @@ -70,3 +77,4 @@ namespace boost } } +#endif // diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp new file mode 100644 index 0000000..b7ee1dc --- /dev/null +++ b/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp @@ -0,0 +1,90 @@ +// (C) Copyright 2013 Andrey Semashev +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// 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/detail/config.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/atomic.hpp> +#include <boost/memory_order.hpp> +#include <pthread.h> + +namespace boost +{ + namespace thread_detail + { + + enum flag_states + { + uninitialized, in_progress, initialized + }; + + +#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11 + BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type) == sizeof(atomic_type), "Boost.Thread: unsupported platform"); +#endif + + static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + if (f.load(memory_order_acquire) != initialized) + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + if (f.load(memory_order_acquire) != initialized) + { + while (true) + { + atomic_int_type expected = uninitialized; + if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire)) + { + // We have set the flag to in_progress + return true; + } + else if (expected == initialized) + { + // Another thread managed to complete the initialization + return false; + } + else + { + // Wait until the initialization is complete + //pthread::pthread_mutex_scoped_lock lk(&once_mutex); + BOOST_VERIFY(!pthread_cond_wait(&once_cv, &once_mutex)); + } + } + } + } + return false; + } + + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(initialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(uninitialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + } // namespace thread_detail + +} // namespace boost diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp index c83eac1..f218fa8 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp @@ -1,20 +1,22 @@ // Copyright (C) 2001-2003 // William E. Kempf // Copyright (C) 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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/thread_only.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/thread/condition_variable.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/once.hpp> #include <boost/thread/tss.hpp> -#include <boost/throw_exception.hpp> +#include <boost/thread/future.hpp> #ifdef __GLIBC__ #include <sys/sysinfo.h> @@ -25,6 +27,15 @@ #include <unistd.h> #endif +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/lexical_cast.hpp> + +#include <fstream> +#include <string> +#include <set> +#include <vector> + #include "./timeconv.inl" #pragma GCC diagnostic ignored "-Wreturn-type" @@ -35,14 +46,17 @@ namespace boost { thread_data_base::~thread_data_base() { - { for (notify_list_t::iterator i = notify.begin(), e = notify.end(); i != e; ++i) { i->second->unlock(); i->first->notify_all(); } - } + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->make_ready(); + } } struct thread_exit_callback_node @@ -74,6 +88,7 @@ namespace boost { while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks) { + while(thread_info->thread_exit_callbacks) { detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; @@ -99,7 +114,10 @@ namespace boost thread_info->tss_data.erase(current); } } - thread_info->self.reset(); + if (thread_info) // fixme: should we test this? + { + thread_info->self.reset(); + } } } } @@ -150,38 +168,54 @@ namespace boost 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()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_TRY { +#endif thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } BOOST_CATCH (thread_interrupted const&) { } - BOOST_CATCH_END // Removed as it stops the debugger identifying the cause of the exception // Unhandled exceptions still cause the application to terminate // BOOST_CATCH(...) // { +// throw; +// // std::terminate(); // } - + BOOST_CATCH_END +#endif 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; } } - + } + namespace detail + { struct externally_launched_thread: detail::thread_data_base { externally_launched_thread() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interrupt_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); } - void run() {} void notify_all_at_thread_exit(condition_variable*, mutex*) @@ -192,18 +226,18 @@ namespace boost void operator=(externally_launched_thread&); }; - detail::thread_data_base* make_external_thread_data() + thread_data_base* make_external_thread_data() { - detail::thread_data_base* const me(new externally_launched_thread()); + thread_data_base* const me(detail::heap_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() + thread_data_base* get_or_make_current_thread_data() { - detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + thread_data_base* current_thread_data(get_current_thread_data()); if(!current_thread_data) { current_thread_data=make_external_thread_data(); @@ -217,18 +251,20 @@ namespace boost thread::thread() BOOST_NOEXCEPT {} - void thread::start_thread() + bool thread::start_thread_noexcept() { 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(); - boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } + return true; } - void thread::start_thread(const attributes& attr) + bool thread::start_thread_noexcept(const attributes& attr) { thread_info->self=thread_info; const attributes::native_handle_type* h = attr.native_handle(); @@ -236,14 +272,16 @@ namespace boost if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } int detached_state; res = pthread_attr_getdetachstate(h, &detached_state); if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_attr_getdetachstate")); } if (PTHREAD_CREATE_DETACHED==detached_state) { @@ -261,6 +299,7 @@ namespace boost } } } + return true; } @@ -270,12 +309,8 @@ namespace boost return thread_info; } - void thread::join() + bool thread::join_noexcept() { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -314,21 +349,16 @@ namespace boost { thread_info.reset(); } + return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } - bool thread::do_try_join_until(struct timespec const &timeout) + bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -338,9 +368,10 @@ namespace boost unique_lock<mutex> lock(local_thread_info->data_mutex); while(!local_thread_info->done) { - if(!local_thread_info->done_condition.do_timed_wait(lock,timeout)) + if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) { - return false; + res=false; + return true; } } do_join=!local_thread_info->join_started; @@ -370,19 +401,18 @@ namespace boost { thread_info.reset(); } + res=true; return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)(); + return (get_thread_info)()?true:false; } @@ -405,61 +435,121 @@ namespace boost namespace this_thread { + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) + { -#ifdef __DECXXX - /// Workaround of DECCXX issue of incorrect template substitution - template<> -#endif - void sleep(const system_time& st) + if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero())) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + # if defined(__IBMCPP__) || defined(_AIX) + BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts))); + # else + BOOST_VERIFY(!pthread_delay_np(&ts)); + # endif + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_for(lock, ts); + # endif + } + } + + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + timespec now = boost::detail::timespec_now(); + if (boost::detail::timespec_gt(ts, now)) + { + for (int foo=0; foo < 5; ++foo) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec d = boost::detail::timespec_minus(ts, now); + BOOST_VERIFY(!pthread_delay_np(&d)); + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + timespec d = boost::detail::timespec_minus(ts, now); + nanosleep(&d, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_until(lock, ts); + # endif + timespec now2 = boost::detail::timespec_now(); + if (boost::detail::timespec_ge(now2, ts)) + { + return; + } + } + } + } + + } + } + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) { - detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + boost::detail::thread_data_base* const thread_info=boost::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)) {} + unique_lock<mutex> lk(thread_info->sleep_mutex); + while( thread_info->sleep_condition.do_wait_for(lk,ts)) {} } else { - xtime const xt=get_xtime(st); + boost::this_thread::no_interruption_point::hiden::sleep_for(ts); + } + } - 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); + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); - // 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; - } + if(thread_info) + { + unique_lock<mutex> lk(thread_info->sleep_mutex); + while(thread_info->sleep_condition.do_wait_until(lk,ts)) {} + } + else + { + boost::this_thread::no_interruption_point::hiden::sleep_until(ts); } } + } // hiden + } // this_thread + namespace this_thread + { void yield() BOOST_NOEXCEPT { # if defined(BOOST_HAS_SCHED_YIELD) BOOST_VERIFY(!sched_yield()); # elif defined(BOOST_HAS_PTHREAD_YIELD) BOOST_VERIFY(!pthread_yield()); +//# elif defined BOOST_THREAD_USES_DATETIME +// xtime xt; +// xtime_get(&xt, TIME_UTC_); +// sleep(xt); +// sleep_for(chrono::milliseconds(0)); # else - xtime xt; - xtime_get(&xt, TIME_UTC_); - sleep(xt); +#error + timespec ts; + ts.tv_sec= 0; + ts.tv_nsec= 0; + hiden::sleep_for(ts); # endif } } @@ -481,24 +571,65 @@ namespace boost #endif } - thread::id thread::get_id() const BOOST_NOEXCEPT + unsigned thread::physical_concurrency() BOOST_NOEXCEPT { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - //return local_thread_info->thread_handle; - return const_cast<thread*>(this)->native_handle(); - #else - detail::thread_data_ptr const local_thread_info=(get_thread_info)(); - if(local_thread_info) - { - return id(local_thread_info); - } - else - { - return id(); +#ifdef __linux__ + try { + using namespace std; + + ifstream proc_cpuinfo ("/proc/cpuinfo"); + + const string physical_id("physical id"), core_id("core id"); + + typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id] + + std::set<core_entry> cores; + + core_entry current_core_entry; + + string line; + while ( getline(proc_cpuinfo, line) ) { + if (line.empty()) + continue; + + vector<string> key_val(2); + boost::split(key_val, line, boost::is_any_of(":")); + + if (key_val.size() != 2) + return hardware_concurrency(); + + string key = key_val[0]; + string value = key_val[1]; + boost::trim(key); + boost::trim(value); + + if (key == physical_id) { + current_core_entry.first = boost::lexical_cast<unsigned>(value); + continue; + } + + if (key == core_id) { + current_core_entry.second = boost::lexical_cast<unsigned>(value); + cores.insert(current_core_entry); + continue; + } + } + // Fall back to hardware_concurrency() in case + // /proc/cpuinfo is formatted differently than we expect. + return cores.size() != 0 ? cores.size() : hardware_concurrency(); + } catch(...) { + return hardware_concurrency(); } - #endif +#elif defined(__APPLE__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count; +#else + return hardware_concurrency(); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void thread::interrupt() { detail::thread_data_ptr const local_thread_info=(get_thread_info)(); @@ -527,6 +658,7 @@ namespace boost return false; } } +#endif thread::native_handle_type thread::native_handle() { @@ -544,18 +676,9 @@ namespace boost +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS namespace this_thread { - thread::id get_id() BOOST_NOEXCEPT - { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - return pthread_self(); - #else - 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()); - #endif - } - void interruption_point() { #ifndef BOOST_NO_EXCEPTIONS @@ -625,6 +748,7 @@ namespace boost } } } +#endif namespace detail { @@ -632,7 +756,7 @@ namespace boost { 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); + heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks); current_thread_data->thread_exit_callbacks=new_node; } @@ -670,8 +794,11 @@ namespace boost void erase_tss_node(void const* key) { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - current_thread_data->tss_data.erase(key); + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->tss_data.erase(key); + } } void set_tss_data(void const* key, @@ -700,6 +827,7 @@ namespace boost } } } + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) { detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); @@ -708,6 +836,17 @@ namespace boost current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); } } +namespace detail { + + void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->make_ready_at_thread_exit(as); + } + } +} diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl index cab7c55..d81f31b 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl +++ b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl @@ -17,6 +17,7 @@ const int NANOSECONDS_PER_MILLISECOND = 1000000; const int MICROSECONDS_PER_SECOND = 1000000; const int NANOSECONDS_PER_MICROSECOND = 1000; +#if defined BOOST_THREAD_USES_DATETIME inline void to_time(int milliseconds, boost::xtime& xt) { int res = 0; @@ -33,7 +34,9 @@ inline void to_time(int milliseconds, boost::xtime& xt) xt.nsec -= NANOSECONDS_PER_SECOND; } } +#endif #if defined(BOOST_HAS_PTHREADS) +#if defined BOOST_THREAD_USES_DATETIME inline void to_timespec(const boost::xtime& xt, timespec& ts) { ts.tv_sec = static_cast<int>(xt.sec); @@ -44,14 +47,27 @@ inline void to_timespec(const boost::xtime& xt, timespec& ts) ts.tv_nsec %= NANOSECONDS_PER_SECOND; } } - +#endif inline void to_time(int milliseconds, timespec& ts) { +#if defined BOOST_THREAD_USES_DATETIME boost::xtime xt; to_time(milliseconds, xt); to_timespec(xt, ts); +#else + ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND); + ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND); + + if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ++ts.tv_sec; + ts.tv_nsec -= NANOSECONDS_PER_SECOND; + } +#endif } +#if defined BOOST_THREAD_USES_DATETIME inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) { boost::xtime cur; @@ -82,7 +98,9 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) } } #endif +#endif +#if defined BOOST_THREAD_USES_DATETIME inline void to_duration(boost::xtime xt, int& milliseconds) { boost::xtime cur; @@ -126,6 +144,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds) NANOSECONDS_PER_MICROSECOND); } } +#endif } // Change Log: diff --git a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp index 5a26f5e..54ebbf3 100644 --- a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp @@ -3,6 +3,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 David Deakins +// (C) Copyright 2011-2013 Vicente J. Botet Escriba #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 @@ -11,17 +12,20 @@ #ifndef WINVER #define WINVER 0x400 #endif +//#define BOOST_THREAD_VERSION 3 -#include <boost/thread/thread.hpp> +#include <boost/thread/thread_only.hpp> #include <boost/thread/once.hpp> #include <boost/thread/tss.hpp> #include <boost/thread/condition_variable.hpp> #include <boost/thread/detail/tss_hooks.hpp> +#include <boost/thread/future.hpp> #include <boost/assert.hpp> -#include <boost/throw_exception.hpp> +#include <boost/cstdint.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/date_time/posix_time/conversion.hpp> - +#endif #include <memory> #include <algorithm> #ifndef UNDER_CE @@ -36,16 +40,20 @@ namespace boost { thread_data_base::~thread_data_base() { - { for (notify_list_t::iterator i = notify.begin(), e = notify.end(); i != e; ++i) { i->second->unlock(); i->first->notify_all(); } - } + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->make_ready(); + } } } + namespace { #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 @@ -75,24 +83,34 @@ namespace boost } } - detail::thread_data_base* get_current_thread_data() - { - if(current_thread_tls_key==TLS_OUT_OF_INDEXES) - { - 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); - if(current_thread_tls_key!=TLS_OUT_OF_INDEXES) + if (current_thread_tls_key!=TLS_OUT_OF_INDEXES) + { BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); + } else - boost::throw_exception(thread_resource_error()); + { + BOOST_VERIFY(false); + //boost::throw_exception(thread_resource_error()); + } } + } + namespace detail + { + thread_data_base* get_current_thread_data() + { + if(current_thread_tls_key==TLS_OUT_OF_INDEXES) + { + return 0; + } + return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); + } + } + namespace + { #ifndef BOOST_HAS_THREADEX // Windows CE doesn't define _beginthreadex @@ -111,7 +129,7 @@ namespace boost return ret; } - typedef void* uintptr_t; + //typedef void* uintptr_t; inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), void* arglist, unsigned initflag, unsigned* thrdaddr) @@ -151,7 +169,7 @@ namespace boost { void run_thread_exit_callbacks() { - detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); + detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false); if(current_thread_data) { while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks) @@ -190,23 +208,24 @@ namespace boost { detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); set_current_thread_data(thread_info); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_TRY { +#endif thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS } -#ifndef BOOST_NO_EXCEPTIONS - catch(thread_interrupted const&) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(thread_interrupted const&) { } -#endif // Removed as it stops the debugger identifying the cause of the exception // Unhandled exceptions still cause the application to terminate -// catch(...) // BOOST_NO_EXCEPTIONS protected +// BOOST_CATCH(...) // { // std::terminate(); // } + BOOST_CATCH_END +#endif run_thread_exit_callbacks(); return 0; } @@ -215,29 +234,33 @@ namespace boost thread::thread() BOOST_NOEXCEPT {} - void thread::start_thread() + bool thread::start_thread_noexcept() { uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error()); } intrusive_ptr_add_ref(thread_info.get()); thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); + return true; } - void thread::start_thread(const attributes& attr) + bool thread::start_thread_noexcept(const attributes& attr) { //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error()); } intrusive_ptr_add_ref(thread_info.get()); thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); + return true; } thread::thread(detail::thread_data_ptr data): @@ -252,7 +275,15 @@ namespace boost externally_launched_thread() { ++count; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interruption_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); } void run() @@ -268,28 +299,25 @@ namespace boost void make_external_thread_data() { externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { set_current_thread_data(me); } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { detail::heap_delete(me); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } detail::thread_data_base* get_or_make_current_thread_data() { - detail::thread_data_base* current_thread_data(get_current_thread_data()); + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); if(!current_thread_data) { make_external_thread_data(); - current_thread_data=get_current_thread_data(); + current_thread_data=detail::get_current_thread_data(); } return current_thread_data; } @@ -309,54 +337,47 @@ namespace boost bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)(); + return (get_thread_info)() ? true : false; } - void thread::join() + bool thread::join_noexcept() { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } + 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(); + return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } +#if defined BOOST_THREAD_USES_DATETIME bool thread::timed_join(boost::system_time const& wait_until) { return do_try_join_until(get_milliseconds_until(wait_until)); } - - bool thread::do_try_join_until(uintmax_t milli) +#endif + bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli)) { - return false; + res=false; + return true; } release_handle(); + res=true; return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } @@ -370,6 +391,7 @@ namespace boost thread_info=0; } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void thread::interrupt() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -385,13 +407,40 @@ namespace boost return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); } +#endif + unsigned thread::hardware_concurrency() BOOST_NOEXCEPT { - SYSTEM_INFO info={{0}}; + //SYSTEM_INFO info={{0}}; + SYSTEM_INFO info; GetSystemInfo(&info); return info.dwNumberOfProcessors; } + unsigned thread::physical_concurrency() BOOST_NOEXCEPT + { + unsigned cores = 0; +#if !(defined(__MINGW32__) || defined (__MINGW64__)) + DWORD size = 0; + + GetLogicalProcessorInformation(NULL, &size); + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + return 0; + + std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(size); + if (GetLogicalProcessorInformation(&buffer.front(), &size) == FALSE) + return 0; + + const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + + for (size_t i = 0; i < Elements; ++i) { + if (buffer[i].Relationship == RelationProcessorCore) + ++cores; + } +#endif + return cores; + } + thread::native_handle_type thread::native_handle() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -409,10 +458,10 @@ namespace boost { LARGE_INTEGER get_due_time(detail::timeout const& target_time) { - LARGE_INTEGER due_time={{0}}; + LARGE_INTEGER due_time={{0,0}}; if(target_time.relative) { - unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start; + detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64()()-target_time.start; LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; @@ -423,7 +472,7 @@ namespace boost } else { - SYSTEMTIME target_system_time={0}; + SYSTEMTIME target_system_time={0,0,0,0,0,0,0,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(); @@ -467,19 +516,22 @@ namespace boost detail::win32::handle handles[3]={0}; unsigned handle_count=0; unsigned wait_handle_index=~0U; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS unsigned interruption_index=~0U; +#endif 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) +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled) { interruption_index=handle_count; - handles[handle_count++]=get_current_thread_data()->interruption_handle; + handles[handle_count++]=detail::get_current_thread_data()->interruption_handle; } - +#endif detail::win32::handle_manager timer_handle; #ifndef UNDER_CE @@ -531,11 +583,13 @@ namespace boost { return true; } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS else if(notified_index==interruption_index) { - detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle); throw thread_interrupted(); } +#endif else if(notified_index==timeout_index) { return false; @@ -555,54 +609,140 @@ namespace boost return false; } + namespace no_interruption_point + { + bool non_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 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; + } + 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==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() BOOST_NOEXCEPT { #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - //return detail::win32::GetCurrentThread(); return detail::win32::GetCurrentThreadId(); #else return thread::id(get_or_make_current_thread_data()); #endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interruption_point() { if(interruption_enabled() && interruption_requested()) { - detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle); throw thread_interrupted(); } } bool interruption_enabled() BOOST_NOEXCEPT { - return get_current_thread_data() && get_current_thread_data()->interruption_enabled; + return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled; } bool interruption_requested() BOOST_NOEXCEPT { - return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); + return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0); } +#endif void yield() BOOST_NOEXCEPT { detail::win32::Sleep(0); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS disable_interruption::disable_interruption() BOOST_NOEXCEPT: interruption_was_enabled(interruption_enabled()) { if(interruption_was_enabled) { - get_current_thread_data()->interruption_enabled=false; + detail::get_current_thread_data()->interruption_enabled=false; } } disable_interruption::~disable_interruption() BOOST_NOEXCEPT { - if(get_current_thread_data()) + if(detail::get_current_thread_data()) { - get_current_thread_data()->interruption_enabled=interruption_was_enabled; + detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled; } } @@ -610,17 +750,18 @@ namespace boost { if(d.interruption_was_enabled) { - get_current_thread_data()->interruption_enabled=true; + detail::get_current_thread_data()->interruption_enabled=true; } } restore_interruption::~restore_interruption() BOOST_NOEXCEPT { - if(get_current_thread_data()) + if(detail::get_current_thread_data()) { - get_current_thread_data()->interruption_enabled=false; + detail::get_current_thread_data()->interruption_enabled=false; } } +#endif } namespace detail @@ -716,12 +857,22 @@ namespace boost BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) { - detail::thread_data_base* const current_thread_data(get_current_thread_data()); + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); if(current_thread_data) { current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); } } +//namespace detail { +// +// void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as) +// { +// detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); +// if(current_thread_data) +// { +// current_thread_data->make_ready_at_thread_exit(as); +// } +// } +//} } - diff --git a/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp b/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp index 1654b19..5fd53b6 100644 --- a/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp +++ b/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp @@ -1,4 +1,4 @@ -// $Id: tss_pe.cpp 79373 2012-07-09 05:55:01Z viboes $ +// $Id$ // (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. // (C) Copyright 2007 Roland Schwarz // (C) Copyright 2007 Anthony Williams @@ -80,6 +80,36 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata #define WIN32_LEAN_AND_MEAN #include <windows.h> + +// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp +// into your dll; it ensures that MFC-Dll-initialization will be done properly +// The following code is adapted from the MFC-Dll-init code +/* + * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to + * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the + * alternatename directive. + */ + +// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008) +#if (_MSC_VER >= 1500) + +extern "C" { +extern BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID); +extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NULL; +#if defined (_M_IX86) +#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig") +#elif defined (_M_X64) || defined (_M_ARM) +#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig") +#else /* defined (_M_X64) || defined (_M_ARM) */ +#error Unsupported platform +#endif /* defined (_M_X64) || defined (_M_ARM) */ +} + +#endif + + + + //Definitions required by implementation #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 @@ -240,7 +270,11 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata } } +#if (_MSC_VER >= 1500) + BOOL WINAPI dll_callback(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) +#else BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID) +#endif { switch (dwReason) { @@ -251,6 +285,13 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata boost::on_process_exit(); break; } + +#if (_MSC_VER >= 1500) + if( _pRawDllMainOrig ) + { + return _pRawDllMainOrig(hInstance, dwReason, lpReserved); + } +#endif return true; } } //namespace |