Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85673 - in trunk: boost/detail/win boost/sync boost/sync/detail boost/sync/semaphore libs/sync/test
From: tim_at_[hidden]
Date: 2013-09-15 06:46:54


Author: timblechmann
Date: 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013)
New Revision: 85673
URL: http://svn.boost.org/trac/boost/changeset/85673

Log:
sync: add semaphore implementation

Added:
   trunk/boost/sync/semaphore/
   trunk/boost/sync/semaphore.hpp (contents, props changed)
   trunk/boost/sync/semaphore/semaphore_dispatch.hpp (contents, props changed)
   trunk/boost/sync/semaphore/semaphore_emulation.hpp (contents, props changed)
   trunk/boost/sync/semaphore/semaphore_posix.hpp (contents, props changed)
   trunk/boost/sync/semaphore/semaphore_win32.hpp (contents, props changed)
   trunk/libs/sync/test/
   trunk/libs/sync/test/Jamfile.v2 (contents, props changed)
   trunk/libs/sync/test/semaphore_test.cpp (contents, props changed)
Text files modified:
   trunk/boost/detail/win/synchronization.hpp | 58 ++++++++-----
   trunk/boost/sync/detail/config.hpp | 45 ++++++++++
   trunk/boost/sync/semaphore.hpp | 38 ++++++++
   trunk/boost/sync/semaphore/semaphore_dispatch.hpp | 106 ++++++++++++++++++++++++
   trunk/boost/sync/semaphore/semaphore_emulation.hpp | 93 +++++++++++++++++++++
   trunk/boost/sync/semaphore/semaphore_posix.hpp | 172 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/sync/semaphore/semaphore_win32.hpp | 124 ++++++++++++++++++++++++++++
   trunk/libs/sync/test/Jamfile.v2 | 37 ++++++++
   trunk/libs/sync/test/semaphore_test.cpp | 128 +++++++++++++++++++++++++++++
   9 files changed, 778 insertions(+), 23 deletions(-)

Modified: trunk/boost/detail/win/synchronization.hpp
==============================================================================
--- trunk/boost/detail/win/synchronization.hpp Sun Sep 15 06:21:59 2013 (r85672)
+++ trunk/boost/detail/win/synchronization.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -27,7 +27,7 @@
     using ::TryEnterCriticalSection;
     using ::LeaveCriticalSection;
     using ::DeleteCriticalSection;
-
+
 # ifdef BOOST_NO_ANSI_APIS
     using ::CreateMutexW;
     using ::CreateEventW;
@@ -46,6 +46,12 @@
     using ::WaitForMultipleObjects;
     using ::WaitForSingleObject;
             using ::QueueUserAPC;
+
+ static const DWORD_ wait_abandoned = WAIT_ABANDONED;
+ static const DWORD_ wait_object_0 = WAIT_OBJECT_0;
+ static const DWORD_ wait_timeout = WAIT_TIMEOUT;
+ static const DWORD_ wait_failed = WAIT_FAILED;
+
 #else
 extern "C" {
     struct CRITICAL_SECTION_
@@ -62,61 +68,67 @@
     #endif
     };
 
- __declspec(dllimport) void __stdcall
+ __declspec(dllimport) void __stdcall
         InitializeCriticalSection(CRITICAL_SECTION_ *);
- __declspec(dllimport) void __stdcall
+ __declspec(dllimport) void __stdcall
         EnterCriticalSection(CRITICAL_SECTION_ *);
- __declspec(dllimport) bool __stdcall
+ __declspec(dllimport) bool __stdcall
         TryEnterCriticalSection(CRITICAL_SECTION_ *);
- __declspec(dllimport) void __stdcall
+ __declspec(dllimport) void __stdcall
         LeaveCriticalSection(CRITICAL_SECTION_ *);
- __declspec(dllimport) void __stdcall
+ __declspec(dllimport) void __stdcall
         DeleteCriticalSection(CRITICAL_SECTION_ *);
-
+
     struct _SECURITY_ATTRIBUTES;
 # ifdef BOOST_NO_ANSI_APIS
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         OpenEventW(unsigned long,int,wchar_t const*);
 # else
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
- __declspec(dllimport) void* __stdcall
+ __declspec(dllimport) void* __stdcall
         OpenEventA(unsigned long,int,char const*);
 # endif
- __declspec(dllimport) int __stdcall
+ __declspec(dllimport) int __stdcall
         ReleaseMutex(void*);
