Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86211 - in trunk/boost/sync: . detail/condition_variables detail/mutexes exceptions
From: andrey.semashev_at_[hidden]
Date: 2013-10-09 07:21:52


Author: andysem
Date: 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013)
New Revision: 86211
URL: http://svn.boost.org/trac/boost/changeset/86211

Log:
Proceeding with Windows CV implementation.

Added:
   trunk/boost/sync/exceptions/wait_error.hpp (contents, props changed)
Text files modified:
   trunk/boost/sync/detail/condition_variables/basic_condition_variable_windows.hpp | 520 ++++++++++++++++++++++++---------------
   trunk/boost/sync/detail/condition_variables/condition_variable_posix.hpp | 26 +-
   trunk/boost/sync/detail/mutexes/timed_mutex_windows.hpp | 6
   trunk/boost/sync/exceptions.hpp | 1
   trunk/boost/sync/exceptions/wait_error.hpp | 58 ++++
   5 files changed, 390 insertions(+), 221 deletions(-)

Modified: trunk/boost/sync/detail/condition_variables/basic_condition_variable_windows.hpp
==============================================================================
--- trunk/boost/sync/detail/condition_variables/basic_condition_variable_windows.hpp Tue Oct 8 17:26:30 2013 (r86210)
+++ trunk/boost/sync/detail/condition_variables/basic_condition_variable_windows.hpp 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013) (r86211)
@@ -19,22 +19,17 @@
 
 #include <limits.h>
 #include <cstddef>
-#include <vector>
-#include <algorithm>
 #include <boost/assert.hpp>
-#include <boost/smart_ptr/intrusive_ptr.hpp>
-#include <boost/smart_ptr/intrusive_ref_counter.hpp>
 #include <boost/detail/winapi/synchronization.hpp>
 #include <boost/sync/detail/config.hpp>
-#include <boost/sync/locks/unique_lock_fwd.hpp>
-#include <boost/sync/exceptions/runtime_exception.hpp>
+#include <boost/sync/exceptions/wait_error.hpp>
 #include <boost/sync/exceptions/resource_error.hpp>
 #include <boost/sync/detail/throw_exception.hpp>
 #include <boost/sync/detail/time_traits.hpp>
 #include <boost/sync/detail/time_units.hpp>
 #include <boost/sync/detail/interlocked.hpp>
-#include <boost/sync/detail/auto_handle.hpp>
 #include <boost/sync/detail/waitable_timer.hpp>
+#include <boost/sync/locks/unique_lock_fwd.hpp>
 #include <boost/sync/locks/lock_guard.hpp>
 #include <boost/sync/mutexes/mutex.hpp>
 #include <boost/sync/condition_variables/cv_status.hpp>
@@ -52,127 +47,59 @@
 
 namespace windows {
 
-class cv_list_entry :
- public intrusive_ref_counter< cv_list_entry >
+class basic_condition_variable
 {
 private:
- auto_handle m_semaphore;
- auto_handle m_wake_sem;
- long m_waiters;
- bool m_notified;
-
-public:
- explicit cv_list_entry(auto_handle const& wake_sem):
- m_waiters(1),
- m_notified(false)
- {
- m_semaphore.reset(boost::detail::winapi::create_anonymous_semaphore(0, LONG_MAX));
- if (!m_semaphore)
- {
- const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
- BOOST_SYNC_DETAIL_THROW(resource_error, (err)("boost::sync::condition_variable: failed to create a semaphore"));
- }
-
- m_wake_sem.reset(wake_sem.duplicate());
- if (!m_wake_sem)
- {
- const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
- BOOST_SYNC_DETAIL_THROW(resource_error, (err)("boost::sync::condition_variable: failed to duplicate a semaphore handle"));
- }
- }
-
- static bool no_waiters(intrusive_ptr< cv_list_entry > const& entry)
- {
- return interlocked_read_acquire(&entry->m_waiters) == 0;
- }
-
- void add_waiter()
- {
- BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&m_waiters, 1);
- }
-
- void remove_waiter()
- {
- BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&m_waiters, -1);
- }
-
- void release(unsigned count_to_release)
- {
- m_notified = true;
- boost::detail::winapi::ReleaseSemaphore(m_semaphore, count_to_release, 0);
- }
-
- void release_waiters()
- {
- release(interlocked_read_acquire(&m_waiters));
- }
-
- bool is_notified() const
- {
- return m_notified;
- }
-
- void wait()
- {
- const boost::detail::winapi::DWORD_ res = boost::detail::winapi::WaitForSingleObject(m_semaphore, boost::detail::winapi::infinite);
- if (res != boost::detail::winapi::wait_object_0)
- {
- const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
- BOOST_SYNC_DETAIL_THROW(runtime_exception, (err)("boost::sync::condition_variable wait failed in WaitForSingleObject"));
- }
- }
-
- bool timed_wait(sync::detail::system_time_point const& t)
- {
-
- }
+ typedef boost::sync::mutex mutex_type;
 
