Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85773 - in trunk: boost/sync boost/sync/detail/event libs/sync/test
From: tim_at_[hidden]
Date: 2013-09-18 07:38:52


Author: timblechmann
Date: 2013-09-18 07:38:52 EDT (Wed, 18 Sep 2013)
New Revision: 85773
URL: http://svn.boost.org/trac/boost/changeset/85773

Log:
sync: event - implement event with mach semaphores

Added:
   trunk/boost/sync/detail/event/event_mach.hpp (contents, props changed)
Text files modified:
   trunk/boost/sync/detail/event/event_emulation.hpp | 11 +-
   trunk/boost/sync/detail/event/event_mach.hpp | 156 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/sync/event.hpp | 22 ++++-
   trunk/libs/sync/test/event_test.cpp | 2
   4 files changed, 180 insertions(+), 11 deletions(-)

Modified: trunk/boost/sync/detail/event/event_emulation.hpp
==============================================================================
--- trunk/boost/sync/detail/event/event_emulation.hpp Wed Sep 18 06:58:46 2013 (r85772)
+++ trunk/boost/sync/detail/event/event_emulation.hpp 2013-09-18 07:38:52 EDT (Wed, 18 Sep 2013) (r85773)
@@ -32,16 +32,17 @@
 public:
     explicit event(bool auto_reset = false) :
         m_auto_reset(auto_reset), m_is_set(false)
- {
- }
+ {}
 
     void post()
     {
         unique_lock<mutex> lock(m_mutex);
+ bool already_signaled = m_is_set;
         m_is_set = true;
- if (m_auto_reset)
- m_cond.notify_one();
- else
+ if (m_auto_reset) {
+ if (!already_signaled)
+ m_cond.notify_one();
+ } else
             m_cond.notify_all();
     }
 