- __declspec(dllimport) unsigned long __stdcall
+ __declspec(dllimport) unsigned long __stdcall
         WaitForSingleObject(void*,unsigned long);
- __declspec(dllimport) unsigned long __stdcall
+ __declspec(dllimport) unsigned long __stdcall
         WaitForMultipleObjects(unsigned long nCount,
                 void* const * lpHandles,
                 int bWaitAll,
                 unsigned long dwMilliseconds);
- __declspec(dllimport) int __stdcall
+ __declspec(dllimport) int __stdcall
         ReleaseSemaphore(void*,long,long*);
     typedef void (__stdcall *PAPCFUNC8)(ulong_ptr);
- __declspec(dllimport) unsigned long __stdcall
+ __declspec(dllimport) unsigned long __stdcall
         QueueUserAPC(PAPCFUNC8,void*,ulong_ptr);
 # ifndef UNDER_CE
- __declspec(dllimport) int __stdcall
+ __declspec(dllimport) int __stdcall
         SetEvent(void*);
- __declspec(dllimport) int __stdcall
+ __declspec(dllimport) int __stdcall
         ResetEvent(void*);
 # else
     using ::SetEvent;
     using ::ResetEvent;
+
+ static const DWORD_ wait_abandoned = 0x00000080L;
+ static const DWORD_ wait_object_0 = 0x00000000L;
+ static const DWORD_ wait_timeout = 0x00000102L;
+ static const DWORD_ wait_failed = (DWORD_)0xFFFFFFFF;
+
 # endif
-}
+}
 #endif
 }
 }

Modified: trunk/boost/sync/detail/config.hpp
==============================================================================
--- trunk/boost/sync/detail/config.hpp Sun Sep 15 06:21:59 2013 (r85672)
+++ trunk/boost/sync/detail/config.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -31,6 +31,7 @@
 #define BOOST_SYNC_USE_WINAPI_VERSION 0x0500
 #endif
 
+#endif
 #if defined(BOOST_SYNC_USE_PTHREAD)
 #define BOOST_SYNC_DETAIL_PLATFORM_PTHREAD
 #elif defined(BOOST_SYNC_USE_WINAPI_VERSION)
@@ -43,4 +44,48 @@
 #define BOOST_SYNC_DETAIL_NO_CXX11_INITIALIZER_LISTS
 #endif
 
+
+#ifdef BOOST_HAS_UNISTD_H
+#include <unistd.h>
+
+#if (_POSIX_SEMAPHORES - 0) >= 200112L
+#define BOOST_SYNC_POSIX_SEMAPHORES
+#endif
+
+#endif // BOOST_HAS_UNISTD_H
+
+#if defined(__APPLE__)
+#include <Availability.h>
+
+// OSX
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6
+#define BOOST_SYNC_DISPATCH_SEMAPHORES
+#endif
+
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
+
+// iOS
+#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
+
+// untested!
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
+#define BOOST_SYNC_DISPATCH_SEMAPHORES
+#endif
+
+#endif // __IPHONE_OS_VERSION_MIN_REQUIRED
+
+#endif // __APPLE__
+
+
+#if ! defined BOOST_SYNC_DONT_USE_CHRONO \
+ && ! defined BOOST_SYNC_USES_CHRONO
+#define BOOST_SYNC_USES_CHRONO
+#endif
+
+#define BOOST_SYNC_USES_CHRONO
+
+
+
 #endif // BOOST_SYNC_DETAIL_CONFIG_HPP_INCLUDED_

Added: trunk/boost/sync/semaphore.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/semaphore.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,38 @@
+// semaphore.hpp
+//
+// 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_SEMAPHORE_HPP
+#define BOOST_SYNC_SEMAPHORE_HPP
+
+#include <boost/sync/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#include <boost/sync/detail/header.hpp>
+
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+#include <boost/sync/semaphore/semaphore_win32.hpp>
+
+#elif defined(BOOST_THREAD_POSIX_SEMAPHORES)
+#include <boost/sync/semaphore/semaphore_posix.hpp>
+
+#elif defined(BOOST_THREAD_DISPATCH_SEMAPHORES)
+#include <boost/sync/semaphore/semaphore_dispatch.hpp>
+
+#else
+
+#include <boost/sync/semaphore/semaphore_emulation.hpp>
+
+#endif
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_THREAD_SEMAPHORE_HPP

