diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread')
22 files changed, 601 insertions, 191 deletions
diff --git a/3rdParty/Boost/src/boost/thread/detail/config.hpp b/3rdParty/Boost/src/boost/thread/detail/config.hpp index 7661507..4015a6c 100644 --- a/3rdParty/Boost/src/boost/thread/detail/config.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/config.hpp @@ -19,8 +19,14 @@ #include "platform.hpp" +// provided for backwards compatibility, since this +// macro was used for several releases by mistake. +#if defined(BOOST_THREAD_DYN_DLL) +# define BOOST_THREAD_DYN_LINK +#endif + // compatibility with the rest of Boost's auto-linking code: -#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK) +#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) # undef BOOST_THREAD_USE_LIB # define BOOST_THREAD_USE_DLL #endif diff --git a/3rdParty/Boost/src/boost/thread/detail/platform.hpp b/3rdParty/Boost/src/boost/thread/detail/platform.hpp index 4a37cf3..58601b0 100644 --- a/3rdParty/Boost/src/boost/thread/detail/platform.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/platform.hpp @@ -29,7 +29,7 @@ # define BOOST_THREAD_HPUX #elif defined(__CYGWIN__) # define BOOST_THREAD_CYGWIN -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32) # define BOOST_THREAD_WIN32 #elif defined(__BEOS__) # define BOOST_THREAD_BEOS diff --git a/3rdParty/Boost/src/boost/thread/detail/thread.hpp b/3rdParty/Boost/src/boost/thread/detail/thread.hpp index 9615a39..005555e 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread.hpp @@ -3,10 +3,12 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-10 Anthony Williams #include <boost/thread/exceptions.hpp> +#ifndef BOOST_NO_IOSTREAM #include <ostream> +#endif #include <boost/thread/detail/move.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/xtime.hpp> @@ -113,14 +115,13 @@ namespace boost void release_handle(); - mutable boost::mutex thread_info_mutex; detail::thread_data_ptr thread_info; void start_thread(); explicit thread(detail::thread_data_ptr data); - detail::thread_data_ptr get_thread_info() const; + detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; #ifndef BOOST_NO_RVALUE_REFERENCES template<typename F> @@ -147,7 +148,7 @@ namespace boost #endif struct dummy; public: -#ifdef __SUNPRO_CC +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) thread(const volatile thread&); #endif thread(); @@ -157,7 +158,7 @@ namespace boost #ifdef BOOST_MSVC template <class F> explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): - thread_info(make_thread_info(f)) + thread_info(make_thread_info(static_cast<F&&>(f))) { start_thread(); } @@ -217,7 +218,7 @@ namespace boost x->thread_info.reset(); } -#ifdef __SUNPRO_CC +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) thread& operator=(thread x) { swap(x); @@ -394,7 +395,7 @@ namespace boost thread_data(thread_data_) {} friend class thread; - friend id this_thread::get_id(); + friend id BOOST_THREAD_DECL this_thread::get_id(); public: id(): thread_data() @@ -430,6 +431,8 @@ namespace boost return !(thread_data<y.thread_data); } +#ifndef BOOST_NO_IOSTREAM +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS template<class charT, class traits> friend std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const id& x) @@ -443,8 +446,34 @@ namespace boost return os<<"{Not-any-thread}"; } } +#else + template<class charT, class traits> + std::basic_ostream<charT, traits>& + print(std::basic_ostream<charT, traits>& os) const + { + if(thread_data) + { + return os<<thread_data; + } + else + { + return os<<"{Not-any-thread}"; + } + } + +#endif +#endif }; +#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template<class charT, class traits> + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) + { + return x.print(os); + } +#endif + inline bool thread::operator==(const thread& other) const { return get_id()==other.get_id(); diff --git a/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp b/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp index 823b92e..f1ccdf8 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp @@ -18,10 +18,13 @@ namespace boost { - class thread_group: - private noncopyable + class thread_group { + private: + thread_group(thread_group const&); + thread_group& operator=(thread_group const&); public: + thread_group() {} ~thread_group() { for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); diff --git a/3rdParty/Boost/src/boost/thread/detail/tss_hooks.hpp b/3rdParty/Boost/src/boost/thread/detail/tss_hooks.hpp index c496844..b2ceece 100644 --- a/3rdParty/Boost/src/boost/thread/detail/tss_hooks.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/tss_hooks.hpp @@ -12,27 +12,9 @@ #if defined(BOOST_HAS_WINTHREADS) - typedef void (__cdecl *thread_exit_handler)(void); - - extern "C" BOOST_THREAD_DECL int at_thread_exit( - thread_exit_handler exit_handler - ); - //Add a function to the list of functions that will - //be called when a thread is about to exit. - //Currently only implemented for Win32, but should - //later be implemented for all platforms. - //Used by Win32 implementation of Boost.Threads - //tss to perform cleanup. - //Like the C runtime library atexit() function, - //which it mimics, at_thread_exit() returns - //zero if successful and a nonzero - //value if an error occurs. - -#endif //defined(BOOST_HAS_WINTHREADS) - -#if defined(BOOST_HAS_WINTHREADS) - - extern "C" BOOST_THREAD_DECL void on_process_enter(void); +namespace boost +{ + BOOST_THREAD_DECL void __cdecl on_process_enter(void); //Function to be called when the exe or dll //that uses Boost.Threads first starts //or is first loaded. @@ -42,7 +24,7 @@ //a method for doing so has been discovered. //May be omitted; may be called multiple times. - extern "C" BOOST_THREAD_DECL void on_process_exit(void); + BOOST_THREAD_DECL void __cdecl on_process_exit(void); //Function to be called when the exe or dll //that uses Boost.Threads first starts //or is first loaded. @@ -52,7 +34,7 @@ //a method for doing so has been discovered. //Must not be omitted; may be called multiple times. - extern "C" BOOST_THREAD_DECL void on_thread_enter(void); + BOOST_THREAD_DECL void __cdecl on_thread_enter(void); //Function to be called just after a thread starts //in an exe or dll that uses Boost.Threads. //Must be called in the context of the thread @@ -61,7 +43,7 @@ //a method for doing so has been discovered. //May be omitted; may be called multiple times. - extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void); + BOOST_THREAD_DECL void __cdecl on_thread_exit(void); //Function to be called just be fore a thread ends //in an exe or dll that uses Boost.Threads. //Must be called in the context of the thread @@ -70,10 +52,11 @@ //a method for doing so has been discovered. //Must not be omitted; may be called multiple times. - extern "C" void tss_cleanup_implemented(void); + void tss_cleanup_implemented(); //Dummy function used both to detect whether tss cleanup //cleanup has been implemented and to force //it to be linked into the Boost.Threads library. +} #endif //defined(BOOST_HAS_WINTHREADS) diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp index 8111d9e..a4b4343 100644 --- a/3rdParty/Boost/src/boost/thread/future.hpp +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -9,6 +9,8 @@ #include <stdexcept> #include <boost/thread/detail/move.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> #include <boost/exception_ptr.hpp> #include <boost/shared_ptr.hpp> #include <boost/scoped_ptr.hpp> @@ -140,6 +142,8 @@ namespace boost { lock.lock(); } + private: + relocker& operator=(relocker const&); }; void do_callback(boost::unique_lock<boost::mutex>& lock) @@ -388,15 +392,18 @@ namespace boost class future_waiter { + struct registered_waiter; + typedef std::vector<registered_waiter>::size_type count_type; + struct registered_waiter { boost::shared_ptr<detail::future_object_base> future; detail::future_object_base::waiter_list::iterator wait_iterator; - unsigned index; + count_type index; registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_, detail::future_object_base::waiter_list::iterator wait_iterator_, - unsigned index_): + count_type index_): future(future_),wait_iterator(wait_iterator_),index(index_) {} @@ -404,7 +411,6 @@ namespace boost struct all_futures_lock { - typedef std::vector<registered_waiter>::size_type count_type; count_type count; boost::scoped_array<boost::unique_lock<boost::mutex> > locks; @@ -424,7 +430,7 @@ namespace boost void unlock() { - for(unsigned i=0;i<count;++i) + for(count_type i=0;i<count;++i) { locks[i].unlock(); } @@ -433,7 +439,7 @@ namespace boost boost::condition_variable_any cv; std::vector<registered_waiter> futures; - unsigned future_count; + count_type future_count; public: future_waiter(): @@ -450,12 +456,12 @@ namespace boost ++future_count; } - unsigned wait() + count_type wait() { all_futures_lock lk(futures); for(;;) { - for(unsigned i=0;i<futures.size();++i) + for(count_type i=0;i<futures.size();++i) { if(futures[i].future->done) { @@ -468,7 +474,7 @@ namespace boost ~future_waiter() { - for(unsigned i=0;i<futures.size();++i) + for(count_type i=0;i<futures.size();++i) { futures[i].future->remove_external_waiter(futures[i].wait_iterator); } @@ -548,6 +554,9 @@ namespace boost template<typename Iterator> typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) { + if(begin==end) + return end; + detail::future_waiter waiter; for(Iterator current=begin;current!=end;++current) { @@ -903,10 +912,10 @@ namespace boost void lazy_init() { - if(!future) + if(!atomic_load(&future)) { - future_obtained=false; - future.reset(new detail::future_object<R>); + future_ptr blank; + atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>)); } } @@ -936,12 +945,14 @@ namespace boost future_obtained(rhs.future_obtained) { future.swap(rhs.future); + rhs.future_obtained=false; } promise & operator=(promise&& rhs) { future.swap(rhs.future); future_obtained=rhs.future_obtained; rhs.future.reset(); + rhs.future_obtained=false; return *this; } #else @@ -949,12 +960,14 @@ namespace boost future(rhs->future),future_obtained(rhs->future_obtained) { rhs->future.reset(); + rhs->future_obtained=false; } promise & operator=(boost::detail::thread_move_t<promise> rhs) { future=rhs->future; future_obtained=rhs->future_obtained; rhs->future.reset(); + rhs->future_obtained=false; return *this; } @@ -1038,10 +1051,10 @@ namespace boost void lazy_init() { - if(!future) + if(!atomic_load(&future)) { - future_obtained=false; - future.reset(new detail::future_object<void>); + future_ptr blank; + atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>)); } } public: @@ -1070,12 +1083,14 @@ namespace boost future_obtained(rhs.future_obtained) { future.swap(rhs.future); + rhs.future_obtained=false; } promise & operator=(promise&& rhs) { future.swap(rhs.future); future_obtained=rhs.future_obtained; rhs.future.reset(); + rhs.future_obtained=false; return *this; } #else @@ -1083,12 +1098,14 @@ namespace boost future(rhs->future),future_obtained(rhs->future_obtained) { rhs->future.reset(); + rhs->future_obtained=false; } promise & operator=(boost::detail::thread_move_t<promise> rhs) { future=rhs->future; future_obtained=rhs->future_obtained; rhs->future.reset(); + rhs->future_obtained=false; return *this; } diff --git a/3rdParty/Boost/src/boost/thread/locks.hpp b/3rdParty/Boost/src/boost/thread/locks.hpp index 3cd6f28..d23e619 100644 --- a/3rdParty/Boost/src/boost/thread/locks.hpp +++ b/3rdParty/Boost/src/boost/thread/locks.hpp @@ -11,6 +11,7 @@ #include <iterator> #include <boost/thread/thread_time.hpp> #include <boost/detail/workaround.hpp> +#include <boost/type_traits/is_class.hpp> #include <boost/config/abi_prefix.hpp> @@ -27,41 +28,101 @@ namespace boost #ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES namespace detail { - template<typename T> +#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \ + template<typename T, bool=boost::is_class<T>::value> \ + struct has_member_called_##member_name \ + { \ + BOOST_STATIC_CONSTANT(bool, value=false); \ + }; \ + \ + template<typename T> \ + struct has_member_called_##member_name<T,true> \ + { \ + typedef char true_type; \ + struct false_type \ + { \ + true_type dummy[2]; \ + }; \ + \ + struct fallback { int member_name; }; \ + struct derived: \ + T, fallback \ + { \ + derived(); \ + }; \ + \ + template<int fallback::*> struct tester; \ + \ + template<typename U> \ + static false_type has_member(tester<&U::member_name>*); \ + template<typename U> \ + static true_type has_member(...); \ + \ + BOOST_STATIC_CONSTANT( \ + bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \ + } + + BOOST_DEFINE_HAS_MEMBER_CALLED(lock); + BOOST_DEFINE_HAS_MEMBER_CALLED(unlock); + BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock); + + template<typename T,bool=has_member_called_lock<T>::value > struct has_member_lock { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template<typename T> + struct has_member_lock<T,true> + { typedef char true_type; struct false_type { true_type dummy[2]; }; + template<typename U,typename V> + static true_type has_member(V (U::*)()); template<typename U> - static true_type has_member(U*,void (U::*dummy)()=&U::lock); - static false_type has_member(void*); + static false_type has_member(U); - BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type)); + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type)); }; - - template<typename T> + + template<typename T,bool=has_member_called_unlock<T>::value > struct has_member_unlock { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template<typename T> + struct has_member_unlock<T,true> + { typedef char true_type; struct false_type { true_type dummy[2]; }; + template<typename U,typename V> + static true_type has_member(V (U::*)()); template<typename U> - static true_type has_member(U*,void (U::*dummy)()=&U::unlock); - static false_type has_member(void*); + static false_type has_member(U); - BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type)); + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type)); }; - template<typename T> + template<typename T,bool=has_member_called_try_lock<T>::value > struct has_member_try_lock { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template<typename T> + struct has_member_try_lock<T,true> + { typedef char true_type; struct false_type { @@ -69,10 +130,12 @@ namespace boost }; template<typename U> - static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock); - static false_type has_member(void*); + static true_type has_member(bool (U::*)()); + template<typename U> + static false_type has_member(U); - BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type)); + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type)); }; } @@ -214,7 +277,7 @@ namespace boost unique_lock& operator=(unique_lock&); unique_lock& operator=(upgrade_lock<Mutex>& other); public: -#ifdef __SUNPRO_CC +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) unique_lock(const volatile unique_lock&); #endif unique_lock(): @@ -300,7 +363,7 @@ namespace boost return detail::thread_move_t<unique_lock<Mutex> >(*this); } -#ifdef __SUNPRO_CC +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) unique_lock& operator=(unique_lock<Mutex> other) { swap(other); @@ -422,6 +485,18 @@ namespace boost { lhs.swap(rhs); } + + template<typename Mutex> + inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul) + { + return static_cast<upgrade_lock<Mutex>&&>(ul); + } + + template<typename Mutex> + inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul) + { + return static_cast<upgrade_lock<Mutex>&&>(ul); + } #endif template<typename Mutex> void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) @@ -678,6 +753,39 @@ namespace boost { try_lock(); } +#ifdef BOOST_HAS_RVALUE_REFS + upgrade_lock(upgrade_lock<Mutex>&& other): + m(other.m),is_locked(other.is_locked) + { + other.is_locked=false; + other.m=0; + } + + upgrade_lock(unique_lock<Mutex>&& other): + m(other.m),is_locked(other.is_locked) + { + if(is_locked) + { + m->unlock_and_lock_upgrade(); + } + other.is_locked=false; + other.m=0; + } + + upgrade_lock& operator=(upgrade_lock<Mutex>&& other) + { + upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other)); + swap(temp); + return *this; + } + + upgrade_lock& operator=(unique_lock<Mutex>&& other) + { + upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other)); + swap(temp); + return *this; + } +#else upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): m(other->m),is_locked(other->is_locked) { @@ -720,6 +828,7 @@ namespace boost swap(temp); return *this; } +#endif void swap(upgrade_lock& other) { @@ -824,6 +933,20 @@ namespace boost } } +#ifdef BOOST_HAS_RVALUE_REFS + upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other): + source(other.source),exclusive(move(other.exclusive)) + { + other.source=0; + } + + upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other) + { + upgrade_to_unique_lock temp(other); + swap(temp); + return *this; + } +#else upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other): source(other->source),exclusive(move(other->exclusive)) { @@ -836,6 +959,7 @@ namespace boost swap(temp); return *this; } +#endif void swap(upgrade_to_unique_lock& other) { std::swap(source,other.source); @@ -923,15 +1047,15 @@ namespace boost return *this; } - void swap(try_lock_wrapper& other) - { - base::swap(other); - } void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other) { base::swap(*other); } #endif + void swap(try_lock_wrapper& other) + { + base::swap(other); + } void lock() { base::lock(); @@ -1116,7 +1240,7 @@ namespace boost { unsigned const lock_count=2; unsigned lock_first=0; - while(true) + for(;;) { switch(lock_first) { @@ -1169,7 +1293,7 @@ namespace boost { unsigned const lock_count=3; unsigned lock_first=0; - while(true) + for(;;) { switch(lock_first) { @@ -1201,7 +1325,7 @@ namespace boost { unsigned const lock_count=4; unsigned lock_first=0; - while(true) + for(;;) { switch(lock_first) { @@ -1239,7 +1363,7 @@ namespace boost { unsigned const lock_count=5; unsigned lock_first=0; - while(true) + for(;;) { switch(lock_first) { diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp index 8e8f5b5..9c5bee2 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp @@ -3,7 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-10 Anthony Williams #include "timespec.hpp" #include "pthread_mutex_scoped_lock.hpp" @@ -14,17 +14,55 @@ namespace boost { + namespace this_thread + { + void BOOST_THREAD_DECL interruption_point(); + } + + namespace thread_cv_detail + { + template<typename MutexType> + struct lock_on_exit + { + MutexType* m; + + lock_on_exit(): + m(0) + {} + + void activate(MutexType& m_) + { + m_.unlock(); + m=&m_; + } + ~lock_on_exit() + { + if(m) + { + m->lock(); + } + } + }; + } + inline void condition_variable::wait(unique_lock<mutex>& m) { - detail::interruption_checker check_for_interruption(&cond); - BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle())); + thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + int const res=pthread_cond_wait(&cond,&internal_mutex); + BOOST_ASSERT(!res); + this_thread::interruption_point(); } inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until) { - detail::interruption_checker check_for_interruption(&cond); + thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); struct timespec const timeout=detail::get_timespec(wait_until); - int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout); + int const cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + this_thread::interruption_point(); if(cond_res==ETIMEDOUT) { return false; @@ -35,11 +73,13 @@ namespace boost inline void condition_variable::notify_one() { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_signal(&cond)); } inline void condition_variable::notify_all() { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } @@ -48,8 +88,8 @@ namespace boost pthread_mutex_t internal_mutex; pthread_cond_t cond; - condition_variable_any(condition_variable&); - condition_variable_any& operator=(condition_variable&); + condition_variable_any(condition_variable_any&); + condition_variable_any& operator=(condition_variable_any&); public: condition_variable_any() @@ -77,13 +117,11 @@ namespace boost { int res=0; { - detail::interruption_checker check_for_interruption(&cond); - { - boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); - m.unlock(); - res=pthread_cond_wait(&cond,&internal_mutex); - } - m.lock(); + thread_cv_detail::lock_on_exit<lock_type> guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + res=pthread_cond_wait(&cond,&internal_mutex); + this_thread::interruption_point(); } if(res) { @@ -103,13 +141,11 @@ namespace boost struct timespec const timeout=detail::get_timespec(wait_until); int res=0; { - detail::interruption_checker check_for_interruption(&cond); - { - boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); - m.unlock(); - res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); - } - m.lock(); + thread_cv_detail::lock_on_exit<lock_type> guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + this_thread::interruption_point(); } if(res==ETIMEDOUT) { 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 59908f4..365f511 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp @@ -20,6 +20,7 @@ namespace boost class condition_variable { private: + pthread_mutex_t internal_mutex; pthread_cond_t cond; condition_variable(condition_variable&); @@ -28,14 +29,21 @@ namespace boost public: condition_variable() { - int const res=pthread_cond_init(&cond,NULL); + int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { boost::throw_exception(thread_resource_error()); } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + boost::throw_exception(thread_resource_error()); + } } ~condition_variable() { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); BOOST_VERIFY(!pthread_cond_destroy(&cond)); } @@ -47,7 +55,8 @@ namespace boost while(!pred()) wait(m); } - bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until); + inline bool timed_wait(unique_lock<mutex>& m, + boost::system_time const& wait_until); bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until) { return timed_wait(m,system_time(wait_until)); diff --git a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp index 1f7f790..2a326d7 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp @@ -27,10 +27,11 @@ namespace boost { - class mutex: - boost::noncopyable + class mutex { private: + mutex(mutex const&); + mutex& operator=(mutex const&); pthread_mutex_t m; public: mutex() @@ -48,7 +49,11 @@ namespace boost void lock() { - BOOST_VERIFY(!pthread_mutex_lock(&m)); + int const res=pthread_mutex_lock(&m); + if(res) + { + boost::throw_exception(lock_error(res)); + } } void unlock() @@ -59,7 +64,11 @@ namespace boost bool try_lock() { int const res=pthread_mutex_trylock(&m); - BOOST_ASSERT(!res || res==EBUSY); + if(res && (res!=EBUSY)) + { + boost::throw_exception(lock_error(res)); + } + return !res; } @@ -75,10 +84,12 @@ namespace boost typedef mutex try_mutex; - class timed_mutex: - boost::noncopyable + class timed_mutex { private: + timed_mutex(timed_mutex const&); + timed_mutex& operator=(timed_mutex const&); + private: pthread_mutex_t m; #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK pthread_cond_t cond; diff --git a/3rdParty/Boost/src/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/3rdParty/Boost/src/boost/thread/pthread/pthread_mutex_scoped_lock.hpp index 2407f91..cdbf8c6 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/pthread_mutex_scoped_lock.hpp @@ -18,15 +18,25 @@ namespace boost class pthread_mutex_scoped_lock { pthread_mutex_t* m; + bool locked; public: explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): - m(m_) + m(m_),locked(true) { BOOST_VERIFY(!pthread_mutex_lock(m)); } - ~pthread_mutex_scoped_lock() + void unlock() { BOOST_VERIFY(!pthread_mutex_unlock(m)); + locked=false; + } + + ~pthread_mutex_scoped_lock() + { + if(locked) + { + unlock(); + } } }; diff --git a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp index ad3b7e1..4158a57 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp @@ -26,18 +26,30 @@ #endif #endif +#if defined(BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) +#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK +#endif + #include <boost/config/abi_prefix.hpp> namespace boost { - class recursive_mutex: - boost::noncopyable + class recursive_mutex { private: + recursive_mutex(recursive_mutex const&); + recursive_mutex& operator=(recursive_mutex const&); pthread_mutex_t m; +#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; +#endif public: recursive_mutex() { +#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE pthread_mutexattr_t attr; int const init_attr_res=pthread_mutexattr_init(&attr); @@ -48,21 +60,42 @@ namespace boost int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); if(set_attr_res) { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); boost::throw_exception(thread_resource_error()); } int const res=pthread_mutex_init(&m,&attr); if(res) { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); boost::throw_exception(thread_resource_error()); } BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error()); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error()); + } + is_locked=false; + count=0; +#endif } ~recursive_mutex() { BOOST_VERIFY(!pthread_mutex_destroy(&m)); +#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#endif } - + +#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE void lock() { BOOST_VERIFY(!pthread_mutex_lock(&m)); @@ -79,25 +112,70 @@ namespace boost BOOST_ASSERT(!res || res==EBUSY); return !res; } - typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle() { return &m; } +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return; + } + + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(!--count) + { + is_locked=false; + } + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && !pthread_equal(owner,pthread_self())) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + +#endif + typedef unique_lock<recursive_mutex> scoped_lock; typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock; }; typedef recursive_mutex recursive_try_mutex; - class recursive_timed_mutex: - boost::noncopyable + class recursive_timed_mutex { private: + recursive_timed_mutex(recursive_timed_mutex const&); + recursive_timed_mutex& operator=(recursive_timed_mutex const&); + private: pthread_mutex_t m; -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK pthread_cond_t cond; bool is_locked; pthread_t owner; @@ -106,7 +184,7 @@ namespace boost public: recursive_timed_mutex() { -#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK pthread_mutexattr_t attr; int const init_attr_res=pthread_mutexattr_init(&attr); @@ -146,7 +224,7 @@ namespace boost ~recursive_timed_mutex() { BOOST_VERIFY(!pthread_mutex_destroy(&m)); -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } @@ -157,7 +235,7 @@ namespace boost return timed_lock(get_system_time()+relative_time); } -#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK void lock() { BOOST_VERIFY(!pthread_mutex_lock(&m)); diff --git a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp index 30440eb..bc26282 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp @@ -225,7 +225,7 @@ namespace boost template<typename TimeDuration> bool timed_lock_upgrade(TimeDuration const & relative_time) { - return timed_lock(get_system_time()+relative_time); + return timed_lock_upgrade(get_system_time()+relative_time); } bool try_lock_upgrade() diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp index 730c77c..1bee28b 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp @@ -12,6 +12,7 @@ #include <boost/thread/mutex.hpp> #include <boost/optional.hpp> #include <pthread.h> +#include <boost/assert.hpp> #include "condition_variable_fwd.hpp" #include <map> @@ -55,6 +56,7 @@ namespace boost 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; thread_data_base(): @@ -76,6 +78,8 @@ namespace boost class interruption_checker { thread_data_base* const thread_info; + pthread_mutex_t* m; + bool set; void check_for_interruption() { @@ -88,23 +92,35 @@ namespace boost void operator=(interruption_checker&); public: - explicit interruption_checker(pthread_cond_t* cond): - thread_info(detail::get_current_thread_data()) + explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): + thread_info(detail::get_current_thread_data()),m(cond_mutex), + set(thread_info && thread_info->interrupt_enabled) { - if(thread_info && thread_info->interrupt_enabled) + if(set) { lock_guard<mutex> guard(thread_info->data_mutex); check_for_interruption(); + thread_info->cond_mutex=cond_mutex; thread_info->current_cond=cond; + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + else + { + BOOST_VERIFY(!pthread_mutex_lock(m)); } } ~interruption_checker() { - if(thread_info && thread_info->interrupt_enabled) + if(set) { + BOOST_VERIFY(!pthread_mutex_unlock(m)); lock_guard<mutex> guard(thread_info->data_mutex); + thread_info->cond_mutex=NULL; thread_info->current_cond=NULL; - check_for_interruption(); + } + else + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); } } }; diff --git a/3rdParty/Boost/src/boost/thread/thread_time.hpp b/3rdParty/Boost/src/boost/thread/thread_time.hpp index 8b557d5..ffdcf85 100644 --- a/3rdParty/Boost/src/boost/thread/thread_time.hpp +++ b/3rdParty/Boost/src/boost/thread/thread_time.hpp @@ -6,6 +6,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include <boost/date_time/time_clock.hpp> #include <boost/date_time/microsec_time_clock.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp> @@ -17,7 +18,11 @@ namespace boost inline system_time get_system_time() { +#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) return boost::date_time::microsec_clock<system_time>::universal_time(); +#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + return boost::date_time::second_clock<system_time>::universal_time(); +#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) } namespace detail diff --git a/3rdParty/Boost/src/boost/thread/tss.hpp b/3rdParty/Boost/src/boost/thread/tss.hpp index e38e3e9..c920024 100644 --- a/3rdParty/Boost/src/boost/thread/tss.hpp +++ b/3rdParty/Boost/src/boost/thread/tss.hpp @@ -62,6 +62,8 @@ namespace boost boost::shared_ptr<detail::tss_cleanup_function> cleanup; public: + typedef T element_type; + thread_specific_ptr(): cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>()) {} diff --git a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp index efe6241..d59fbfa 100644 --- a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp @@ -20,9 +20,11 @@ namespace boost } class mutex: - boost::noncopyable, public ::boost::detail::underlying_mutex { + private: + mutex(mutex const&); + mutex& operator=(mutex const&); public: mutex() { @@ -40,9 +42,11 @@ namespace boost typedef mutex try_mutex; class timed_mutex: - boost::noncopyable, public ::boost::detail::basic_timed_mutex { + private: + timed_mutex(timed_mutex const&); + timed_mutex& operator=(timed_mutex const&); public: timed_mutex() { diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp index c25f9ab..e1b1843 100644 --- a/3rdParty/Boost/src/boost/thread/win32/once.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp @@ -34,42 +34,85 @@ namespace boost { long status; long count; - long throw_count; - void* event_handle; + }; + +#define BOOST_ONCE_INIT {0,0} + + namespace detail + { +#ifdef BOOST_NO_ANSI_APIS + typedef wchar_t once_char_type; +#else + typedef char once_char_type; +#endif + unsigned const once_mutex_name_fixed_length=54; + unsigned const once_mutex_name_length=once_mutex_name_fixed_length+ + sizeof(void*)*2+sizeof(unsigned long)*2+1; - ~once_flag() + template <class I> + void int_to_string(I p, once_char_type* buf) { - if(count) + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) { - BOOST_ASSERT(count==throw_count); +#ifdef BOOST_NO_ANSI_APIS + once_char_type const a=L'A'; +#else + once_char_type const a='A'; +#endif + *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f); } + *buf = 0; + } + + inline void name_once_mutex(once_char_type* mutex_name,void* flag_address) + { +#ifdef BOOST_NO_ANSI_APIS + static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#else + static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#endif + BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == + (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); - void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event_handle,0); - if(old_event) + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); + detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), + mutex_name + once_mutex_name_fixed_length); + detail::int_to_string(win32::GetCurrentProcessId(), + mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); + } + + inline void* open_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) { - ::boost::detail::win32::CloseHandle(old_event); + name_once_mutex(mutex_name,flag_address); } + +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::OpenEventW( +#else + return ::boost::detail::win32::OpenEventA( +#endif + ::boost::detail::win32::synchronize | + ::boost::detail::win32::event_modify_state, + false, + mutex_name); } - }; -#define BOOST_ONCE_INIT {0,0,0,0} - - namespace detail - { - inline void* allocate_event_handle(void*& handle) + inline void* create_once_event(once_char_type* mutex_name,void* flag_address) { - void* const new_handle=::boost::detail::win32::create_anonymous_event( - ::boost::detail::win32::manual_reset_event, - ::boost::detail::win32::event_initially_reset); - - void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle, - new_handle,0); - if(event_handle) + if(!*mutex_name) { - ::boost::detail::win32::CloseHandle(new_handle); - return event_handle; + name_once_mutex(mutex_name,flag_address); } - return new_handle; +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::CreateEventW( +#else + return ::boost::detail::win32::CreateEventA( +#endif + 0,::boost::detail::win32::manual_reset_event, + ::boost::detail::win32::event_initially_reset, + mutex_name); } } @@ -83,8 +126,9 @@ namespace boost long const running_value=0x7f0725e3; long status; bool counted=false; - void* event_handle=0; - long throw_count=0; + detail::win32::handle_manager event_handle; + detail::once_char_type mutex_name[detail::once_mutex_name_length]; + mutex_name[0]=0; while((status=::boost::detail::interlocked_read_acquire(&flag.status)) !=function_complete_flag_value) @@ -96,7 +140,7 @@ namespace boost { if(!event_handle) { - event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); + event_handle=detail::open_once_event(mutex_name,&flag); } if(event_handle) { @@ -112,25 +156,20 @@ namespace boost if(!event_handle && (::boost::detail::interlocked_read_acquire(&flag.count)>1)) { - event_handle=::boost::detail::allocate_event_handle(flag.event_handle); + event_handle=detail::create_once_event(mutex_name,&flag); } if(event_handle) { ::boost::detail::win32::SetEvent(event_handle); } - throw_count=::boost::detail::interlocked_read_acquire(&flag.throw_count); break; } catch(...) { - if(counted) - { - BOOST_INTERLOCKED_INCREMENT(&flag.throw_count); - } BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); if(!event_handle) { - event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); + event_handle=detail::open_once_event(mutex_name,&flag); } if(event_handle) { @@ -149,31 +188,15 @@ namespace boost { break; } - event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); if(!event_handle) { - event_handle=::boost::detail::allocate_event_handle(flag.event_handle); + event_handle=detail::create_once_event(mutex_name,&flag); continue; } } BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( event_handle,::boost::detail::win32::infinite)); } - if(counted || throw_count) - { - if(!BOOST_INTERLOCKED_EXCHANGE_ADD(&flag.count,(counted?-1:0)-throw_count)) - { - if(!event_handle) - { - event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); - } - if(event_handle) - { - BOOST_INTERLOCKED_EXCHANGE_POINTER(&flag.event_handle,0); - ::boost::detail::win32::CloseHandle(event_handle); - } - } - } } } diff --git a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp index 2360a92..e83d3bc 100644 --- a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp @@ -20,9 +20,11 @@ namespace boost { class recursive_mutex: - boost::noncopyable, public ::boost::detail::basic_recursive_mutex { + private: + recursive_mutex(recursive_mutex const&); + recursive_mutex& operator=(recursive_mutex const&); public: recursive_mutex() { @@ -40,9 +42,11 @@ namespace boost typedef recursive_mutex recursive_try_mutex; class recursive_timed_mutex: - boost::noncopyable, public ::boost::detail::basic_recursive_timed_mutex { + private: + recursive_timed_mutex(recursive_timed_mutex const&); + recursive_timed_mutex& operator=(recursive_timed_mutex const&); public: recursive_timed_mutex() { diff --git a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp index 58e8093..58fc622 100644 --- a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp @@ -19,10 +19,12 @@ namespace boost { - class shared_mutex: - private boost::noncopyable + class shared_mutex { private: + shared_mutex(shared_mutex const&); + shared_mutex& operator=(shared_mutex const&); + private: struct state_data { unsigned shared_count:11, @@ -49,33 +51,35 @@ namespace boost return *reinterpret_cast<T const*>(&res); } + enum + { + unlock_sem = 0, + exclusive_sem = 1 + }; + state_data state; detail::win32::handle semaphores[2]; - detail::win32::handle &unlock_sem; - detail::win32::handle &exclusive_sem; detail::win32::handle upgrade_sem; void release_waiters(state_data old_state) { if(old_state.exclusive_waiting) { - BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0); + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); } if(old_state.shared_waiting || old_state.exclusive_waiting) { - BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); } } public: - shared_mutex(): - unlock_sem(semaphores[0]), - exclusive_sem(semaphores[1]) + shared_mutex() { - unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); state_data state_={0}; state=state_; @@ -84,8 +88,8 @@ namespace boost ~shared_mutex() { detail::win32::CloseHandle(upgrade_sem); - detail::win32::CloseHandle(unlock_sem); - detail::win32::CloseHandle(exclusive_sem); + detail::win32::CloseHandle(semaphores[unlock_sem]); + detail::win32::CloseHandle(semaphores[exclusive_sem]); } bool try_lock_shared() @@ -97,6 +101,10 @@ namespace boost if(!new_state.exclusive && !new_state.exclusive_waiting_blocked) { ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); @@ -131,10 +139,18 @@ namespace boost if(new_state.exclusive || new_state.exclusive_waiting_blocked) { ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } } else { ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); @@ -150,7 +166,7 @@ namespace boost return true; } - unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until)); + unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); if(res==detail::win32::timeout) { for(;;) @@ -166,6 +182,10 @@ namespace boost else { ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); @@ -282,6 +302,11 @@ namespace boost if(new_state.shared_count || new_state.exclusive) { ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + new_state.exclusive_waiting_blocked=true; } else @@ -374,10 +399,18 @@ namespace boost if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) { ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } } else { ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } new_state.upgrade=true; } @@ -394,7 +427,7 @@ namespace boost return; } - BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite)); + BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); } } @@ -411,6 +444,10 @@ namespace boost else { ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } new_state.upgrade=true; } diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp index 1a6a1e0..c86b0fa 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp @@ -144,6 +144,11 @@ namespace boost start(0),milliseconds(~uintmax_t(0)),relative(true) {} }; + + inline unsigned long pin_to_zero(long value) + { + return (value<0)?0u:(unsigned long)value; + } } namespace this_thread @@ -163,7 +168,7 @@ namespace boost template<typename TimeDuration> inline void sleep(TimeDuration const& rel_time) { - interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds())); + interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } inline void sleep(system_time const& abs_time) { diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index 2359c38..9b20e86 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -31,14 +31,18 @@ namespace boost unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; + unsigned const event_modify_state=EVENT_MODIFY_STATE; + unsigned const synchronize=SYNCHRONIZE; # ifdef BOOST_NO_ANSI_APIS using ::CreateMutexW; using ::CreateEventW; + using ::OpenEventW; using ::CreateSemaphoreW; # else using ::CreateMutexA; using ::CreateEventA; + using ::OpenEventA; using ::CreateSemaphoreA; # endif using ::CloseHandle; @@ -100,6 +104,8 @@ namespace boost unsigned const infinite=~0U; unsigned const timeout=258U; handle const invalid_handle_value=(handle)(-1); + unsigned const event_modify_state=2; + unsigned const synchronize=0x100000u; extern "C" { @@ -108,10 +114,12 @@ namespace boost __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*); __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*); __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*); + __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); # else __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); + __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); # endif __declspec(dllimport) int __stdcall CloseHandle(void*); __declspec(dllimport) int __stdcall ReleaseMutex(void*); |