- bool timed_wait(sync::detail::system_duration t)
- {
- sync::detail::system_duration::native_type time_left = t.get();
- while (time_left > 0)
- {
- const boost::detail::winapi::DWORD_ dur = time_left > boost::detail::winapi::max_non_infinite_wait ?
- boost::detail::winapi::max_non_infinite_wait : static_cast< boost::detail::winapi::DWORD_ >(time_left);
- const boost::detail::winapi::DWORD_ res = boost::detail::winapi::WaitForSingleObject(m_semaphore, dur);
- switch (res)
+ /*!
+ * \brief An entry of the list of semaphores to block and release threads.
+ *
+ * The semaphores are organized in a doubly linked list so that it is guaranteed that waits are never
+ * performed on the semaphores that are participating in ongoing notifications. This is needed because
+ * unblocking from a semaphore and updating internal thread counters is not atomic, and the following
+ * scenario is possible:
+ *
+ * 1. Threads A and B are blocked on the CV.
+ * 2. Thread C calls notify_all(), the semaphore is released (set to value 2).
+ * 3. Thread D calls wait(). It may enter WaitForSingleObject() before thread A or B is released by OS,
+ * reducing the counter of the semaphore and leaving one of the threads blocked. This makes thread D
+ * to be notified by thread C and either thread A or B being left blocked.
+ *
+ * In the current implementation, thread D would have to create a new semaphore to block on. The semaphores
+ * are reusable, so that when the notification is complete, it can be used for waiting again.
+ */
+ struct waiter_state
+ {
+ // Pointers to the adjacent nodes in the list
+ waiter_state* m_prev, *m_next;
+ // Semaphore to block on
+ boost::detail::winapi::HANDLE_ m_semaphore;
+ // The number of blocked threads on this semaphore and the number of threads that are in the process of being woken
+ long m_waiter_count, m_notify_count;
+
+ waiter_state()
+ {
+ m_prev = m_next = this;
+ m_semaphore = boost::detail::winapi::create_anonymous_semaphore(NULL, 0, LONG_MAX);
+ if (!m_semaphore)
             {
- case boost::detail::winapi::wait_object_0:
- return true;
-
- case boost::detail::winapi::wait_timeout:
- time_left -= dur;
- break;
-
- default:
- {
- const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
- BOOST_SYNC_DETAIL_THROW(runtime_exception, (res)("boost::sync::condition_variable timed_wait failed in WaitForSingleObject"));
- }
+ const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ BOOST_SYNC_DETAIL_THROW(resource_error, (err)("condition_variable failed to create a semaphore"));
             }
+ m_waiter_count = m_notify_count = 0;
         }
- return false;
- }
-
- bool woken()
- {
- unsigned long const woken_result = boost::detail::winapi::WaitForSingleObject(m_wake_sem, 0);
- BOOST_ASSERT((woken_result == boost::detail::winapi::timeout) || (woken_result == 0));
- return woken_result == 0;
- }
 
- BOOST_DELETED_FUNCTION(cv_list_entry(cv_list_entry const&))
- BOOST_DELETED_FUNCTION(cv_list_entry& operator= (cv_list_entry const&))
-};
-
-class basic_condition_variable
-{
-private:
- typedef boost::sync::mutex mutex_type;
+ ~waiter_state()
+ {
+ BOOST_VERIFY(boost::detail::winapi::CloseHandle(m_semaphore) != 0);
+ }
 
- typedef boost::intrusive_ptr< cv_list_entry > entry_ptr;
- typedef std::vector< entry_ptr > generation_list;
+ BOOST_DELETED_FUNCTION(waiter_state(waiter_state const&))
+ BOOST_DELETED_FUNCTION(waiter_state& operator= (waiter_state const&))
+ };
 
+ //! A scope guard that automatically locks the lock object on destructor
     template< typename Lockable >
     class relocker
     {
@@ -180,7 +107,7 @@
         bool m_unlocked;
 
     public:
- explicit relocker(Lockable& lock) : m_lock(lock), m_unlocked(false)
+ explicit relocker(Lockable& lock) BOOST_NOEXCEPT : m_lock(lock), m_unlocked(false)
         {
         }
 
@@ -190,7 +117,7 @@
                 m_lock.lock();
         }
 
- void unlock()
+ void unlock() BOOST_NOEXCEPT
         {
             m_lock.unlock();
             m_unlocked = true;
@@ -200,148 +127,331 @@
         BOOST_DELETED_FUNCTION(relocker& operator= (relocker const&))
     };
 
- class entry_manager
+private:
+ // Internal mutex to protect internal data
+ mutex_type m_internal_mutex;
+ // Points to the waiter state that will be used to wake up blocked threads
+ waiter_state* m_notify_state;
+ // Points to the waiter state that will be used to block threads
+ waiter_state* m_wait_state;
+ // Total number of blocked threads, in all waiter states
+ long m_total_waiter_count;
+
+public:
+ BOOST_CONSTEXPR basic_condition_variable() BOOST_NOEXCEPT : m_notify_state(NULL), m_wait_state(NULL), m_total_waiter_count(0)
     {
- entry_ptr const m_entry;
- mutex_type& m_internal_mutex;
+ }
 
- public:
- entry_manager(entry_ptr const& entry, mutex_type& mutex):
- m_entry(entry), m_internal_mutex(mutex)
+ ~basic_condition_variable()
+ {
+ BOOST_ASSERT(m_total_waiter_count == 0);
+
+ if (m_notify_state)
         {
+ waiter_state* p = m_notify_state, *const end = p;
+ do
+ {
+ waiter_state* next = p->m_next;
+ delete p;
+ p = next;
+ }
+ while (p != end);
+
+ m_notify_state = NULL;
+ m_wait_state = NULL;
         }
+ }
 
- ~entry_manager() BOOST_NOEXCEPT_IF(false)
+ void notify_one() BOOST_NOEXCEPT
+ {
+ if (interlocked_read_acquire(&m_total_waiter_count))
         {
             boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
- m_entry->remove_waiter();
+ if (m_total_waiter_count == 0)
+ return;
+
+ wake_waiters(1);
         }
+ }
 
- cv_list_entry* operator->() const BOOST_NOEXCEPT
+ void notify_all() BOOST_NOEXCEPT
+ {
+ if (interlocked_read_acquire(&m_total_waiter_count))
         {
- return m_entry.get();
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ if (m_total_waiter_count == 0)
+ return;
+
+ wake_waiters(m_total_waiter_count);
         }
+ }
 
- BOOST_DELETED_FUNCTION(entry_manager(entry_manager const&))
- BOOST_DELETED_FUNCTION(entry_manager& operator= (entry_manager const&))
- };
+ template< typename Lockable >
+ void wait(Lockable& lock)
+ {
+ relocker< Lockable > unlocker(lock);
 
-private:
- mutex_type m_internal_mutex;
- long m_total_count;
+ waiter_state* const state = initiate_wait();
 
- generation_list m_generations;
- auto_handle m_wake_sem;
+ unlocker.unlock();
 
-public:
- BOOST_CONSTEXPR basic_condition_variable() : m_total_count(0)
- {
+ priv_wait(state);
     }
 
- void notify_one() BOOST_NOEXCEPT
+ template< typename Lockable >
+ sync::cv_status timed_wait(Lockable& lock, sync::detail::system_duration t)
     {
- if (interlocked_read_acquire(&m_total_count))
- {
- boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
- if (m_total_count == 0)
- return;
+ relocker< Lockable > unlocker(lock);
 
- wake_waiters(1);
+ waiter_state* const state = initiate_wait();
 
- for(generation_list::iterator it = m_generations.begin(), end = m_generations.end(); it != end; ++it)
- {
- (*it)->release(1);
- }
- m_generations.erase(std::remove_if(m_generations.begin(), m_generations.end(), &cv_list_entry::no_waiters), m_generations.end());
- }
+ unlocker.unlock();
+
+ return priv_timed_wait(state, t);
     }
 
- void notify_all() BOOST_NOEXCEPT
+ template< typename Lockable >
+ sync::cv_status timed_wait(Lockable& lock, sync::detail::system_time_point const& t)
     {
- if (interlocked_read_acquire(&m_total_count))
+ relocker< Lockable > unlocker(lock);
+
+ const boost::detail::winapi::HANDLE_ waitable_timer = sync::detail::windows::get_waitable_timer();
+
+ if (!boost::detail::winapi::SetWaitableTimer(waitable_timer, reinterpret_cast< const boost::detail::winapi::LARGE_INTEGER_* >(&t.get()), 0, NULL, NULL, false))
         {
- boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
- if (m_total_count == 0)
- return;
+ const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ BOOST_SYNC_DETAIL_THROW(wait_error, (err)("condition_variable timed_wait failed to set a timeout"));
+ }
 
- wake_waiters(m_total_count);
+ waiter_state* const state = initiate_wait();
 
- for (generation_list::iterator it = m_generations.begin(), end = m_generations.end(); it != end; ++it)
- {
- (*it)->release_waiters();
- }
- m_generations.clear();
- m_wake_sem.reset();
+ unlocker.unlock();
+
+ return priv_timed_wait(state, waitable_timer);
+ }
+
+ template< typename Lockable, typename TimePoint >
+ sync::cv_status timed_wait(Lockable& lock, sync::detail::chrono_time_point< TimePoint > const& t)
+ {
+ typedef TimePoint time_point;
+ typedef typename time_point::clock clock;
+ typedef typename time_point::duration duration;
+ time_point now = clock::now();
+ while (now < t.get())
+ {
+ if (timed_wait(lock, sync::detail::time_traits< duration >::to_sync_unit(t.get() - now)) == sync::cv_status::no_timeout)
+ return sync::cv_status::no_timeout;
+ now = clock::now();
         }
+ return sync::cv_status::timeout;
     }
 
     BOOST_DELETED_FUNCTION(basic_condition_variable(basic_condition_variable const&))
     BOOST_DELETED_FUNCTION(basic_condition_variable& operator= (basic_condition_variable const&))
 
-protected:
- template< typename Lock >
- bool do_wait(Lock& lock,timeout abs_time)
+private:
+ void wake_waiters(long count_to_wake) BOOST_NOEXCEPT
     {
- relocker< Lock > locker(lock);
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - count_to_wake);
+ if (count_to_wake > 0)
+ {
+ while (true)
+ {
+ const long n = m_notify_state->m_waiter_count - m_notify_state->m_notify_count;
+ if (n > 0)
+ {
+ m_notify_state->m_notify_count += n;
+ boost::detail::winapi::ReleaseSemaphore(m_notify_state->m_semaphore, n, NULL);
+ count_to_wake -= n;
+ }
+
+ if (count_to_wake > 0)
+ m_notify_state = m_notify_state->m_next;
+ else
+ break;
+ }
+ }
+ }
 