Added: trunk/boost/sync/semaphore/semaphore_dispatch.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/semaphore/semaphore_dispatch.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,106 @@
+// semaphore.hpp, osx/ios dispatch semaphores
+//
+// 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_SEMAPHORE_SEMAPHORE_DISPATCH_HPP
+#define BOOST_SYNC_SEMAPHORE_SEMAPHORE_DISPATCH_HPP
+
+#include <dispatch/dispatch.h>
+
+#include <boost/thread/exceptions.hpp>
+
+#ifdef BOOST_SYNC_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+
+namespace boost {
+namespace sync {
+
+class semaphore
+{
+ BOOST_DELETED_FUNCTION(semaphore(semaphore const&))
+ BOOST_DELETED_FUNCTION(semaphore& operator=(semaphore const&))
+
+public:
+ semaphore(int i=0)
+ {
+ BOOST_ASSERT_MSG(i >= 0, "boost::sync::semaphore constructor called with negative count");
+ sem = dispatch_semaphore_create(i);
+ if (sem == NULL)
+ boost::throw_exception(thread_resource_error(system::errc::not_enough_memory, "boost::sync::semaphore constructor failed in dispatch_semaphore_create"));
+ }
+
+ ~semaphore()
+ {
+ dispatch_release(sem);
+ }
+
+ void post()
+ {
+ dispatch_semaphore_signal(sem);
+ }
+
+ void wait()
+ {
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ }
+
+ bool try_wait(void)
+ {
+ const long status = dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW);
+ return status == 0;
+ }
+
+#ifdef BOOST_SYNC_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_wait_for(const chrono::duration<Rep, Period> & rel_time)
+ {
+ return try_wait_until(chrono::steady_clock::now() + rel_time);
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout )
+ {
+ using namespace chrono;
+ system_clock::time_point s_now = system_clock::now();
+ typename Clock::time_point c_now = Clock::now();
+ return try_wait_until(s_now + ceil<nanoseconds>(timeout - c_now));
+ }
+
+ template <class Duration>
+ bool try_wait_until(const chrono::time_point<chrono::system_clock, Duration>& t)
+ {
+ using namespace chrono;
+ typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ return try_wait_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+ }
+
+ bool try_wait_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
+ {
+ chrono::nanoseconds d = tp.time_since_epoch();
+ timespec ts = boost::detail::to_timespec(d);
+ return do_wait_lock_until(dispatch_walltime(&ts, 0));
+ }
+
+private:
+ bool do_wait_lock_until(const dispatch_time_t timeout)
+ {
+ const long status = dispatch_semaphore_wait(sem, timeout);
+ return status == 0;
+ }
+
+#endif // BOOST_SYNC_USES_CHRONO
+
+private:
+ dispatch_semaphore_t sem;
+};
+
+}
+}
+
+#endif // BOOST_SYNC_SEMAPHORE_SEMAPHORE_DISPATCH_HPP

Added: trunk/boost/sync/semaphore/semaphore_emulation.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/semaphore/semaphore_emulation.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,93 @@
+// semaphore.hpp, mutex/condition_varibale emulation
+//
+// 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_SEMAPHORE_SEMAPHORE_EMULATION_HPP
+#define BOOST_SYNC_SEMAPHORE_SEMAPHORE_EMULATION_HPP
+
+#include <boost/bind.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+#ifdef BOOST_SYNC_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+
+namespace boost {
+namespace sync {
+
+class semaphore
+{
+ BOOST_DELETED_FUNCTION(semaphore(semaphore const&))
+ BOOST_DELETED_FUNCTION(semaphore& operator=(semaphore const&))
+
+public:
+ semaphore(int i=0):
+ m_count(i)
+ {
+ BOOST_ASSERT_MSG(i >= 0, "boost::sync::semaphore constructor called with negative count");
+ }
+
+ void post(void)
+ {
+ mutex::scoped_lock lock(m_mutex);
+ ++m_count;
+ m_cond.notify_one();
+ }
+
+ void wait(void)
+ {
+ mutex::scoped_lock lock(m_mutex);
+ m_cond.wait(lock, boost::bind(&semaphore::check_wakeup_condition, this));
+
+ --m_count;
+ }
+
+ bool try_wait(void)
+ {
+ mutex::scoped_lock lock(m_mutex);
+ if (!check_wakeup_condition())
+ return false;
+
+ --m_count;
+ return true;
+ }
+
+#ifdef BOOST_SYNC_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_wait_for(const chrono::duration<Rep, Period> & rel_time)
+ {
+ mutex::scoped_lock lock(m_mutex);
+ return m_cond.wait_for(lock, rel_time, boost::bind(&semaphore::check_wakeup_condition, this));
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout )
+ {
+ mutex::scoped_lock lock(m_mutex);
+ return m_cond.wait_until(lock, timeout, boost::bind(&semaphore::check_wakeup_condition, this));
+ }
+#endif // BOOST_SYNC_USES_CHRONO
+
+private:
+ bool check_wakeup_condition()
+ {
+ return m_count > 0;
+ }
+
+ unsigned int m_count;
+ boost::mutex m_mutex;
+ boost::condition_variable m_cond;
+};
+
+}
+}
+
+#endif // BOOST_SYNC_SEMAPHORE_SEMAPHORE_EMULATION_HPP

