summaryrefslogtreecommitdiff
path: root/boost/thread/win32
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/win32')
-rw-r--r--boost/thread/win32/condition_variable.hpp81
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>