- entry_manager entry(get_wait_entry(), m_internal_mutex);
+ waiter_state* initiate_wait()
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
 
- locker.unlock();
+ if (!m_wait_state)
+ {
+ // It's the first waiter
+ waiter_state* p = new waiter_state();
+ m_notify_state = m_wait_state = p;
+ p->m_waiter_count = 1;
+ interlocked_write_release(&m_total_waiter_count, 1);
+ return p;
+ }
 
- bool woken = false;
+ // Find a waiter state without any ongoing notifications
+ waiter_state* const end = m_wait_state;
         do
         {
- if (!entry->wait(abs_time))
+ if (m_wait_state->m_notify_count == 0)
             {
- return false;
+ ++m_wait_state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count + 1);
+ return m_wait_state;
             }
 
- woken = entry->woken();
+ m_wait_state = m_wait_state->m_next;
         }
- while (!woken);
+ while (m_wait_state != end);
+
+ // None found, create a new waiter state
+ m_wait_state = new waiter_state();
 
- return woken;
+ m_wait_state->m_prev = end;
+ waiter_state* const next = end->m_next;
+ m_wait_state->m_next = next;
+ next->m_prev = end->m_next = m_wait_state;
+
+ m_wait_state->m_waiter_count = 1;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count + 1);
+
+ return m_wait_state;
     }
 
