diff options
Diffstat (limited to 'boost/thread/win32')
-rw-r--r-- | boost/thread/win32/condition_variable.hpp | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/boost/thread/win32/condition_variable.hpp b/boost/thread/win32/condition_variable.hpp index 23e9e44484..f4b535f74b 100644 --- a/boost/thread/win32/condition_variable.hpp +++ b/boost/thread/win32/condition_variable.hpp @@ -142,32 +142,38 @@ namespace boost struct relocker { BOOST_THREAD_NO_COPYABLE(relocker) - lock_type& lock; - bool unlocked; + lock_type& _lock; + bool _unlocked; relocker(lock_type& lock_): - lock(lock_),unlocked(false) + _lock(lock_), _unlocked(false) {} void unlock() { - lock.unlock(); - unlocked=true; + if ( ! _unlocked ) + { + _lock.unlock(); + _unlocked=true; + } } - ~relocker() + void lock() { - if(unlocked) - { - lock.lock(); - } - + if ( _unlocked ) + { + _lock.lock(); + _unlocked=false; + } + } + ~relocker() BOOST_NOEXCEPT_IF(false) + { + lock(); } }; entry_ptr get_wait_entry() { - boost::lock_guard<boost::mutex> internal_lock(internal_mutex); - + boost::lock_guard<boost::mutex> lk(internal_mutex); if(!wake_sem) { wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); @@ -190,18 +196,32 @@ namespace boost struct entry_manager { - entry_ptr const entry; + entry_ptr entry; boost::mutex& internal_mutex; + BOOST_THREAD_NO_COPYABLE(entry_manager) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + entry_manager(entry_ptr&& entry_, boost::mutex& mutex_): + entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_) + {} +#else entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): entry(entry_), internal_mutex(mutex_) {} +#endif - ~entry_manager() + void remove_waiter() { + if (entry) { boost::lock_guard<boost::mutex> internal_lock(internal_mutex); entry->remove_waiter(); + entry.reset(); + } + } + ~entry_manager() BOOST_NOEXCEPT_IF(false) + { + remove_waiter(); } list_entry* operator->() @@ -215,23 +235,24 @@ namespace boost template<typename lock_type> bool do_wait(lock_type& lock,timeout abs_time) { - relocker<lock_type> locker(lock); - - entry_manager entry(get_wait_entry(), internal_mutex); - - locker.unlock(); + relocker<lock_type> locker(lock); + entry_manager entry(get_wait_entry(), internal_mutex); + locker.unlock(); - bool woken=false; - while(!woken) - { - if(!entry->wait(abs_time)) - { - return false; - } + bool woken=false; + while(!woken) + { + if(!entry->wait(abs_time)) + { + return false; + } - woken=entry->woken(); - } - return woken; + woken=entry->woken(); + } + // do it here to avoid throwing on the destructor + entry->remove_waiter(); + locker.lock(); + return woken; } template<typename lock_type,typename predicate_type> |