Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85978 - in trunk: boost/sync boost/sync/detail/event libs/sync/test/run
From: tim_at_[hidden]
Date: 2013-09-28 04:58:43


Author: timblechmann
Date: 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013)
New Revision: 85978
URL: http://svn.boost.org/trac/boost/changeset/85978

Log:
sync: event - split event into auto_reset_event and manual_reset_event

Text files modified:
   trunk/boost/sync/detail/event/event_autoreset_semaphore.hpp | 55 +++----
   trunk/boost/sync/detail/event/event_emulation.hpp | 141 ++++++++++++++++---
   trunk/boost/sync/detail/event/event_futex.hpp | 279 ++++++++++++++++++++++-----------------
   trunk/boost/sync/detail/event/event_mach.hpp | 91 +++---------
   trunk/boost/sync/detail/event/event_windows.hpp | 44 +++++
   trunk/boost/sync/event.hpp | 107 +++++++++++++--
   trunk/libs/sync/test/run/event_test.cpp | 22 ++-
   7 files changed, 475 insertions(+), 264 deletions(-)

Modified: trunk/boost/sync/detail/event/event_autoreset_semaphore.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_autoreset_semaphore.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/detail/event/event_autoreset_semaphore.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -28,85 +28,84 @@
 
 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class event
+class auto_reset_event
 {
- BOOST_DELETED_FUNCTION(event(event const&))
- BOOST_DELETED_FUNCTION(event& operator=(event const&));
+ BOOST_DELETED_FUNCTION(auto_reset_event(auto_reset_event const&))
+ BOOST_DELETED_FUNCTION(auto_reset_event& operator=(auto_reset_event const&));
 
 public:
- event() : m_state(0)
- {
- }
+ auto_reset_event():
+ m_state(0)
+ {}
 
     void post() BOOST_NOEXCEPT
     {
- int32_t old_state = m_state.load(detail::atomic_ns::memory_order_acquire);
- if (old_state >= 0)
- {
- for (;;)
- {
- if (m_state.compare_exchange_weak( old_state, old_state - 1, detail::atomic_ns::memory_order_release, detail::atomic_ns::memory_order_acquire))
- {
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int32_t old_state = m_state.load(memory_order_acquire);
+ if (old_state >= 0) {
+ for (;;) {
+ if (m_state.compare_exchange_weak( old_state, old_state - 1, memory_order_release, memory_order_acquire)) {
                     m_sem.post();
                     return; // avoid unnecessary fence
                 }
 
                 if (old_state < 0)
- break; // someone else has set the event with no waiters
+ break; // someone else has set the auto_reset_event with no waiters
 
                 detail::pause();
             }
         }
 
- detail::atomic_ns::atomic_thread_fence(detail::atomic_ns::memory_order_release);
- }
-
- void reset() BOOST_NOEXCEPT
- {
- m_state.store(0, detail::atomic_ns::memory_order_relaxed);
+ atomic_thread_fence( memory_order_release );
     }
 
     void wait()
     {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
+ m_state.fetch_add(1, memory_order_acquire);
         m_sem.wait();
     }
 
     bool try_wait()
     {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+
+ m_state.fetch_add(1, memory_order_acquire);
 
         const bool wait_successful = m_sem.try_wait();
         if (wait_successful)
             return true;
 
- m_state.fetch_add(-1, detail::atomic_ns::memory_order_relaxed);
+ m_state.fetch_add(-1, memory_order_relaxed);
         return false;
     }
 
     template <typename Duration>
- bool try_wait_for(const chrono::duration<Rep, Period> & duration)
+ bool try_wait_for(const Duration & duration)
     {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+
+ m_state.fetch_add(1, memory_order_acquire);
 
         const bool wait_successful = m_sem.try_wait_for( duration );
         if (wait_successful)
             return true;
 
- m_state.fetch_add(-1, detail::atomic_ns::memory_order_relaxed);
+ m_state.fetch_add(-1, memory_order_relaxed);
         return false;
     }
 
     template <typename Timepoint>
     bool try_wait_until(const Timepoint & timeout )
     {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+
+ m_state.fetch_add(1, memory_order_acquire);
 
         const bool wait_successful = m_sem.try_wait_until( timeout );
         if (wait_successful)
             return true;
 
- m_state.fetch_add(-1, detail::atomic_ns::memory_order_relaxed);
+ m_state.fetch_add(-1, memory_order_relaxed);
         return false;
     }
 

Modified: trunk/boost/sync/detail/event/event_emulation.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_emulation.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/detail/event/event_emulation.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -9,6 +9,14 @@
 #ifndef BOOST_SYNC_DETAIL_EVENT_EVENT_EMULATION_HPP_INCLUDED_
 #define BOOST_SYNC_DETAIL_EVENT_EVENT_EMULATION_HPP_INCLUDED_
 
+#include <boost/sync/semaphore.hpp>
+
+// we use the semaphore implementation if we have native semaphores
+#ifndef BOOST_SYNC_SEMAPHORE_EMULATED
+#include <boost/sync/detail/event/event_autoreset_semaphore.hpp>
+#endif
+
+
 #include <boost/thread/condition_variable.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <boost/thread/locks.hpp>
@@ -24,14 +32,17 @@
 namespace sync {
 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class event
+
+#ifdef BOOST_SYNC_SEMAPHORE_EMULATED
+
+class auto_reset_event
 {
- BOOST_DELETED_FUNCTION(event(event const&));
- BOOST_DELETED_FUNCTION(event& operator=(event const&));
+ BOOST_DELETED_FUNCTION(auto_reset_event(auto_reset_event const&));
+ BOOST_DELETED_FUNCTION(auto_reset_event& operator=(auto_reset_event const&));
 
 public:
- explicit event(bool auto_reset = false) BOOST_NOEXCEPT :
- m_auto_reset(auto_reset), m_is_set(false)
+ auto_reset_event() BOOST_NOEXCEPT :
+ m_is_set(false)
     {}
 
     void post()
@@ -39,11 +50,8 @@
         unique_lock<upgrade_mutex> lock(m_mutex);
         bool already_signaled = m_is_set;
         m_is_set = true;
- if (m_auto_reset) {
- if (!already_signaled)
- m_cond.notify_one();
- } else
- m_cond.notify_all();
+ if (!already_signaled)
+ m_cond.notify_one();
     }
 
     void wait()
@@ -53,10 +61,8 @@
         while (!m_is_set)
             m_cond.wait(lock);
 
- if (m_auto_reset) {
- upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
- m_is_set = false;
- }
+ upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
+ m_is_set = false;
     }
 
     void reset()
@@ -69,19 +75,31 @@
     {
         lock_guard<upgrade_mutex> lock(m_mutex);
         const bool res = m_is_set;
- if (res && m_auto_reset)
+ if (res)
             m_is_set = false;
         return res;
     }
 
- template <class Rep, class Period>
- bool try_wait_for(const chrono::duration<Rep, Period> & duration)
+ template <class Duration>
+ bool try_wait_for(const Duration & duration)
     {
- return try_wait_until( chrono::system_clock::now() + duration );
+ upgrade_lock<upgrade_mutex> lock(m_mutex);
+
+ while (!m_is_set) {
+ if (m_cond.wait_for(lock, duration) == cv_status::timeout) {
+ if (!m_is_set)
+ return false;
+ break;
+ }
+ }
+
+ upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
+ m_is_set = false;
+ return true;
     }
 
- template <class Clock, class Duration>
- bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout)
+ template <typename TimePoint>
+ bool try_wait_until(const TimePoint & timeout)
     {
         upgrade_lock<upgrade_mutex> lock(m_mutex);
 
@@ -93,15 +111,90 @@
             }
         }
 
- if (m_auto_reset) {
- upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
- m_is_set = false;
+ upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
+ m_is_set = false;
+ return true;
+ }
+
+private:
+ bool m_is_set;
+ upgrade_mutex m_mutex;
+ condition_variable_any m_cond;
+};
+
+#endif
+
+class manual_reset_event
+{
+ BOOST_DELETED_FUNCTION(manual_reset_event(manual_reset_event const&));
+ BOOST_DELETED_FUNCTION(manual_reset_event& operator=(manual_reset_event const&));
+
+public:
+ manual_reset_event() BOOST_NOEXCEPT :
+ m_is_set(false)
+ {}
+
+ void post()
+ {
+ unique_lock<upgrade_mutex> lock(m_mutex);
+ bool already_signaled = m_is_set;
+ m_is_set = true;
+ m_cond.notify_all();
+ }
+
+ void wait()
+ {
+ upgrade_lock<upgrade_mutex> lock(m_mutex);
+
+ while (!m_is_set)
+ m_cond.wait(lock);
+ }
+
+ void reset()
+ {
+ lock_guard<upgrade_mutex> lock(m_mutex);
+ m_is_set = false;
+ }
+
+ bool try_wait()
+ {
+ lock_guard<upgrade_mutex> lock(m_mutex);
+ return m_is_set;
+ }
+
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration)
+ {
+ upgrade_lock<upgrade_mutex> lock(m_mutex);
+
+ while (!m_is_set) {
+ if (m_cond.wait_for(lock, duration) == cv_status::timeout) {
+ if (!m_is_set)
+ return false;
+ break;
+ }
         }
+
+ return true;
+ }
+
+ template <typename TimePoint>
+ bool try_wait_until(const TimePoint & timeout)
+ {
+ upgrade_lock<upgrade_mutex> lock(m_mutex);
+
+ while (!m_is_set) {
+ if (m_cond.wait_until(lock, timeout) == cv_status::timeout) {
+ if (!m_is_set)
+ return false;
+ break;
+ }
+ }
+
         return true;
     }
 
 private:
- const bool m_auto_reset;
     bool m_is_set;
     upgrade_mutex m_mutex;
     condition_variable_any m_cond;

Modified: trunk/boost/sync/detail/event/event_futex.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_futex.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/detail/event/event_futex.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -27,113 +27,83 @@
 namespace sync {
 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class event
+class futex_event_base
 {
- BOOST_DELETED_FUNCTION(event(event const&));
- BOOST_DELETED_FUNCTION(event& operator=(event const&));
+ BOOST_DELETED_FUNCTION(futex_event_base(futex_event_base const&));
+ BOOST_DELETED_FUNCTION(futex_event_base& operator=(futex_event_base const&));
 
+protected:
+ static long futex(void *addr1, int op, int val1, const struct timespec *timeout = NULL, void *addr2 = NULL, int val3 = 0)
+ {
+ return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
+ }
+};
+
+class auto_reset_event : futex_event_base
+{
 public:
- explicit event(bool auto_reset = false) BOOST_NOEXCEPT :
- m_auto_reset(auto_reset), m_state(0)
+ auto_reset_event() BOOST_NOEXCEPT :
+ m_state(0)
     {}
 
     void post() BOOST_NOEXCEPT
     {
- if (m_auto_reset) {
- int32_t old_state = m_state.load();
- if (old_state >= 0) {
- for(;;) {
- if (m_state.compare_exchange_weak(old_state, old_state - 1))
- break;
- detail::pause();
- }
- futex(&m_state, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max() ); // wake all threads
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int32_t old_state = m_state.load();
+ if (old_state >= 0) {
+ for(;;) {
+ if (m_state.compare_exchange_weak(old_state, old_state - 1))
+ break;
+ detail::pause();
             }
-
- } else {
- int old_state = m_state.exchange(1); // set state
- if (old_state == 0)
- futex(&m_state, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max() ); // wake all threads
+ futex(&m_state, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max() ); // wake all threads
         }
     }
 
     void wait() BOOST_NOEXCEPT
     {
- if (m_auto_reset) {
- int32_t old_state = m_state.fetch_add(1) + 1;
-
- for (;;) {
- long status = futex(&m_state, FUTEX_WAIT_PRIVATE, old_state);
- if (status == 0)
- return;
-
- switch (errno) {
- case EINTR: // signal received
- continue;
-
- case EWOULDBLOCK: // another thread changed the state, reread and retry
- old_state = m_state.load();
- continue;
-
- default:
- BOOST_ASSERT(false);
- }
- }
- } else {
- try_again:
-
- if ( m_state.load(detail::atomic_ns::memory_order_acquire) == 1 )
- return; // fast-path
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int32_t old_state = m_state.fetch_add(1) + 1;
 
- const long status = futex(&m_state, FUTEX_WAIT_PRIVATE, 0);
+ for (;;) {
+ long status = futex(&m_state, FUTEX_WAIT_PRIVATE, old_state);
             if (status == 0)
                 return;
 
- switch (errno)
- {
- case EINTR:
- // signal received
- goto try_again;
-
- case EWOULDBLOCK:
- // another thread has reset the event
- goto try_again;
+ switch (errno) {
+ case EINTR: // signal received
+ continue;
+
+ case EWOULDBLOCK: // another thread changed the state, reread and retry
+ old_state = m_state.load();
+ continue;
+
+ default:
+ BOOST_ASSERT(false);
             }
         }
     }
 
     bool try_wait()
     {
- if (m_auto_reset) {
- int32_t old_state = m_state.load();
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int32_t old_state = m_state.load();
 
- if (old_state < 0) {
- for(;;) {
- int32_t new_state = old_state + 1;
- bool cas_successful = m_state.compare_exchange_weak(old_state, new_state);
- if (cas_successful) // we succeeded and reset the wait count
- return true;
- if (old_state >= 0) // another thread a succeeded
- return false;
- }
+ if (old_state < 0) {
+ for(;;) {
+ int32_t new_state = old_state + 1;
+ bool cas_successful = m_state.compare_exchange_weak(old_state, new_state);
+ if (cas_successful) // we succeeded and reset the wait count
+ return true;
+ if (old_state >= 0) // another thread a succeeded
+ return false;
             }
- return false;
-
- } else {
- if ( m_state.load(detail::atomic_ns::memory_order_acquire) == 1 )
- return true; // fast-path
- else
- return false;
         }
+ return false;
     }
 
- void reset() BOOST_NOEXCEPT
- {
- m_state.store( 0 );
- }
-
- template <class Rep, class Period>
- bool try_wait_for(const chrono::duration<Rep, Period> & duration) BOOST_NOEXCEPT
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration) BOOST_NOEXCEPT
     {
         timespec ts = boost::detail::to_timespec( duration );
         return do_wait_for(ts);
@@ -148,67 +118,136 @@
 private:
     bool do_wait_for(const struct timespec & timeout)
     {
- if (m_auto_reset) {
- int32_t old_state = m_state.fetch_add(1) + 1;
-
- for (;;) {
- long status = futex(&m_state, FUTEX_WAIT_PRIVATE, old_state, &timeout);
- if (status == 0)
- return true;
-
- switch (errno) {
- case ETIMEDOUT:
- return false;
-
- case EINTR: // signal received
- continue;
-
- case EWOULDBLOCK: // another thread changed the state, reread and retry
- old_state = m_state.load();
- continue;
-
- default:
- BOOST_ASSERT(false);
- }
- }
- } else {
- try_again:
-
- if ( m_state.load(detail::atomic_ns::memory_order_acquire) == 1 )
- return true; // fast-path
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int32_t old_state = m_state.fetch_add(1) + 1;
 
- const long status = futex(&m_state, FUTEX_WAIT_PRIVATE, 0, &timeout);
+ for (;;) {
+ long status = futex(&m_state, FUTEX_WAIT_PRIVATE, old_state, &timeout);
             if (status == 0)
                 return true;
 
- switch (errno)
- {
+ switch (errno) {
             case ETIMEDOUT:
                 return false;
 
- case EINTR:
- // signal received
- goto try_again;
-
- case EWOULDBLOCK:
- // another thread has reset the event
- goto try_again;
+ case EINTR: // signal received
+ continue;
+
+ case EWOULDBLOCK: // another thread changed the state, reread and retry
+ old_state = m_state.load();
+ continue;
+
+ default:
+ BOOST_ASSERT(false);
             }
         }
         BOOST_ASSERT(false);
         return false;
     }
 
- static long futex(void *addr1, int op, int val1, const struct timespec *timeout = NULL, void *addr2 = NULL, int val3 = 0)
+ detail::atomic_ns::atomic<int32_t> m_state;
+};
+
+class manual_reset_event: futex_event_base
+{
+public:
+ manual_reset_event() BOOST_NOEXCEPT :
+ m_state(0)
+ {}
+
+ void post() BOOST_NOEXCEPT
     {
- return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ int old_state = m_state.exchange(1); // set state
+ if (old_state == 0)
+ futex(&m_state, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max() ); // wake all threads
     }
 
- const bool m_auto_reset;
+ void wait() BOOST_NOEXCEPT
+ {
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ try_again:
+
+ if ( m_state.load(memory_order_acquire) == 1 )
+ return; // fast-path
 
+ const long status = futex(&m_state, FUTEX_WAIT_PRIVATE, 0);
+ if (status == 0)
+ return;
+
+ switch (errno)
+ {
+ case EINTR:
+ // signal received
+ goto try_again;
+
+ case EWOULDBLOCK:
+ // another thread has reset the event
+ goto try_again;
+ }
+ }
+
+ bool try_wait()
+ {
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ if ( m_state.load(memory_order_acquire) == 1 )
+ return true; // fast-path
+ else
+ return false;
+ }
+
+ void reset() BOOST_NOEXCEPT
+ {
+ m_state.store( 0 );
+ }
+
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration) BOOST_NOEXCEPT
+ {
+ timespec ts = boost::detail::to_timespec( duration );
+ return do_wait_for(ts);
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout ) BOOST_NOEXCEPT
+ {
+ return try_wait_for( timeout - Clock::now() );
+ }
+
+private:
+ bool do_wait_for(const struct timespec & timeout)
+ {
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+
+ try_again:
+ if ( m_state.load(memory_order_acquire) == 1 )
+ return true; // fast-path
+
+ const long status = futex(&m_state, FUTEX_WAIT_PRIVATE, 0, &timeout);
+ if (status == 0)
+ return true;
+
+ switch (errno)
+ {
+ case ETIMEDOUT:
+ return false;
+
+ case EINTR:
+ // signal received
+ goto try_again;
+
+ case EWOULDBLOCK:
+ // another thread has reset the event
+ goto try_again;
+ }
+ BOOST_ASSERT(false);
+ return false;
+ }
     detail::atomic_ns::atomic<int32_t> m_state;
 };
 
+
+
 }
 }
 }

Modified: trunk/boost/sync/detail/event/event_mach.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_mach.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/detail/event/event_mach.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -10,6 +10,10 @@
 #ifndef BOOST_SYNC_EVENT_DETAIL_DARWIN_EVENT_MACH_HPP
 #define BOOST_SYNC_EVENT_DETAIL_DARWIN_EVENT_MACH_HPP
 
+// auto_reset_event is implemented via sync::semaphores:
+#include <boost/sync/detail/event/event_autoreset_semaphore.hpp>
+
+
 #include <cstddef>
 #include <boost/assert.hpp>
 #include <boost/cstdint.hpp>
@@ -32,20 +36,21 @@
 
 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class event
+
+class manual_reset_event
 {
- BOOST_DELETED_FUNCTION(event(event const&))
- BOOST_DELETED_FUNCTION(event& operator=(event const&));
+ BOOST_DELETED_FUNCTION(manual_reset_event(manual_reset_event const&))
+ BOOST_DELETED_FUNCTION(manual_reset_event& operator=(manual_reset_event const&));
 
 public:
- explicit event(bool auto_reset = false) BOOST_NOEXCEPT:
- m_auto_reset(auto_reset), m_state(0)
+ manual_reset_event() BOOST_NOEXCEPT:
+ m_state(0)
     {
         kern_return_t result = semaphore_create(mach_task_self(), &m_sem, SYNC_POLICY_FIFO, 0);
         BOOST_VERIFY(result == KERN_SUCCESS);
     }
 
- ~event() BOOST_NOEXCEPT
+ ~manual_reset_event() BOOST_NOEXCEPT
     {
         kern_return_t result = semaphore_destroy(mach_task_self(), m_sem);
         BOOST_VERIFY(result == KERN_SUCCESS);
@@ -53,33 +58,9 @@
 
     void post() BOOST_NOEXCEPT
     {
- if (m_auto_reset)
- {
- int32_t old_state = m_state.load(detail::atomic_ns::memory_order_acquire);
- if (old_state >= 0)
- {
- for (;;)
- {
- if (m_state.compare_exchange_weak( old_state, old_state - 1, detail::atomic_ns::memory_order_release, detail::atomic_ns::memory_order_acquire))
- {
- semaphore_signal( m_sem );
- return; // avoid unnecessary fence
- }
-
- if (old_state < 0)
- break; // someone else has set the event with no waiters
-
- detail::pause();
- }
- }
-
- detail::atomic_ns::atomic_thread_fence( detail::atomic_ns::memory_order_release );
- }
- else
- {
- m_state.store( 1, detail::atomic_ns::memory_order_release );
- semaphore_signal_all( m_sem ); // wake all threads!& reset semaphore count
- }
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ m_state.store( 1, memory_order_release );
+ semaphore_signal_all( m_sem ); // wake all threads!& reset semaphore count
     }
 
     void reset() BOOST_NOEXCEPT
@@ -89,18 +70,12 @@
 
     void wait() BOOST_NOEXCEPT
     {
- if (m_auto_reset) {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ if (m_state.load(memory_order_acquire) == 1)
+ return;
 
- kern_return_t result = semaphore_wait( m_sem );
- BOOST_VERIFY (result == KERN_SUCCESS);
- } else {
- if (m_state.load(detail::atomic_ns::memory_order_acquire) == 1)
- return;
-
- kern_return_t result = semaphore_wait( m_sem );
- BOOST_VERIFY (result == KERN_SUCCESS);
- }
+ kern_return_t result = semaphore_wait( m_sem );
+ BOOST_VERIFY (result == KERN_SUCCESS);
     }
 
     bool try_wait() BOOST_NOEXCEPT
@@ -128,29 +103,17 @@
 private:
     bool do_try_wait_until (const mach_timespec_t & timeout)
     {
- if (m_auto_reset) {
- m_state.fetch_add(1, detail::atomic_ns::memory_order_acquire);
-
- kern_return_t result = semaphore_timedwait( m_sem, timeout );
- if (result == KERN_SUCCESS)
- return true;
-
- m_state.fetch_add(-1, detail::atomic_ns::memory_order_relaxed);
+ using namespace boost::sync::detail::atomic_ns; // for memory_order
+ if (m_state.load( memory_order_acquire ) == 1)
+ return true;
+
+ kern_return_t result = semaphore_timedwait( m_sem, timeout );
+ if (result == KERN_SUCCESS)
+ return true;
+ else
             return false;
-
- } else {
- if (m_state.load( detail::atomic_ns::memory_order_acquire ) == 1)
- return true;
-
- kern_return_t result = semaphore_timedwait( m_sem, timeout );
- if (result == KERN_SUCCESS)
- return true;
- else
- return false;
- }
     }
 
- const bool m_auto_reset;
     semaphore_t m_sem;
     detail::atomic_ns::atomic<int32_t> m_state;
 };

Modified: trunk/boost/sync/detail/event/event_windows.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_windows.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/detail/event/event_windows.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -26,17 +26,17 @@
 
 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class event
+class win32_event_base
 {
- BOOST_DELETED_FUNCTION(event(event const&))
- BOOST_DELETED_FUNCTION(event& operator=(event const&))
+ BOOST_DELETED_FUNCTION(win32_event_base(win32_event_base const&))
+ BOOST_DELETED_FUNCTION(win32_event_base& operator=(win32_event_base const&))
 
     typedef boost::detail::winapi::HANDLE_ HANDLE_;
     typedef boost::detail::winapi::BOOL_ BOOL_;
     typedef boost::detail::winapi::DWORD_ DWORD_;
 
 public:
- explicit event(bool auto_reset = false)
+ explicit win32_event_base(bool auto_reset)
     {
         handle_ = boost::detail::winapi::CreateEventA(NULL, !auto_reset, 0, NULL);
         if (!handle_)
@@ -46,7 +46,7 @@
         }
     }
 
- ~event() BOOST_NOEXCEPT
+ ~win32_event_base() BOOST_NOEXCEPT
     {
         BOOST_VERIFY( boost::detail::winapi::CloseHandle(handle_) );
     }
@@ -138,6 +138,40 @@
     HANDLE_ handle_;
 };
 
+class auto_reset_event : win32_event_base
+{
+public:
+ auto_reset_event() : win32_event_base(true) {}
+
+ void post() { win32_event_base::post(); }
+ void wait() { win32_event_base::wait(); }
+ bool try_wait() { return win32_event_base::try_wait(); }
+
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration) { return win32_event_base::try_wait_for( duration ); }
+
+ template <typename TimePoint>
+ bool try_wait_until(const TimePoint & timeout) { return win32_event_base::try_wait_until( timeout ); }
+};
+
+class manual_reset_event : win32_event_base
+{
+public:
+ manual_reset_event() : win32_event_base(false) {}
+
+ void post() { win32_event_base::post(); }
+ void wait() { win32_event_base::wait(); }
+ bool try_wait() { return win32_event_base::try_wait(); }
+ void reset() { win32_event_base::reset(); }
+
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration) { return win32_event_base::try_wait_for( duration ); }
+
+ template <typename TimePoint>
+ bool try_wait_until(const TimePoint & timeout) { return win32_event_base::try_wait_until( timeout ); }
+};
+
+
 }
 }
 }

Modified: trunk/boost/sync/event.hpp
==============================================================================
--- trunk/boost/sync/event.hpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/boost/sync/event.hpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -11,31 +11,107 @@
 
 #ifdef BOOST_SYNC_DETAIL_DOXYGEN
 
-class event
+class auto_reset_event
 {
-
 public:
     /**
- * \b Effects: Constructs an event object. If `auto_reset` is true, waiting for an even will automatically reset it.
+ * \b Effects: Constructs an auto_reset_event object.
      *
      * \b Throws: if an error occurs.
      */
- explicit event(bool auto_reset = false);
+ auto_reset_event();
+
+ auto_reset_event(auto_reset_event const&) = delete;
+ auto_reset_event& operator= (auto_reset_event const&) = delete;
 
- event(event const&) = delete;
- event& operator= (event const&) = delete;
+ /**
+ * \b Effects: Destroys the auto_reset_event object.
+ *
+ * \b Precondition: No thread waits on this auto_reset_event.
+ *
+ * \b Throws: nothing.
+ */
+ ~auto_reset_event() noexcept;
+
+ /**
+ * \b Effects: Signals the auto_reset_event: the object remains signalled until one thread has finished waiting for this object.
+ *
+ * \b Memory Ordering: release
+ *
+ * \b Throws: if an error occurs.
+ */
+ void post();
+
+ /**
+ * \b Effects: If the auto_reset_event is set, the call returns immediately, otherwise it will block until the thread will be woken up
+ * by. When a waiting thread is released, the state of the auto_reset_event is automatically reset to the unsignaled state.
+ *
+ * \b Memory Ordering: acquire
+ *
+ * \b Throws: if an error occurs.
+ */
+ void wait();
 
     /**
- * \b Effects: Destroys the event object.
+ * \b Effects: Tries to wait for the auto_reset_event. If successful, the state of the auto_reset_event us automatically set to the unsignaled state.
+ *
+ * \b Memory Ordering: acquire, if successful, relaxed otherwise
      *
- * \b Precondition: No thread waits on this event.
+ * \b Returns: True if the auto_reset_event had been signaled, False, if the call would be blocking or the auto_reset_event has not been signaled.
      *
      * \b Throws: if an error occurs.
      */
- ~event();
+ bool try_wait();
+
+ /**
+ * \b Effects: Tries to wait for the auto_reset_event until a timeout occurs. If successful, the state of the auto_reset_event us automatically set to the unsignaled state.
+ *
+ * \b Memory Ordering: acquire, if successful, relaxed otherwise
+ *
+ * \b Returns: True if the auto_reset_event had been signaled, False, if the call would be blocking or the auto_reset_event has not been signaled.
+ *
+ * \b Throws: if an error occurs.
+ */
+ template <typename Duration>
+ bool try_wait_for(const Duration & duration);
+
+ /**
+ * \b Effects: Tries to wait for the auto_reset_event for a certain duration. If successful, the state of the auto_reset_event us automatically set to the unsignaled state.
+ *
+ * \b Memory Ordering: acquire, if successful, relaxed otherwise
+ *
+ * \b Returns: True if the auto_reset_event had been signaled, False, if the call would be blocking or the auto_reset_event has not been signaled.
+ *
+ * \b Throws: if an error occurs.
+ */
+ template <typename TimePoint>
+ bool try_wait_until(const TimePoint & timeout);
+};
+
+class manual_reset_event
+{
+public:
+ /**
+ * \b Effects: Constructs a manual_reset_event object.
+ *
+ * \b Throws: if an error occurs.
+ */
+ auto_reset_event();
+
+ auto_reset_event(auto_reset_event const&) = delete;
+ auto_reset_event& operator= (auto_reset_event const&) = delete;
+
+ /**
+ * \b Effects: Destroys the manual_reset_event object.
+ *
+ * \b Precondition: No thread waits on this manual_reset_event.
+ *
+ * \b Throws: nothing.
+ */
+ ~auto_reset_event() noexcept;
 
     /**
- * \b Effects: Signals the event object: the event is set and waiting threads will be woken up.
+ * \b Effects: Signals the event object: the event is set and waiting threads will be released.
      *
      * \b Memory Ordering: release
      *
@@ -44,7 +120,7 @@
     void post();
 
     /**
- * \b Effects: Waits for the event to be signaled. If the event is created as `auto_reset`, it will unset the `signaled` state
+ * \b Effects: Waits for the event to be signaled.
      *
      * \b Memory Ordering: acquire
      *
@@ -53,14 +129,14 @@
     void wait();
 
     /**
- * \b Effects: Resets the event to the unsignaled state.
+ * \b Effects: Resets the event to the unsignaled state.
      *
      * \b Throws: if an error occurs.
      */
     void reset();
 
     /**
- * \b Effects: Waits for the event to be signaled. If the event is created as `auto_reset`, it will unset the `signaled` state
+ * \b Effects: Tries to waits for the event to be signaled.
      *
      * \b Memory Ordering: acquire, if successful, relaxed otherwise
      *
@@ -71,7 +147,7 @@
     bool try_wait();
 
     /**
- * \b Effects: Waits for the event to be signaled. If the event is created as `auto_reset`, it will unset the `signaled` state
+ * \b Effects: Waits for the event to be signaled.
      *
      * \b Memory Ordering: acquire, if successful, relaxed otherwise
      *
@@ -83,7 +159,7 @@
     bool try_wait_for(const Duration & duration);
 
     /**
- * \b Effects: Waits for the event to be signaled. If the event is created as `auto_reset`, it will unset the `signaled` state
+ * \b Effects: Waits for the event to be signaled.
      *
      * \b Memory Ordering: acquire, if successful, relaxed otherwise
      *
@@ -95,6 +171,7 @@
     bool try_wait_until(const TimePoint & timeout);
 };
 
+
 #else // BOOST_SYNC_DETAIL_DOXYGEN
 
 #include <boost/sync/detail/config.hpp>

Modified: trunk/libs/sync/test/run/event_test.cpp
==============================================================================
--- trunk/libs/sync/test/run/event_test.cpp Sat Sep 28 02:15:48 2013 (r85977)
+++ trunk/libs/sync/test/run/event_test.cpp 2013-09-28 04:58:43 EDT (Sat, 28 Sep 2013) (r85978)
@@ -12,7 +12,7 @@
 
 BOOST_AUTO_TEST_CASE(test_event_post_wait)
 {
- boost::sync::event ev;
+ boost::sync::manual_reset_event ev;
 
     ev.post();
     ev.wait();
@@ -27,7 +27,7 @@
 
 BOOST_AUTO_TEST_CASE(test_event_post_try_wait)
 {
- boost::sync::event ev;
+ boost::sync::manual_reset_event ev;
 
     BOOST_REQUIRE( ev.try_wait() == false );
 
@@ -38,7 +38,7 @@
 
 BOOST_AUTO_TEST_CASE(test_event_post_wait_autoreset)
 {
- boost::sync::event ev(true);
+ boost::sync::auto_reset_event ev;
 
     ev.post();
     BOOST_REQUIRE( ev.try_wait() == true );
@@ -48,7 +48,7 @@
 
 BOOST_AUTO_TEST_CASE(test_event_reset)
 {
- boost::sync::event ev(false);
+ boost::sync::manual_reset_event ev;
 
     BOOST_REQUIRE( ev.try_wait() == false );
     ev.post();
@@ -57,6 +57,7 @@
     BOOST_REQUIRE( ev.try_wait() == false );
 }
 
+template <typename EventType>
 struct event_wait_and_post_test
 {
     void run()
@@ -71,22 +72,27 @@
         ev_.post();
     }
 
- boost::sync::event ev_;
+ EventType ev_;
     boost::thread thread_;
 };
 
 BOOST_AUTO_TEST_CASE(event_wait_and_post)
 {
- event_wait_and_post_test test;
+ event_wait_and_post_test<boost::sync::manual_reset_event> test;
     test.run();
 }
 
+BOOST_AUTO_TEST_CASE(event_wait_and_post_autoreset)
+{
+ event_wait_and_post_test<boost::sync::auto_reset_event> test;
+ test.run();
+}
 
 BOOST_AUTO_TEST_CASE(test_event_wait_for)
 {
     using namespace boost;
 
- sync::event ev;
+ sync::manual_reset_event ev;
 
     BOOST_AUTO(start, chrono::system_clock::now());
 
@@ -113,7 +119,7 @@
 {
     using namespace boost;
 
- sync::event ev(0);
+ sync::manual_reset_event ev;
     {
         BOOST_AUTO(now, chrono::system_clock::now());
         BOOST_AUTO(timeout, now + chrono::milliseconds(500));


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