- template<typename lock_type,typename predicate_type>
- bool do_wait(lock_type& m, timeout const& abs_time, predicate_type pred)
+ void priv_wait(waiter_state* state)
     {
- while (!pred())
+ while (true)
         {
- if(!do_wait(m, abs_time))
- return pred();
+ const boost::detail::winapi::DWORD_ res = boost::detail::winapi::WaitForSingleObject(state->m_semaphore, boost::detail::winapi::infinite);
+ if (res != boost::detail::winapi::wait_object_0)
+ {
+ const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ --state->m_waiter_count;
+ if (state->m_notify_count > 0)
+ --state->m_notify_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ }
+ BOOST_SYNC_DETAIL_THROW(wait_error, (err)("condition_variable wait failed in WaitForSingleObject"));
+ }
+
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ if (state->m_notify_count > 0)
+ {
+ --state->m_notify_count;
+ --state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ return;
+ }
         }
- return true;
     }
 
-private:
- void wake_waiters(long count_to_wake)
+ sync::cv_status priv_timed_wait(waiter_state* state, sync::detail::system_duration t)
     {
- interlocked_write_release(&m_total_count, m_total_count - count_to_wake);
- boost::detail::winapi::ReleaseSemaphore(m_wake_sem, count_to_wake, 0);
- }
+ sync::detail::system_duration::native_type time_left = t.get();
+ while (time_left > 0)
+ {
+ const boost::detail::winapi::DWORD_ dur = time_left > boost::detail::winapi::max_non_infinite_wait ?
+ boost::detail::winapi::max_non_infinite_wait : static_cast< boost::detail::winapi::DWORD_ >(time_left);
+ const boost::detail::winapi::DWORD_ res = boost::detail::winapi::WaitForSingleObject(state->m_semaphore, dur);
+ switch (res)
+ {
+ case boost::detail::winapi::wait_object_0: // condition variable was signalled
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ if (state->m_notify_count > 0)
+ {
+ --state->m_notify_count;
+ --state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ return sync::cv_status::no_timeout;
+ }
+ }
+ break;
 
- entry_ptr get_wait_entry()
- {
- boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ case boost::detail::winapi::wait_timeout: // timeout expired
+ time_left -= dur;
+ break;
 
- if(!m_wake_sem)
- {
- m_wake_sem = boost::detail::winapi::create_anonymous_semaphore(0, LONG_MAX);
- BOOST_ASSERT(m_wake_sem);
+ default: // error occurred
+ {
+ const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ --state->m_waiter_count;
+ if (state->m_notify_count > 0)
+ --state->m_notify_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ }
+ BOOST_SYNC_DETAIL_THROW(wait_error, (err)("condition_variable wait failed in WaitForSingleObject"));
+ }
+ }
         }
 