Added: trunk/boost/sync/semaphore/semaphore_posix.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/semaphore/semaphore_posix.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,172 @@
+// semaphore.hpp, posix implementation
+//
+// 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_SEMAPHORE_SEMAPHORE_POSIX_HPP
+#define BOOST_SYNC_SEMAPHORE_SEMAPHORE_POSIX_HPP
+
+#include <semaphore.h>
+
+#include <boost/assert.hpp>
+#include <boost/thread/exceptions.hpp>
+
+#ifdef BOOST_SYNC_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+
+namespace boost {
+namespace sync {
+
+class semaphore
+{
+ BOOST_DELETED_FUNCTION(semaphore(semaphore const&))
+ BOOST_DELETED_FUNCTION(semaphore& operator=(semaphore const&))
+
+public:
+ semaphore(int i=0)
+ {
+ BOOST_ASSERT_MSG(i >= 0, "boost::sync::semaphore constructor called with negative count");
+
+ const int status = sem_init(&sem, 0, i);
+ if (status)
+ boost::throw_exception(thread_resource_error(status, "boost::sync::semaphore constructor failed in sem_init"));
+ }
+
+ ~semaphore()
+ {
+ const int status = sem_destroy(&sem);
+ (void)status;
+ BOOST_ASSERT(!status);
+ }
+
+ void post()
+ {
+ const int status = sem_post(&sem);
+
+ switch (status)
+ {
+ case EOVERFLOW:
+ boost::throw_exception(thread_resource_error(status, "boost::sync::semaphore post failed: Maximum allowable value would be exceeded"));
+ break;
+
+ case EINVAL:
+ BOOST_ASSERT(false);
+
+ default:
+ break;
+ }
+ }
+
+ void wait(void)
+ {
+ for (;;)
+ {
+ const int status = sem_wait(&sem);
+ if (status == 0)
+ return;
+
+ switch (errno)
+ {
+ case EINTR: // interrupted by a signal handler
+ continue;
+
+ case EINVAL:
+ default:
+ // we should not reach here
+ BOOST_ASSERT(false);
+ return;
+ }
+ }
+ }
+
+ bool try_wait(void)
+ {
+ const int status = sem_trywait(&sem);
+ if (status == 0)
+ return true;
+
+ switch (errno)
+ {
+ case EINVAL:
+ BOOST_ASSERT(false);
+
+ case EAGAIN:
+ return false;
+
+ default:
+ return false;
+ }
+ }
+
+#ifdef BOOST_SYNC_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_wait_for(const chrono::duration<Rep, Period> & rel_time)
+ {
+ return try_wait_until(chrono::steady_clock::now() + rel_time);
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout )
+ {
+ using namespace chrono;
+ system_clock::time_point s_now = system_clock::now();
+ typename Clock::time_point c_now = Clock::now();
+ return try_wait_until(s_now + ceil<nanoseconds>(timeout - c_now));
+ }
+
+ template <class Duration>
+ bool try_wait_until(const chrono::time_point<chrono::system_clock, Duration>& t)
+ {
+ using namespace chrono;
+ typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ return try_wait_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+ }
+
+ bool try_wait_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
+ {
+ chrono::nanoseconds d = tp.time_since_epoch();
+ timespec ts = boost::detail::to_timespec(d);
+ return do_wait_lock_until(ts);
+ }
+
+private:
+ bool do_wait_lock_until(struct timespec const & timeout)
+ {
+ for (;;) {
+ const int status = sem_timedwait(&sem, &timeout);
+ if (status == 0)
+ return true;
+
+ switch (errno)
+ {
+ case ETIMEDOUT:
+ return false;
+
+ case EINTR: // interrupted by a signal handler
+ continue;
+
+ case EINVAL:
+ case EAGAIN:
+ default:
+ BOOST_ASSERT(false);
+ return false;
+ }
+ }
+ }
+
+#endif // BOOST_SYNC_USES_CHRONO
+
+private:
+ sem_t sem;
+};
+
+}
+}
+
+#endif /* BOOST_SYNC_SEMAPHORE_SEMAPHORE_POSIX_HPP */