Added: trunk/boost/sync/detail/event/event_mach.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/detail/event/event_mach.hpp 2013-09-18 07:38:52 EDT (Wed, 18 Sep 2013) (r85773)
@@ -0,0 +1,156 @@
+// event.hpp, mach events
+//
+// Copyright (C) 2013 Tim Blechmann
+//
+// 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)
+
+#ifndef BOOST_SYNC_EVENT_DETAIL_DARWIN_EVENT_MACH_HPP
+#define BOOST_SYNC_EVENT_DETAIL_DARWIN_EVENT_MACH_HPP
+
+#include <cstddef>
+#include <boost/assert.hpp>
+
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/exceptions/resource_error.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#include <mach/task.h>
+#include <mach/semaphore.h>
+#include <mach/mach_traps.h>
+#include <mach/mach_init.h>
+
+#include <boost/atomic.hpp>
+
+namespace boost {
+
+namespace sync {
+
+BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
+
+class event
+{
+ BOOST_DELETED_FUNCTION(event(event const&))
+ BOOST_DELETED_FUNCTION(event& operator=(event const&));
+
+public:
+ explicit event(bool auto_reset = false):
+ m_auto_reset(auto_reset), m_signaled(0)
+ {
+ kern_return_t result = semaphore_create(mach_task_self(), &m_sem, SYNC_POLICY_FIFO, 0);
+ BOOST_VERIFY(result == KERN_SUCCESS);
+ }
+
+ ~event()
+ {
+ kern_return_t result = semaphore_destroy(mach_task_self(), m_sem);
+ BOOST_VERIFY(result == KERN_SUCCESS);
+ }
+
+ void post()
+ {
+ if (m_auto_reset) {
+ bool already_signaled = m_signaled.exchange(true);
+ if (!already_signaled)
+ semaphore_signal( m_sem ); // wake one thread!
+ } else {
+ m_signaled = true;
+ semaphore_signal_all( m_sem ); // wake all threads!& reset semaphore count
+ }
+ }
+
+ void reset()
+ {
+ m_signaled = false;
+ }
+
+ void wait()
+ {
+ if (m_auto_reset) {
+ // the first waiter succeeds and resets the signalled state
+
+ try_again:
+ kern_return_t result = semaphore_wait( m_sem );
+
+ if (result == KERN_SUCCESS) {
+ bool isTrue = true;
+ bool firstWaiter = m_signaled.compare_exchange_strong(isTrue, false);
+
+ if (firstWaiter) // only the first waiter succeeds
+ return;
+ }
+
+ goto try_again;
+ } else {
+ if (m_signaled.load() == true)
+ return;
+
+ kern_return_t result = semaphore_wait( m_sem );
+ BOOST_VERIFY (result == KERN_SUCCESS);
+ }
+ }
+
+ bool try_wait()
+ {
+ const mach_timespec_t immediate = {0, 0};
+ return do_try_wait_until(immediate);
+ }
+
+ template <class Rep, class Period>
+ bool try_wait_for(const chrono::duration<Rep, Period> & duration)
+ {
+ BOOST_AUTO ( seconds, chrono::duration_cast<chrono::seconds>(duration) );
+ BOOST_AUTO ( nanoseconds, chrono::duration_cast<chrono::nanoseconds>(duration) - seconds );
+
+ const mach_timespec_t mach_duration = { seconds.count(), nanoseconds.count() };
+ return do_try_wait_until( mach_duration );
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout )
+ {
+ return try_wait_for( timeout - Clock::now() );
+ }
+
+private:
+ bool do_try_wait_until (const mach_timespec_t & timeout)
+ {
+ if (m_auto_reset) {
+ // the first waiter succeeds and resets the signaled state
+
+ kern_return_t result = semaphore_timedwait( m_sem, timeout );
+
+ if (result == KERN_SUCCESS) {
+ bool isTrue = true;
+ bool firstWaiter = m_signaled.compare_exchange_strong(isTrue, false);
+
+ if (firstWaiter) // only the first waiter succeeds
+ return true;
+ }
+ return false;
+
+ } else {
+ if (m_signaled.load() == true)
+ 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;
+ atomic_bool m_signaled;
+};
+
+}
+}
+}
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_EVENT_DETAIL_DARWIN_EVENT_MACH_HPP

Modified: trunk/boost/sync/event.hpp
==============================================================================
--- trunk/boost/sync/event.hpp Wed Sep 18 06:58:46 2013 (r85772)
+++ trunk/boost/sync/event.hpp 2013-09-18 07:38:52 EDT (Wed, 18 Sep 2013) (r85773)
@@ -97,14 +97,26 @@
 #pragma once
 #endif
 
+#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+#include <Availability.h>
+
+// OSX
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+
+// Check: do other mach-based platforms support mach semaphores?
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7
+#define BOOST_SYNC_DETAIL_PLATFORM_MACH
+#endif
+
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
+#endif // apple stuff
+
 #if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
 #include <boost/sync/detail/event/event_windows.hpp>
 
-//#elif defined(BOOST_SYNC_POSIX_SEMAPHORES)
-//#include <boost/sync/semaphore/semaphore_posix.hpp>
-
-//#elif defined(BOOST_SYNC_DISPATCH_SEMAPHORES)
-//#include <boost/sync/semaphore/semaphore_dispatch.hpp>
+#elif defined(BOOST_SYNC_DETAIL_PLATFORM_MACH)
+#include <boost/sync/detail/event/event_mach.hpp>
 
 #else
 

Modified: trunk/libs/sync/test/event_test.cpp
==============================================================================
--- trunk/libs/sync/test/event_test.cpp Wed Sep 18 06:58:46 2013 (r85772)
+++ trunk/libs/sync/test/event_test.cpp 2013-09-18 07:38:52 EDT (Wed, 18 Sep 2013) (r85773)
@@ -41,7 +41,7 @@
     boost::sync::event ev(true);
 
     ev.post();
- ev.wait();
+ BOOST_REQUIRE( ev.try_wait() == true );
     BOOST_REQUIRE( ev.try_wait() == false );
 }
 


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