$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;
+}