Added: trunk/boost/sync/semaphore/semaphore_win32.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/semaphore/semaphore_win32.hpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,124 @@
+// semaphore.hpp, win32 semaphores
+//
+// 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_SEMAPHORE_SEMAPHORE_WIN32_HPP
+#define BOOST_SYNC_SEMAPHORE_SEMAPHORE_WIN32_HPP
+
+#include <boost/detail/win/GetLastError.hpp>
+#include <boost/detail/win/synchronization.hpp>
+#include <boost/detail/win/handles.hpp>
+
+#include <boost/typeof/typeof.hpp>
+
+namespace boost {
+namespace sync {
+
+class semaphore
+{
+ BOOST_DELETED_FUNCTION(semaphore(semaphore const&))
+ BOOST_DELETED_FUNCTION(semaphore& operator=(semaphore const&))
+
+ typedef boost::detail::win32::HANDLE_ HANDLE_;
+ typedef boost::detail::win32::DWORD_ DWORD_;
+ typedef boost::detail::win32::LONG_ LONG_;
+ typedef boost::detail::win32::BOOL_ BOOL_;
+
+public:
+ semaphore(int i=0)
+ {
+ BOOST_ASSERT_MSG(i >= 0, "boost::sync::semaphore constructor called with negative count");
+
+ sem_ = boost::detail::win32::CreateSemaphoreA(NULL, i, (std::numeric_limits<LONG_>::max)(), NULL);
+ if (!sem_)
+ boost::throw_exception(thread_resource_error(boost::detail::win32::GetLastError(), "boost::sync::semaphore constructor failed in CreateSemaphore"));
+ }
+
+ ~semaphore()
+ {
+ boost::detail::win32::CloseHandle(sem_);
+ }
+
+ void post()
+ {
+ const BOOL_ status = boost::detail::win32::ReleaseSemaphore(sem_, 1, NULL);
+ if (status == 0)
+ boost::throw_exception(thread_resource_error(boost::detail::win32::GetLastError(), "boost::sync::semaphore::post failed in ReleaseSemaphore"));
+ }
+
+
+ bool wait()
+ {
+ using namespace boost::detail::win32;
+
+ switch ( WaitForSingleObject(sem_, INFINITE) )
+ {
+ case wait_object_0:
+ return true;
+
+ case wait_failed:
+ boost::throw_exception(thread_resource_error(boost::detail::win32::GetLastError(), "boost::sync::semaphore::wait failed in WaitForSingleObject"));
+
+ default:
+ BOOST_ASSERT(false);
+ return false;
+ }
+ }
+
+
+ bool try_wait()
+ {
+ return do_try_wait_for( 0L );
+ }
+
+#ifdef BOOST_SYNC_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_wait_for(const chrono::duration<Rep, Period> & rel_time)
+ {
+ BOOST_AUTO ( milliseconds, (DWORD_)chrono::duration_cast<chrono::milliseconds>( rel_time ) );
+ return do_try_wait_for( milliseconds.count() );
+ }
+
+ template <class Clock, class Duration>
+ bool try_wait_until(const chrono::time_point<Clock, Duration> & timeout )
+ {
+ typename Clock::time_point c_now = Clock::now();
+ return try_wait_for( timeout - c_now );
+ }
+#endif
+
+private:
+#ifdef BOOST_SYNC_USES_CHRONO
+ bool do_try_wait_for( long milliseconds )
+ {
+ using namespace boost::detail::win32;
+
+ switch ( WaitForSingleObject(sem_, milliseconds) )
+ {
+ case wait_object_0:
+ return true;
+
+ case wait_timeout:
+ return false;
+
+ case wait_failed:
+ boost::throw_exception(thread_resource_error(boost::detail::win32::GetLastError(), "boost::sync::semaphore::do_try_wait_for failed in WaitForSingleObject"));
+
+ default:
+ BOOST_ASSERT(false);
+ return false;
+ }
+ }
+#endif
+
+ HANDLE_ sem_;
+};
+
+}
+}
+
+#endif // BOOST_SYNC_SEMAPHORE_SEMAPHORE_WIN32_HPP

