|
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