- interlocked_write_release(&m_total_count, m_total_count + 1);
- if (m_generations.empty() || m_generations.back()->is_notified())
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ --state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ if (state->m_notify_count > 0)
         {
- entry_ptr new_entry(new cv_list_entry(m_wake_sem));
- m_generations.push_back(new_entry);
- return new_entry;
+ --state->m_notify_count;
+ return sync::cv_status::no_timeout;
         }
- else
+ return sync::cv_status::timeout;
+ }
+
+ sync::cv_status priv_timed_wait(waiter_state* state, boost::detail::winapi::HANDLE_ waitable_timer)
+ {
+ boost::detail::winapi::HANDLE_ handles[2];
+ handles[0] = state->m_semaphore;
+ handles[1] = waitable_timer;
+
+ while (true)
         {
- m_generations.back()->add_waiter();
- return m_generations.back();
+ const boost::detail::winapi::DWORD_ res = boost::detail::winapi::WaitForMultipleObjects(sizeof(handles) / sizeof(*handles), handles, false, boost::detail::winapi::infinite);
+ if (res == boost::detail::winapi::wait_failed)
+ {
+ const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ --state->m_waiter_count;
+ if (state->m_notify_count > 0)
+ --state->m_notify_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ }
+ BOOST_SYNC_DETAIL_THROW(wait_error, (err)("condition_variable timed_wait failed in WaitForMultipleObjects"));
+ }
+
+ switch (res)
+ {
+ case boost::detail::winapi::wait_object_0: // condition variable was signalled
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ if (state->m_notify_count > 0)
+ {
+ --state->m_notify_count;
+ --state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ return sync::cv_status::no_timeout;
+ }
+ }
+ break;
+
+ case boost::detail::winapi::wait_object_0 + 1: // timeout has expired
+ {
+ boost::sync::lock_guard< mutex_type > internal_lock(m_internal_mutex);
+ --state->m_waiter_count;
+ interlocked_write_release(&m_total_waiter_count, m_total_waiter_count - 1);
+ if (state->m_notify_count > 0)
+ {
+ --state->m_notify_count;
+ return sync::cv_status::no_timeout;
+ }
+ return sync::cv_status::timeout;
+ }
+ break;
+
+ default:
+ BOOST_ASSERT(false);
+ }
         }
     }
 };