Added: trunk/libs/sync/test/Jamfile.v2
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/Jamfile.v2 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,37 @@
+# (C) Copyright 2010: 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)
+
+import testing ;
+
+lib boost_unit_test_framework ;
+lib boost_thread ;
+lib boost_system ;
+
+project
+ : source-location .
+ : requirements
+ <hardcode-dll-paths>true
+ <library>../../test/build//boost_test_exec_monitor
+ ;
+
+
+rule test_all
+{
+ local all_rules = ;
+
+ for local fileb in [ glob *.cpp ]
+ {
+ all_rules += [ run $(fileb)
+ : # additional args
+ : # test-files
+ : # requirements
+ <library>../../thread/build//boost_thread/
+ <threading>multi
+ ] ;
+ }
+
+ return $(all_rules) ;
+}
+
+test-suite sync : [ test_all r ] : <threading>multi ;

Added: trunk/libs/sync/test/semaphore_test.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/semaphore_test.cpp 2013-09-15 06:46:54 EDT (Sun, 15 Sep 2013) (r85673)
@@ -0,0 +1,128 @@
+// 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)
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/thread.hpp>
+#include <boost/sync/semaphore.hpp>
+
+#include <boost/typeof/typeof.hpp>
+
+static void test_semaphore_post_wait()
+{
+ boost::sync::semaphore sem(0);
+
+ sem.post();
+ sem.wait();
+}
+
+
+static void test_semaphore_try_wait()
+{
+ boost::sync::semaphore sem(0);
+
+ BOOST_REQUIRE(!sem.try_wait());
+ sem.post();
+ BOOST_REQUIRE(sem.try_wait());
+}
+
+
+struct semaphore_wait_and_post_test
+{
+ void run()
+ {
+ boost::thread post_thread(boost::bind(&semaphore_wait_and_post_test::wait_and_post, this));
+ sem_.wait();
+ }
+
+ void wait_and_post()
+ {
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ sem_.post();
+ }
+
+ static void run_test()
+ {
+ semaphore_wait_and_post_test test;
+ test.run();
+ }
+
+ boost::sync::semaphore sem_;
+ boost::thread thread_;
+};
+
+#ifdef BOOST_SYNC_USES_CHRONO
+
+static void test_semaphore_wait_for()
+{
+ using namespace boost;
+
+ sync::semaphore sem(0);
+
+ BOOST_AUTO(start, chrono::system_clock::now());
+
+ BOOST_REQUIRE(!sem.try_wait_for(chrono::milliseconds(500)));
+
+ BOOST_AUTO(end, chrono::system_clock::now());
+ BOOST_AUTO(wait_time, end - start);
+
+ // guessing!
+ BOOST_REQUIRE( wait_time > chrono::milliseconds(450) );
+ BOOST_REQUIRE( wait_time < chrono::milliseconds(1000) );
+
+ sem.post();
+
+ BOOST_REQUIRE(sem.try_wait_for(chrono::milliseconds(500)));
+}
+
+static void test_semaphore_wait_until()
+{
+ using namespace boost;
+
+ sync::semaphore sem(0);
+ {
+ BOOST_AUTO(now, chrono::system_clock::now());
+ BOOST_AUTO(timeout, now + chrono::milliseconds(500));
+
+ BOOST_REQUIRE(!sem.try_wait_until(timeout));
+
+ BOOST_AUTO(end, chrono::system_clock::now());
+ BOOST_AUTO(timeout_delta, end - timeout);
+
+ // guessing!
+ BOOST_REQUIRE( timeout_delta > chrono::milliseconds(-400) );
+ BOOST_REQUIRE( timeout_delta < chrono::milliseconds(400) );
+ }
+
+ sem.post();
+
+ {
+ BOOST_AUTO(start, chrono::system_clock::now());
+ BOOST_AUTO(timeout, start + chrono::milliseconds(500));
+
+ BOOST_REQUIRE(sem.try_wait_until(timeout));
+
+ BOOST_AUTO(end, chrono::system_clock::now());
+
+ // guessing!
+ BOOST_REQUIRE( (end - start) < chrono::milliseconds(100) );
+ }
+}
+#endif
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: semaphore test suite");
+
+ test->add(BOOST_TEST_CASE(test_semaphore_post_wait));
+ test->add(BOOST_TEST_CASE(test_semaphore_try_wait));
+ test->add(BOOST_TEST_CASE(semaphore_wait_and_post_test::run_test));
+
+#ifdef BOOST_SYNC_USES_CHRONO
+ test->add(BOOST_TEST_CASE(test_semaphore_wait_for));
+ test->add(BOOST_TEST_CASE(test_semaphore_wait_until));
+#endif
+ return test;
+}


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