diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread/pthread')
9 files changed, 1434 insertions, 284 deletions
diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp index aa71007..b1b76b0 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp @@ -4,11 +4,13 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include <boost/thread/pthread/timespec.hpp> #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #include <boost/thread/pthread/thread_data.hpp> +#endif #include <boost/thread/pthread/condition_variable_fwd.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -20,10 +22,12 @@ namespace boost { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS namespace this_thread { void BOOST_THREAD_DECL interruption_point(); } +#endif namespace thread_cv_detail { @@ -53,57 +57,88 @@ namespace boost inline void condition_variable::wait(unique_lock<mutex>& m) { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + if(! m.owns_lock()) + { + boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned")); + } +#endif int res=0; { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; detail::interruption_checker check_for_interruption(&internal_mutex,&cond); guard.activate(m); do { res = pthread_cond_wait(&cond,&internal_mutex); } while (res == EINTR); +#else + //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); + do { + res = pthread_cond_wait(&cond,the_mutex); + } while (res == EINTR); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res) { - boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait")); + boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait")); } } - inline bool condition_variable::do_timed_wait( + inline bool condition_variable::do_wait_until( unique_lock<mutex>& m, struct timespec const &timeout) { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED if (!m.owns_lock()) - boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked")); - + { + boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned")); + } +#endif thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; int cond_res; { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); guard.activate(m); cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); +#else + //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(cond_res==ETIMEDOUT) { return false; } if(cond_res) { - boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait")); + boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait")); } return true; } inline void condition_variable::notify_one() BOOST_NOEXCEPT { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif BOOST_VERIFY(!pthread_cond_signal(&cond)); } inline void condition_variable::notify_all() BOOST_NOEXCEPT { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } @@ -119,13 +154,13 @@ namespace boost int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init")); } int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init")); } } ~condition_variable_any() @@ -140,14 +175,20 @@ namespace boost int res=0; { thread_cv_detail::lock_on_exit<lock_type> guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif guard.activate(m); res=pthread_cond_wait(&cond,&internal_mutex); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res) { - boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait")); + boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait")); } } @@ -157,16 +198,17 @@ namespace boost while(!pred()) wait(m); } +#if defined BOOST_THREAD_USES_DATETIME template<typename lock_type> - bool timed_wait(lock_type& m,boost::system_time const& wait_until) + bool timed_wait(lock_type& m,boost::system_time const& abs_time) { - struct timespec const timeout=detail::get_timespec(wait_until); - return do_timed_wait(m, timeout); + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); } template<typename lock_type> - bool timed_wait(lock_type& m,xtime const& wait_until) + bool timed_wait(lock_type& m,xtime const& abs_time) { - return timed_wait(m,system_time(wait_until)); + return timed_wait(m,system_time(abs_time)); } template<typename lock_type,typename duration_type> @@ -176,20 +218,20 @@ namespace boost } template<typename lock_type,typename predicate_type> - bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred) + bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred) { while (!pred()) { - if(!timed_wait(m, wait_until)) + if(!timed_wait(m, abs_time)) return pred(); } return true; } template<typename lock_type,typename predicate_type> - bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred) + bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred) { - return timed_wait(m,system_time(wait_until),pred); + return timed_wait(m,system_time(abs_time),pred); } template<typename lock_type,typename duration_type,typename predicate_type> @@ -197,7 +239,7 @@ namespace boost { return timed_wait(m,get_system_time()+wait_duration,pred); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class lock_type,class Duration> cv_status @@ -265,26 +307,26 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - while (!pred()) - { - if (wait_for(lock, d) == cv_status::timeout) - return pred(); - } - return true; + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + +// while (!pred()) +// { +// if (wait_for(lock, d) == cv_status::timeout) +// return pred(); +// } +// return true; } template <class lock_type> - inline void wait_until( + cv_status wait_until( lock_type& lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) { using namespace chrono; nanoseconds d = tp.time_since_epoch(); - timespec ts; - seconds s = duration_cast<seconds>(d); - ts.tv_sec = static_cast<long>(s.count()); - ts.tv_nsec = static_cast<long>((d - s).count()); - do_timed_wait(lk, ts); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #endif @@ -302,25 +344,31 @@ namespace boost private: // used by boost::thread::try_join_until template <class lock_type> - inline bool do_timed_wait( + inline bool do_wait_until( lock_type& m, struct timespec const &timeout) { int res=0; { thread_cv_detail::lock_on_exit<lock_type> guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif guard.activate(m); res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res==ETIMEDOUT) { return false; } if(res) { - boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait")); + boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait")); } return true; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp index dbb3892..e18030f 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp @@ -4,22 +4,26 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include <boost/assert.hpp> #include <boost/throw_exception.hpp> #include <pthread.h> #include <boost/thread/cv_status.hpp> #include <boost/thread/mutex.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/pthread/timespec.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> #include <boost/chrono/ceil.hpp> #endif #include <boost/thread/detail/delete.hpp> #include <boost/date_time/posix_time/posix_time_duration.hpp> + #include <boost/config/abi_prefix.hpp> namespace boost @@ -28,33 +32,58 @@ namespace boost class condition_variable { private: +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS pthread_mutex_t internal_mutex; +#endif pthread_cond_t cond; public: + //private: // used by boost::thread::try_join_until + + inline bool do_wait_until( + unique_lock<mutex>& lock, + struct timespec const &timeout); + + bool do_wait_for( + unique_lock<mutex>& lock, + struct timespec const &timeout) + { + return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now())); + } + + public: BOOST_THREAD_NO_COPYABLE(condition_variable) condition_variable() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); } +#endif int const res2=pthread_cond_init(&cond,NULL); if(res2) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init")); +#endif + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init")); } } ~condition_variable() { - BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); int ret; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + do { + ret = pthread_mutex_destroy(&internal_mutex); + } while (ret == EINTR); + BOOST_ASSERT(!ret); +#endif do { ret = pthread_cond_destroy(&cond); } while (ret == EINTR); - BOOST_VERIFY(!ret); + BOOST_ASSERT(!ret); } void wait(unique_lock<mutex>& m); @@ -66,23 +95,24 @@ namespace boost } +#if defined BOOST_THREAD_USES_DATETIME inline bool timed_wait( unique_lock<mutex>& m, - boost::system_time const& wait_until) + boost::system_time const& abs_time) { #if defined BOOST_THREAD_WAIT_BUG - struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG); - return do_timed_wait(m, timeout); + struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG); + return do_wait_until(m, timeout); #else - struct timespec const timeout=detail::get_timespec(wait_until); - return do_timed_wait(m, timeout); + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); #endif } bool timed_wait( unique_lock<mutex>& m, - xtime const& wait_until) + xtime const& abs_time) { - return timed_wait(m,system_time(wait_until)); + return timed_wait(m,system_time(abs_time)); } template<typename duration_type> @@ -96,11 +126,11 @@ namespace boost template<typename predicate_type> bool timed_wait( unique_lock<mutex>& m, - boost::system_time const& wait_until,predicate_type pred) + boost::system_time const& abs_time,predicate_type pred) { while (!pred()) { - if(!timed_wait(m, wait_until)) + if(!timed_wait(m, abs_time)) return pred(); } return true; @@ -109,9 +139,9 @@ namespace boost template<typename predicate_type> bool timed_wait( unique_lock<mutex>& m, - xtime const& wait_until,predicate_type pred) + xtime const& abs_time,predicate_type pred) { - return timed_wait(m,system_time(wait_until),pred); + return timed_wait(m,system_time(abs_time),pred); } template<typename duration_type,typename predicate_type> @@ -121,6 +151,7 @@ namespace boost { return timed_wait(m,get_system_time()+wait_duration,pred); } +#endif #ifdef BOOST_THREAD_USES_CHRONO @@ -190,12 +221,14 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - while (!pred()) - { - if (wait_for(lock, d) == cv_status::timeout) - return pred(); - } - return true; + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + +// while (!pred()) +// { +// if (wait_for(lock, d) == cv_status::timeout) +// return pred(); +// } +// return true; } #endif @@ -210,27 +243,21 @@ namespace boost void notify_all() BOOST_NOEXCEPT; #ifdef BOOST_THREAD_USES_CHRONO - inline void wait_until( + inline cv_status wait_until( unique_lock<mutex>& lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) { using namespace chrono; nanoseconds d = tp.time_since_epoch(); - timespec ts; - seconds s = duration_cast<seconds>(d); - ts.tv_sec = static_cast<long>(s.count()); - ts.tv_nsec = static_cast<long>((d - s).count()); - do_timed_wait(lk, ts); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #endif - //private: // used by boost::thread::try_join_until - - inline bool do_timed_wait( - unique_lock<mutex>& lock, - struct timespec const &timeout); }; BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); + } diff --git a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp index 2c5af92..3e9af2a 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp @@ -6,10 +6,14 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/detail/config.hpp> #include <pthread.h> #include <boost/throw_exception.hpp> +#include <boost/core/ignore_unused.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/thread/thread_time.hpp> #include <boost/thread/xtime.hpp> #include <boost/assert.hpp> @@ -23,15 +27,68 @@ #include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L +#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif +#endif + #include <boost/config/abi_prefix.hpp> +#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG +#define BOOST_THREAD_HAS_EINTR_BUG +#endif + namespace boost { + namespace posix { +#ifdef BOOST_THREAD_HAS_EINTR_BUG + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_destroy(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_lock(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_unlock(m); + } while (ret == EINTR); + return ret; + } +#else + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + return ::pthread_mutex_destroy(m); + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + return ::pthread_mutex_lock(m); + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + return ::pthread_mutex_unlock(m); + } + +#endif + + } class mutex { private: @@ -49,20 +106,14 @@ namespace boost } ~mutex() { - int ret; - do - { - ret = pthread_mutex_destroy(&m); - } while (ret == EINTR); + int const res = posix::pthread_mutex_destroy(&m); + boost::ignore_unused(res); + BOOST_ASSERT(!res); } void lock() { - int res; - do - { - res = pthread_mutex_lock(&m); - } while (res == EINTR); + int res = posix::pthread_mutex_lock(&m); if (res) { boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); @@ -71,12 +122,11 @@ namespace boost void unlock() { - int ret; - do + int res = posix::pthread_mutex_unlock(&m); + if (res) { - ret = pthread_mutex_unlock(&m); - } while (ret == EINTR); - BOOST_VERIFY(!ret); + boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); + } } bool try_lock() @@ -86,12 +136,8 @@ namespace boost { res = pthread_mutex_trylock(&m); } while (res == EINTR); - if(res && (res!=EBUSY)) + if (res==EBUSY) { - // The following throw_exception has been replaced by an assertion and just return false, - // as this is an internal error and the user can do nothing with the exception. - //boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock")); - BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock"); return false; } @@ -105,8 +151,10 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<mutex> scoped_lock; typedef detail::try_lock_wrapper<mutex> scoped_try_lock; +#endif }; typedef mutex try_mutex; @@ -132,7 +180,8 @@ namespace boost int const res2=pthread_cond_init(&cond,NULL); if(res2) { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); + //BOOST_VERIFY(!pthread_mutex_destroy(&m)); boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init")); } is_locked=false; @@ -140,12 +189,13 @@ namespace boost } ~timed_mutex() { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { @@ -155,23 +205,39 @@ namespace boost { return timed_lock(system_time(absolute_time)); } - +#endif #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK void lock() { - BOOST_VERIFY(!pthread_mutex_lock(&m)); + int res = posix::pthread_mutex_lock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); + } } void unlock() { - BOOST_VERIFY(!pthread_mutex_unlock(&m)); + int res = posix::pthread_mutex_unlock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); + } } bool try_lock() { - int const res=pthread_mutex_trylock(&m); - BOOST_ASSERT(!res || res==EBUSY); - return !res; + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; } @@ -232,12 +298,13 @@ namespace boost public: #endif +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=detail::get_timespec(abs_time); + struct timespec const ts=boost::detail::to_timespec(abs_time); return do_try_lock_until(ts); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -261,12 +328,9 @@ namespace boost } bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts; - seconds s = duration_cast<seconds>(d); - ts.tv_sec = static_cast<long>(s.count()); - ts.tv_nsec = static_cast<long>((d - s).count()); + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); return do_try_lock_until(ts); } #endif @@ -278,9 +342,11 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/once.hpp b/3rdParty/Boost/src/boost/thread/pthread/once.hpp index 02c2732..0bef038 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/once.hpp @@ -11,11 +11,14 @@ // http://www.boost.org/LICENSE_1_0.txt) #include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> #include <boost/thread/detail/delete.hpp> -#include <boost/detail/no_exceptions_support.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/bind.hpp> #include <boost/assert.hpp> #include <boost/config/abi_prefix.hpp> @@ -26,21 +29,32 @@ namespace boost { -#define BOOST_ONCE_INITIAL_FLAG_VALUE 0 + struct once_flag; + + #define BOOST_ONCE_INITIAL_FLAG_VALUE 0 namespace thread_detail { -//#ifdef SIG_ATOMIC_MAX -// typedef sig_atomic_t uintmax_atomic_t; -// #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C SIG_ATOMIC_MAX -//#else - typedef unsigned long uintmax_atomic_t; - #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##ul + typedef boost::uint32_t uintmax_atomic_t; + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0) -//#endif + } #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f); + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1); + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); +#endif struct once_flag { @@ -50,11 +64,26 @@ namespace boost {} private: volatile thread_detail::uintmax_atomic_t epoch; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<typename Function, class ...ArgTypes> + friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else template<typename Function> - friend - void call_once(once_flag& flag,Function f); + friend void call_once(once_flag& flag, Function f); + template<typename Function, typename T1> + friend void call_once(once_flag& flag, Function f, T1 p1); + template<typename Function, typename T1, typename T2> + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template<typename Function, typename T1, typename T2, typename T3> + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); + +#endif + }; +#define BOOST_ONCE_INIT once_flag() + #else // BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag @@ -65,59 +94,445 @@ namespace boost #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 - namespace detail + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + namespace thread_detail { - BOOST_THREAD_DECL thread_detail::uintmax_atomic_t& get_once_per_thread_epoch(); - BOOST_THREAD_DECL extern thread_detail::uintmax_atomic_t once_global_epoch; + BOOST_THREAD_DECL uintmax_atomic_t& get_once_per_thread_epoch(); + BOOST_THREAD_DECL extern uintmax_atomic_t once_global_epoch; BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex; BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv; } // Based on Mike Burrows fast_pthread_once algorithm as described in // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html - template<typename Function> - void call_once(once_flag& flag,Function f) + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + + } + } +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + f(); + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + f(); + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) { - static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; - static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; - thread_detail::uintmax_atomic_t const epoch=flag.epoch; - thread_detail::uintmax_atomic_t& this_thread_epoch=detail::get_once_per_thread_epoch(); + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); - if(epoch<this_thread_epoch) + while(flag.epoch<=being_initialized) { - pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex); + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); - while(flag.epoch<=being_initialized) + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) { - if(flag.epoch==uninitialized_flag) + flag.epoch=being_initialized; + BOOST_TRY { - flag.epoch=being_initialized; - BOOST_TRY - { - pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex); - f(); - } - BOOST_CATCH (...) - { - flag.epoch=uninitialized_flag; - BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); - BOOST_RETHROW - } - BOOST_CATCH_END - flag.epoch=--detail::once_global_epoch; - BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)), + thread_detail::decay_copy(boost::forward<T1>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; } - else + BOOST_CATCH (...) { - while(flag.epoch==being_initialized) - { - BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex)); - } + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); } } - this_thread_epoch=detail::once_global_epoch; } + this_thread_epoch=thread_detail::once_global_epoch; } + } + +#endif + } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp b/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp new file mode 100644 index 0000000..923f07b --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp @@ -0,0 +1,313 @@ +#ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP +#define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP + +// once.hpp +// +// (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) + +#include <boost/thread/detail/config.hpp> + +#include <boost/cstdint.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/bind.hpp> +#include <boost/atomic.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + + struct once_flag; + + namespace thread_detail + { + +#if BOOST_ATOMIC_INT_LOCK_FREE == 2 + typedef unsigned int atomic_int_type; +#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2 + typedef unsigned short atomic_int_type; +#elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2 + typedef unsigned char atomic_int_type; +#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2 + typedef unsigned long atomic_int_type; +#elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2 + typedef ulong_long_type atomic_int_type; +#else + // All tested integer types are not atomic, the spinlock pool will be used + typedef unsigned int atomic_int_type; +#endif + + typedef boost::atomic<atomic_int_type> atomic_type; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0) + { + } + + private: + thread_detail::atomic_type storage; + + friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + }; + +#define BOOST_ONCE_INIT boost::once_flag() + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + //return reinterpret_cast< atomic_type& >(flag.storage); + return flag.storage; + } + } + +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + struct once_flag + { + // The thread_detail::atomic_int_type storage is marked + // with this attribute in order to let the compiler know that it will alias this member + // and silence compilation warnings. + BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage; + }; + + #define BOOST_ONCE_INIT {0} + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + return reinterpret_cast< atomic_type& >(flag.storage); + } + + } + +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)), + thread_detail::decay_copy(boost::forward<T1>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + + +#endif +} + +#include <boost/config/abi_suffix.hpp> + +#endif + diff --git a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp index 2a6bc7d..9330d77 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp @@ -9,7 +9,9 @@ #include <pthread.h> #include <boost/throw_exception.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/thread/thread_time.hpp> #include <boost/assert.hpp> #ifndef _WIN32 @@ -26,10 +28,13 @@ #include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 +#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif +#endif + #if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK @@ -167,8 +172,10 @@ namespace boost #endif +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_mutex> scoped_lock; typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock; +#endif }; typedef recursive_mutex recursive_try_mutex; @@ -232,11 +239,13 @@ namespace boost #endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { return timed_lock(get_system_time()+relative_time); } +#endif #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK void lock() @@ -334,12 +343,13 @@ namespace boost #endif +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=detail::get_timespec(abs_time); + struct timespec const ts=detail::to_timespec(abs_time); return do_try_lock_until(ts); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -363,12 +373,9 @@ namespace boost } bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts; - seconds s = duration_cast<seconds>(d); - ts.tv_sec = static_cast<long>(s.count()); - ts.tv_nsec = static_cast<long>((d - s).count()); + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); return do_try_lock_until(ts); } #endif @@ -380,9 +387,11 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp index cf45188..458d6c8 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp @@ -12,12 +12,15 @@ #include <boost/static_assert.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/condition_variable.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #include <boost/thread/detail/thread_interruption.hpp> +#endif #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> #include <boost/chrono/ceil.hpp> #endif #include <boost/thread/detail/delete.hpp> +#include <boost/assert.hpp> #include <boost/config/abi_prefix.hpp> @@ -26,8 +29,125 @@ namespace boost class shared_mutex { private: - struct state_data + class state_data { + public: + state_data () : + shared_count(0), + exclusive(false), + upgrade(false), + exclusive_waiting_blocked(false) + {} + + void assert_free() const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( ! upgrade ); + BOOST_ASSERT( shared_count==0 ); + } + + void assert_locked() const + { + BOOST_ASSERT( exclusive ); + BOOST_ASSERT( shared_count==0 ); + BOOST_ASSERT( ! upgrade ); + } + + void assert_lock_shared () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( shared_count>0 ); + //BOOST_ASSERT( (! upgrade) || (shared_count>1)); + // if upgraded there are at least 2 threads sharing the mutex, + // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership. + } + + void assert_lock_upgraded () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( upgrade ); + BOOST_ASSERT( shared_count>0 ); + } + + void assert_lock_not_upgraded () const + { + BOOST_ASSERT( ! upgrade ); + } + + bool can_lock () const + { + return ! (shared_count || exclusive); + } + + void exclusive_blocked (bool blocked) + { + exclusive_waiting_blocked = blocked; + } + + void lock () + { + exclusive = true; + } + + void unlock () + { + exclusive = false; + exclusive_waiting_blocked = false; + } + + bool can_lock_shared () const + { + return ! (exclusive || exclusive_waiting_blocked); + } + + bool more_shared () const + { + return shared_count > 0 ; + } + unsigned get_shared_count () const + { + return shared_count ; + } + unsigned lock_shared () + { + return ++shared_count; + } + + + void unlock_shared () + { + --shared_count; + } + + bool unlock_shared_downgrades() + { + if (upgrade) { + upgrade=false; + exclusive=true; + return true; + } else { + exclusive_waiting_blocked=false; + return false; + } + } + + void lock_upgrade () + { + ++shared_count; + upgrade=true; + } + bool can_lock_upgrade () const + { + return ! (exclusive || exclusive_waiting_blocked || upgrade); + } + + void unlock_upgrade () + { + upgrade=false; + --shared_count; + } + + //private: unsigned shared_count; bool exclusive; bool upgrade; @@ -49,12 +169,11 @@ namespace boost } public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) shared_mutex() { - state_data state_={0,0,0,0}; - state=state_; } ~shared_mutex() @@ -63,44 +182,45 @@ namespace boost void lock_shared() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); - - while(state.exclusive || state.exclusive_waiting_blocked) +#endif + boost::unique_lock<boost::mutex> lk(state_change); + while(!state.can_lock_shared()) { shared_cond.wait(lk); } - ++state.shared_count; + state.lock_shared(); } bool try_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); - if(state.exclusive || state.exclusive_waiting_blocked) + if(!state.can_lock_shared()) { return false; } - else - { - ++state.shared_count; - return true; - } + state.lock_shared(); + return true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock_shared(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) + while(!state.can_lock_shared()) { if(!shared_cond.timed_wait(lk,timeout)) { return false; } } - ++state.shared_count; + state.lock_shared(); return true; } @@ -109,6 +229,7 @@ namespace boost { return timed_lock_shared(get_system_time()+relative_time); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) @@ -118,36 +239,43 @@ namespace boost template <class Clock, class Duration> bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) + while(!state.can_lock_shared()) + //while(state.exclusive || state.exclusive_waiting_blocked) { if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) { return false; } } - ++state.shared_count; + state.lock_shared(); return true; } #endif void unlock_shared() { - boost::mutex::scoped_lock lk(state_change); - bool const last_reader=!--state.shared_count; - - if(last_reader) + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); + state.unlock_shared(); + if (! state.more_shared()) { - if(state.upgrade) + if (state.upgrade) { + // As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared() + // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified. state.upgrade=false; state.exclusive=true; + lk.unlock(); upgrade_cond.notify_one(); } else { state.exclusive_waiting_blocked=false; + lk.unlock(); } release_waiters(); } @@ -155,10 +283,12 @@ namespace boost void lock() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.shared_count || state.exclusive) + while (state.shared_count || state.exclusive) { state.exclusive_waiting_blocked=true; exclusive_cond.wait(lk); @@ -166,10 +296,13 @@ namespace boost state.exclusive=true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.shared_count || state.exclusive) { @@ -194,7 +327,7 @@ namespace boost { return timed_lock(get_system_time()+relative_time); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -204,8 +337,10 @@ namespace boost template <class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.shared_count || state.exclusive) { @@ -228,7 +363,7 @@ namespace boost bool try_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); if(state.shared_count || state.exclusive) { @@ -244,28 +379,35 @@ namespace boost void unlock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; state.exclusive_waiting_blocked=false; + state.assert_free(); release_waiters(); } void lock_upgrade() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { shared_cond.wait(lk); } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock_upgrade(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { if(!shared_cond.timed_wait(lk,timeout)) @@ -277,7 +419,7 @@ namespace boost break; } } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; return true; } @@ -287,7 +429,7 @@ namespace boost { return timed_lock_upgrade(get_system_time()+relative_time); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time) @@ -297,8 +439,10 @@ namespace boost template <class Clock, class Duration> bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) @@ -310,68 +454,75 @@ namespace boost break; } } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; return true; } #endif bool try_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { return false; } else { - ++state.shared_count; + state.lock_shared(); state.upgrade=true; + state.assert_lock_upgraded(); return true; } } void unlock_upgrade() { - boost::mutex::scoped_lock lk(state_change); - state.upgrade=false; - bool const last_reader=!--state.shared_count; - - if(last_reader) + boost::unique_lock<boost::mutex> lk(state_change); + //state.upgrade=false; + state.unlock_upgrade(); + if(! state.more_shared() ) { state.exclusive_waiting_blocked=false; release_waiters(); } else { - shared_cond.notify_all(); + shared_cond.notify_all(); } } // Upgrade <-> Exclusive void unlock_upgrade_and_lock() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); - --state.shared_count; - while(state.shared_count) +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); + state.unlock_shared(); + while (state.more_shared()) { upgrade_cond.wait(lk); } state.upgrade=false; state.exclusive=true; + state.assert_locked(); } void unlock_and_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; state.upgrade=true; - ++state.shared_count; + state.lock_shared(); state.exclusive_waiting_blocked=false; + state.assert_lock_upgraded(); release_waiters(); } bool try_unlock_upgrade_and_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); if( !state.exclusive && !state.exclusive_waiting_blocked && state.upgrade @@ -380,6 +531,7 @@ namespace boost state.shared_count=0; state.exclusive=true; state.upgrade=false; + state.assert_locked(); return true; } return false; @@ -398,8 +550,11 @@ namespace boost try_unlock_upgrade_and_lock_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); if (state.shared_count != 1) { for (;;) @@ -422,9 +577,10 @@ namespace boost // Shared <-> Exclusive void unlock_and_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; - ++state.shared_count; + state.lock_shared(); state.exclusive_waiting_blocked=false; release_waiters(); } @@ -432,7 +588,8 @@ namespace boost #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( !state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade @@ -458,8 +615,11 @@ namespace boost try_unlock_shared_and_lock_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if (state.shared_count != 1) { for (;;) @@ -483,7 +643,8 @@ namespace boost // Shared <-> Upgrade void unlock_upgrade_and_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); state.upgrade=false; state.exclusive_waiting_blocked=false; release_waiters(); @@ -492,7 +653,8 @@ namespace boost #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( !state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade @@ -517,8 +679,11 @@ namespace boost try_unlock_shared_and_lock_upgrade_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( state.exclusive || state.exclusive_waiting_blocked || state.upgrade diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp index db4e09f..801f470 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp @@ -8,13 +8,13 @@ #include <boost/thread/detail/config.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/pthread/condition_variable_fwd.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> -#include <boost/optional.hpp> #include <boost/assert.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -24,6 +24,10 @@ #include <vector> #include <utility> +#if defined(__ANDROID__) +#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983 +#endif + #include <pthread.h> #include <unistd.h> @@ -77,6 +81,7 @@ namespace boost namespace detail { + struct shared_state_base; struct tss_cleanup_function; struct thread_exit_callback_node; struct tss_data_node @@ -107,8 +112,7 @@ namespace boost bool joined; boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map<void const*,boost::detail::tss_data_node> tss_data; - bool interrupt_enabled; - bool interrupt_requested; + pthread_mutex_t* cond_mutex; pthread_cond_t* current_cond; typedef std::vector<std::pair<condition_variable*, mutex*> @@ -116,27 +120,49 @@ namespace boost > notify_list_t; notify_list_t notify; + typedef std::vector<shared_ptr<shared_state_base> > async_states_t; + async_states_t async_states_; + +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. + // Another option is to have them always + bool interrupt_enabled; + bool interrupt_requested; +//#endif thread_data_base(): + thread_handle(0), done(false),join_started(false),joined(false), thread_exit_callbacks(0), - interrupt_enabled(true), - interrupt_requested(false), + cond_mutex(0), current_cond(0), - notify() + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interrupt_enabled(true) + , interrupt_requested(false) +//#endif {} virtual ~thread_data_base(); typedef pthread_t native_handle_type; virtual void run()=0; - void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) { notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); } + + void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + async_states_.push_back(as); + } + }; BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS class interruption_checker { thread_data_base* const thread_info; @@ -188,71 +214,68 @@ namespace boost } } }; +#endif } namespace this_thread { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + #ifdef BOOST_THREAD_USES_CHRONO +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { - using namespace chrono; - 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(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {} - } - else - { - if (ns >= nanoseconds::zero()) - { - - # if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts; - ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count()); - ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count()); - BOOST_VERIFY(!pthread_delay_np(&ts)); - # elif defined(BOOST_HAS_NANOSLEEP) - timespec ts; - ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count()); - ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count()); - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); - # else - mutex mx; - mutex::scoped_lock lock(mx); - condition_variable cond; - cond.wait_for(lock, ns); - # endif - } - } + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); } #endif +#endif // BOOST_THREAD_USES_CHRONO + + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + + #ifdef BOOST_THREAD_USES_CHRONO + #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + inline + void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); + } + #endif + #endif // BOOST_THREAD_USES_CHRONO + + } // no_interruption_point + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; +#if defined BOOST_THREAD_USES_DATETIME #ifdef __DECXXX /// Workaround of DECCXX issue of incorrect template substitution - template<typename TimeDuration> - inline void sleep(TimeDuration const& rel_time) + template<> +#endif + inline void sleep(system_time const& abs_time) { - this_thread::sleep(get_system_time()+rel_time); + return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time)); } - template<> - void BOOST_THREAD_DECL sleep(system_time const& abs_time); -#else - void BOOST_THREAD_DECL sleep(system_time const& abs_time); - template<typename TimeDuration> inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { this_thread::sleep(get_system_time()+rel_time); } -#endif - } +#endif // BOOST_THREAD_USES_DATETIME + } // this_thread } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp b/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp index d7465c1..82f50f6 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp @@ -1,34 +1,118 @@ #ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP #define BOOST_THREAD_PTHREAD_TIMESPEC_HPP -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 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_time.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/date_time/posix_time/conversion.hpp> +#endif #include <pthread.h> #ifndef _WIN32 #include <unistd.h> #endif +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/duration.hpp> +#endif + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_TIMESPEC_MAC_API +#include <sys/time.h> //for gettimeofday and timeval +#else +#include <time.h> // for clock_gettime +#endif #include <boost/config/abi_prefix.hpp> namespace boost { - namespace detail - { - inline struct timespec get_timespec(boost::system_time const& abs_time) - { - struct timespec timeout={0,0}; - boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); - - timeout.tv_sec=time_since_epoch.total_seconds(); - timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); - return timeout; - } + namespace detail + { +#if defined BOOST_THREAD_USES_DATETIME + inline struct timespec to_timespec(boost::system_time const& abs_time) + { + struct timespec timeout = { 0,0}; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + timeout.tv_sec=time_since_epoch.total_seconds(); + timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); + return timeout; + } +#endif +#if defined BOOST_THREAD_USES_CHRONO + inline timespec to_timespec(chrono::nanoseconds const& ns) + { + struct timespec ts; + ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count()); + ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count()); + return ts; } + +#endif + + inline timespec to_timespec(boost::intmax_t const& ns) + { + boost::intmax_t s = ns / 1000000000l; + struct timespec ts; + ts.tv_sec = static_cast<long> (s); + ts.tv_nsec = static_cast<long> (ns - s * 1000000000l); + return ts; + } + inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts) + { + return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec; + } + inline bool timespec_ge_zero(timespec const& ts) + { + return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0); + } + inline timespec timespec_now() + { + timespec ts; + +#if defined(BOOST_THREAD_TIMESPEC_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#else + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); + } +#endif + return ts; + } + inline timespec timespec_zero() + { + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + return ts; + } + inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); + } + inline timespec timespec_minus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs)); + } + inline bool timespec_gt(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs); + } + inline bool timespec_ge(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs); + } + + } } #include <boost/config/abi_suffix.hpp> |