Modified: trunk/boost/sync/detail/condition_variables/condition_variable_posix.hpp
==============================================================================
--- trunk/boost/sync/detail/condition_variables/condition_variable_posix.hpp Tue Oct 8 17:26:30 2013 (r86210)
+++ trunk/boost/sync/detail/condition_variables/condition_variable_posix.hpp 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013) (r86211)
@@ -23,7 +23,7 @@
 #include <boost/mpl/and.hpp>
 #include <boost/sync/detail/config.hpp>
 #include <boost/sync/locks/unique_lock_fwd.hpp>
-#include <boost/sync/exceptions/runtime_exception.hpp>
+#include <boost/sync/exceptions/wait_error.hpp>
 #include <boost/sync/exceptions/resource_error.hpp>
 #include <boost/sync/traits/is_condition_variable_compatible.hpp>
 #include <boost/sync/detail/pthread.hpp>
@@ -100,7 +100,7 @@
         BOOST_ASSERT(lock.owns_lock());
         int const res = sync::detail::posix::pthread_cond_wait(&m_cond, lock.mutex()->native_handle());
         if (res != 0)
- BOOST_SYNC_DETAIL_THROW(runtime_exception, (res)("boost::sync::condition_variable::wait failed in pthread_cond_wait"));
+ BOOST_SYNC_DETAIL_THROW(wait_error, (res)("boost::sync::condition_variable::wait failed in pthread_cond_wait"));
     }
 
     template< typename Mutex, typename Predicate >
@@ -148,7 +148,7 @@
     }
 
     template< typename Mutex, typename TimePoint >
- typename enable_if< mpl::and_< detail::is_time_tag_of< TimePoint, detail::time_point_tag >, is_condition_variable_compatible< Mutex > >, cv_status >::type
+ typename enable_if< mpl::and_< detail::is_time_tag_of< TimePoint, detail::time_point_tag >, is_condition_variable_compatible< Mutex > >, sync::cv_status >::type
     wait_until(unique_lock< Mutex >& lock, TimePoint const& abs_time)
     {
         BOOST_ASSERT(lock.owns_lock());
@@ -171,7 +171,7 @@
     }
 
     template< typename Mutex, typename Duration >
- typename enable_if< mpl::and_< detail::is_time_tag_of< Duration, detail::time_duration_tag >, is_condition_variable_compatible< Mutex > >, cv_status >::type
+ typename enable_if< mpl::and_< detail::is_time_tag_of< Duration, detail::time_duration_tag >, is_condition_variable_compatible< Mutex > >, sync::cv_status >::type
     wait_for(unique_lock< Mutex >& lock, Duration const& rel_time)
     {
         BOOST_ASSERT(lock.owns_lock());
@@ -202,24 +202,24 @@
 
 private:
     template< typename Mutex >
- cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::system_duration dur)
+ sync::cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::system_duration dur)
     {
         return priv_timed_wait(lock, sync::detail::system_time_point::now() + dur);
     }
 
     template< typename Mutex >
- cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::system_time_point const& t)
+ sync::cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::system_time_point const& t)
     {
         int const res = sync::detail::posix::pthread_cond_timedwait(&m_cond, lock.mutex()->native_handle(), &t.get());
         if (res == ETIMEDOUT)
- return cv_status::timeout;
+ return sync::cv_status::timeout;
         else if (res != 0)
- BOOST_SYNC_DETAIL_THROW(runtime_exception, (res)("boost::sync::condition_variable timedwait failed in pthread_cond_timedwait"));
- return cv_status::no_timeout;
+ BOOST_SYNC_DETAIL_THROW(wait_error, (res)("boost::sync::condition_variable timedwait failed in pthread_cond_timedwait"));
+ return sync::cv_status::no_timeout;
     }
 
     template< typename Mutex, typename TimePoint >
- cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::chrono_time_point< TimePoint > const& t)
+ sync::cv_status priv_timed_wait(unique_lock< Mutex >& lock, sync::detail::chrono_time_point< TimePoint > const& t)
     {
         typedef TimePoint time_point;
         typedef typename time_point::clock clock;
@@ -227,11 +227,11 @@
         time_point now = clock::now();
         while (now < t.get())
         {
- if (priv_timed_wait(lock, sync::detail::time_traits< duration >::to_sync_unit(t.get() - now)) == cv_status::no_timeout)
- return cv_status::no_timeout;
+ if (priv_timed_wait(lock, sync::detail::time_traits< duration >::to_sync_unit(t.get() - now)) == sync::cv_status::no_timeout)
+ return sync::cv_status::no_timeout;
             now = clock::now();
         }
- return cv_status::timeout;
+ return sync::cv_status::timeout;
     }
 };
 

Modified: trunk/boost/sync/detail/mutexes/timed_mutex_windows.hpp
==============================================================================
--- trunk/boost/sync/detail/mutexes/timed_mutex_windows.hpp Tue Oct 8 17:26:30 2013 (r86210)
+++ trunk/boost/sync/detail/mutexes/timed_mutex_windows.hpp 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013) (r86211)
@@ -136,13 +136,13 @@
 
                 switch (res)
                 {
- case boost::detail::winapi::wait_object_0:
+ case boost::detail::winapi::wait_object_0: // event was notified
                     m_mutex.clear_waiting_and_try_lock(old_count);
                     if ((old_count & sync::detail::windows::basic_mutex::lock_flag_value) == 0)
                         return true;
                     break;
 
- case boost::detail::winapi::wait_object_0 + 1:
+ case boost::detail::winapi::wait_object_0 + 1: // timeout has expired
                     BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&m_mutex.m_active_count, -1);
                     return false;
 
@@ -158,7 +158,7 @@
         }
     }
 
- bool priv_timed_lock(sync::detail::system_duration const& t)
+ bool priv_timed_lock(sync::detail::system_duration t)
     {
         long old_count = m_mutex.m_active_count;
         m_mutex.mark_waiting_and_try_lock(old_count);

Modified: trunk/boost/sync/exceptions.hpp
==============================================================================
--- trunk/boost/sync/exceptions.hpp Tue Oct 8 17:26:30 2013 (r86210)
+++ trunk/boost/sync/exceptions.hpp 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013) (r86211)
@@ -23,5 +23,6 @@
 #include <boost/sync/exceptions/runtime_exception.hpp>
 #include <boost/sync/exceptions/resource_error.hpp>
 #include <boost/sync/exceptions/lock_error.hpp>
+#include <boost/sync/exceptions/wait_error.hpp>
 
 #endif // BOOST_SYNC_EXCEPTIONS_HPP_INCLUDED_

Added: trunk/boost/sync/exceptions/wait_error.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/exceptions/wait_error.hpp 2013-10-09 07:21:51 EDT (Wed, 09 Oct 2013) (r86211)
@@ -0,0 +1,58 @@
+/*
+ * 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 2013 Andrey Semashev
+ */
+/*!
+ * \file exceptions/wait_error.hpp
+ *
+ * \brief This header defines the \c wait_error exception.
+ */
+
+#ifndef BOOST_SYNC_EXCEPTIONS_WAIT_ERROR_HPP_INCLUDED_
+#define BOOST_SYNC_EXCEPTIONS_WAIT_ERROR_HPP_INCLUDED_
+
+#include <string>
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/detail/system_error.hpp>
+#include <boost/sync/exceptions/runtime_exception.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+class BOOST_SYMBOL_VISIBLE wait_error :
+ public runtime_exception
+{
+public:
+ explicit wait_error(int sys_err = 0) : runtime_exception(sys_err, "boost::sync::wait_error")
+ {
+ }
+
+ wait_error(int sys_err, const char* what) : runtime_exception(sys_err, what)
+ {
+ }
+
+ wait_error(int sys_err, std::string const& what) : runtime_exception(sys_err, what)
+ {
+ }
+
+ ~wait_error() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ }
+};
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_EXCEPTIONS_WAIT_ERROR_HPP_INCLUDED_


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk