summaryrefslogtreecommitdiff
path: root/boost/interprocess/sync/windows
diff options
context:
space:
mode:
Diffstat (limited to 'boost/interprocess/sync/windows')
-rw-r--r--boost/interprocess/sync/windows/condition.hpp383
-rw-r--r--boost/interprocess/sync/windows/mutex.hpp137
-rw-r--r--boost/interprocess/sync/windows/recursive_mutex.hpp43
-rw-r--r--boost/interprocess/sync/windows/semaphore.hpp137
-rw-r--r--boost/interprocess/sync/windows/sync_utils.hpp173
5 files changed, 873 insertions, 0 deletions
diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp
new file mode 100644
index 0000000000..167b8730c3
--- /dev/null
+++ b/boost/interprocess/sync/windows/condition.hpp
@@ -0,0 +1,383 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/windows/semaphore.hpp>
+#include <boost/interprocess/sync/windows/mutex.hpp>
+#include <boost/cstdint.hpp>
+#include <limits>
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//
+// Condition variable algorithm taken from pthreads-win32 discussion.
+//
+// The algorithm was developed by Alexander Terekhov in colaboration with
+// Louis Thomas.
+//
+// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+//
+// semBlockLock - bin.semaphore
+// semBlockQueue - semaphore
+// mtxExternal - mutex or CS
+// mtxUnblockLock - mutex or CS
+// nWaitersGone - int
+// nWaitersBlocked - int
+// nWaitersToUnblock - int
+//
+// wait( timeout ) {
+//
+// [auto: register int result ] // error checking omitted
+// [auto: register int nSignalsWasLeft ]
+// [auto: register int nWaitersWasGone ]
+//
+// sem_wait( semBlockLock );
+// nWaitersBlocked++;
+// sem_post( semBlockLock );
+//
+// unlock( mtxExternal );
+// bTimedOut = sem_wait( semBlockQueue,timeout );
+//
+// lock( mtxUnblockLock );
+// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+// if ( bTimedOut ) { // timeout (or canceled)
+// if ( 0 != nWaitersBlocked ) {
+// nWaitersBlocked--;
+// }
+// else {
+// nWaitersGone++; // count spurious wakeups.
+// }
+// }
+// if ( 0 == --nWaitersToUnblock ) {
+// if ( 0 != nWaitersBlocked ) {
+// sem_post( semBlockLock ); // open the gate.
+// nSignalsWasLeft = 0; // do not open the gate
+// // below again.
+// }
+// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+// nWaitersGone = 0;
+// }
+// }
+// }
+// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+// // spurious semaphore :-)
+// sem_wait( semBlockLock );
+// nWaitersBlocked -= nWaitersGone; // something is going on here
+// // - test of timeouts? :-)
+// sem_post( semBlockLock );
+// nWaitersGone = 0;
+// }
+// unlock( mtxUnblockLock );
+//
+// if ( 1 == nSignalsWasLeft ) {
+// if ( 0 != nWaitersWasGone ) {
+// // sem_adjust( semBlockQueue,-nWaitersWasGone );
+// while ( nWaitersWasGone-- ) {
+// sem_wait( semBlockQueue ); // better now than spurious later
+// }
+// } sem_post( semBlockLock ); // open the gate
+// }
+//
+// lock( mtxExternal );
+//
+// return ( bTimedOut ) ? ETIMEOUT : 0;
+// }
+//
+// signal(bAll) {
+//
+// [auto: register int result ]
+// [auto: register int nSignalsToIssue]
+//
+// lock( mtxUnblockLock );
+//
+// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+// if ( 0 == nWaitersBlocked ) { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+// if (bAll) {
+// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = 1;
+// nWaitersToUnblock++;
+// nWaitersBlocked--;
+// }
+// }
+// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+// sem_wait( semBlockLock ); // close the gate
+// if ( 0 != nWaitersGone ) {
+// nWaitersBlocked -= nWaitersGone;
+// nWaitersGone = 0;
+// }
+// if (bAll) {
+// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = nWaitersToUnblock = 1;
+// nWaitersBlocked--;
+// }
+// }
+// else { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+//
+// unlock( mtxUnblockLock );
+// sem_post( semBlockQueue,nSignalsToIssue );
+// return result;
+// }
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_condition
+{
+ windows_condition(const windows_condition &);
+ windows_condition &operator=(const windows_condition &);
+ public:
+ windows_condition();
+ ~windows_condition();
+
+ void notify_one();
+ void notify_all();
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ return this->do_timed_wait(abs_time, *lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ while (!pred()){
+ if (!this->do_timed_wait(abs_time, *lock.mutex()))
+ return pred();
+ }
+ return true;
+ }
+
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ do_wait(*lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ do_wait(*lock.mutex());
+ }
+
+ template<class InterprocessMutex>
+ void do_wait(InterprocessMutex &mut);
+
+ template<class InterprocessMutex>
+ bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+
+ private:
+
+ template<class InterprocessMutex>
+ bool do_timed_wait(bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ void do_signal (bool broadcast);
+
+ boost::int32_t m_nwaiters_blocked;
+ boost::int32_t m_nwaiters_gone;
+ boost::int32_t m_nwaiters_to_unblock;
+ windows_semaphore m_sem_block_queue;
+ windows_semaphore m_sem_block_lock;
+ windows_mutex m_mtx_unblock_lock;
+};
+
+inline windows_condition::windows_condition()
+ : m_nwaiters_blocked(0)
+ , m_nwaiters_gone(0)
+ , m_nwaiters_to_unblock(0)
+ , m_sem_block_queue(0)
+ , m_sem_block_lock(1)
+ , m_mtx_unblock_lock()
+{}
+
+inline windows_condition::~windows_condition()
+{}
+
+inline void windows_condition::notify_one()
+{ this->do_signal(false); }
+
+inline void windows_condition::notify_all()
+{ this->do_signal(true); }
+
+inline void windows_condition::do_signal(bool broadcast)
+{
+ boost::int32_t nsignals_to_issue;
+
+ {
+ scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
+
+ if ( 0 != m_nwaiters_to_unblock ) { // the gate is closed!!!
+ if ( 0 == m_nwaiters_blocked ) { // NO-OP
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ return;
+ }
+ if (broadcast) {
+ m_nwaiters_to_unblock += nsignals_to_issue = m_nwaiters_blocked;
+ m_nwaiters_blocked = 0;
+ }
+ else {
+ nsignals_to_issue = 1;
+ m_nwaiters_to_unblock++;
+ m_nwaiters_blocked--;
+ }
+ }
+ else if ( m_nwaiters_blocked > m_nwaiters_gone ) { // HARMLESS RACE CONDITION!
+ m_sem_block_lock.wait(); // close the gate
+ if ( 0 != m_nwaiters_gone ) {
+ m_nwaiters_blocked -= m_nwaiters_gone;
+ m_nwaiters_gone = 0;
+ }
+ if (broadcast) {
+ nsignals_to_issue = m_nwaiters_to_unblock = m_nwaiters_blocked;
+ m_nwaiters_blocked = 0;
+ }
+ else {
+ nsignals_to_issue = m_nwaiters_to_unblock = 1;
+ m_nwaiters_blocked--;
+ }
+ }
+ else { // NO-OP
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ return;
+ }
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ }
+ m_sem_block_queue.post(nsignals_to_issue);
+}
+
+template<class InterprocessMutex>
+inline void windows_condition::do_wait(InterprocessMutex &mut)
+{ this->do_timed_wait(false, boost::posix_time::ptime(), mut); }
+
+template<class InterprocessMutex>
+inline bool windows_condition::do_timed_wait
+ (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
+{ return this->do_timed_wait(true, abs_time, mut); }
+
+template<class InterprocessMutex>
+inline bool windows_condition::do_timed_wait
+ (bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal)
+{
+ //Initialize to avoid warnings
+ boost::int32_t nsignals_was_left = 0;
+ boost::int32_t nwaiters_was_gone = 0;
+
+ m_sem_block_lock.wait();
+ ++m_nwaiters_blocked;
+ m_sem_block_lock.post();
+
+ struct scoped_unlock
+ {
+ InterprocessMutex & mut;
+ scoped_unlock(InterprocessMutex & m)
+ : mut(m)
+ { m.unlock(); }
+
+ ~scoped_unlock()
+ { mut.lock(); }
+ } unlocker(mtxExternal);
+
+
+ bool bTimedOut = tout_enabled ? !m_sem_block_queue.timed_wait(abs_time) : (m_sem_block_queue.wait(), false);
+
+ {
+ scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
+ if ( 0 != (nsignals_was_left = m_nwaiters_to_unblock) ) {
+ if ( bTimedOut ) { // timeout (or canceled)
+ if ( 0 != m_nwaiters_blocked ) {
+ m_nwaiters_blocked--;
+ }
+ else {
+ m_nwaiters_gone++; // count spurious wakeups.
+ }
+ }
+ if ( 0 == --m_nwaiters_to_unblock ) {
+ if ( 0 != m_nwaiters_blocked ) {
+ m_sem_block_lock.post(); // open the gate.
+ nsignals_was_left = 0; // do not open the gate below again.
+ }
+ else if ( 0 != (nwaiters_was_gone = m_nwaiters_gone) ) {
+ m_nwaiters_gone = 0;
+ }
+ }
+ }
+ else if ( (std::numeric_limits<boost::int32_t>::max)()/2
+ == ++m_nwaiters_gone ) { // timeout/canceled or spurious semaphore :-)
+ m_sem_block_lock.wait();
+ m_nwaiters_blocked -= m_nwaiters_gone; // something is going on here - test of timeouts? :-)
+ m_sem_block_lock.post();
+ m_nwaiters_gone = 0;
+ }
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ }
+
+ if ( 1 == nsignals_was_left ) {
+ if ( 0 != nwaiters_was_gone ) {
+ // sem_adjust( m_sem_block_queue,-nwaiters_was_gone );
+ while ( nwaiters_was_gone-- ) {
+ m_sem_block_queue.wait(); // better now than spurious later
+ }
+ }
+ m_sem_block_lock.post(); // open the gate
+ }
+
+ //mtxExternal.lock(); called from unlocker
+
+ return ( bTimedOut ) ? false : true;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp
new file mode 100644
index 0000000000..5eca522339
--- /dev/null
+++ b/boost/interprocess/sync/windows/mutex.hpp
@@ -0,0 +1,137 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_mutex
+{
+ windows_mutex(const windows_mutex &);
+ windows_mutex &operator=(const windows_mutex &);
+ public:
+
+ windows_mutex();
+ ~windows_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+ void take_ownership(){};
+
+ private:
+ const sync_id id_;
+};
+
+inline windows_mutex::windows_mutex()
+ : id_()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //Create mutex with the initial count
+ bool open_or_created;
+ handles.obtain_mutex(this->id_, &open_or_created);
+ //The mutex must be created, never opened
+ assert(open_or_created);
+ assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ (void)open_or_created;
+}
+
+inline windows_mutex::~windows_mutex()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ handles.destroy_handle(this->id_);
+}
+
+inline void windows_mutex::lock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool windows_mutex::try_lock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, 0);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ boost::posix_time::ptime now
+ = boost::posix_time::microsec_clock::universal_time();
+
+ unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, ms);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline void windows_mutex::unlock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ int ret = winapi::release_mutex(hnd);
+ (void)ret;
+ assert(ret);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
diff --git a/boost/interprocess/sync/windows/recursive_mutex.hpp b/boost/interprocess/sync/windows/recursive_mutex.hpp
new file mode 100644
index 0000000000..9565cb6fb4
--- /dev/null
+++ b/boost/interprocess/sync/windows/recursive_mutex.hpp
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/windows/mutex.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+//Windows mutex is already recursive
+class windows_recursive_mutex
+ : public windows_mutex
+{
+ windows_recursive_mutex(const windows_recursive_mutex &);
+ windows_recursive_mutex &operator=(const windows_recursive_mutex &);
+ public:
+ windows_recursive_mutex() : windows_mutex() {}
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp
new file mode 100644
index 0000000000..d5835ceec7
--- /dev/null
+++ b/boost/interprocess/sync/windows/semaphore.hpp
@@ -0,0 +1,137 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_semaphore
+{
+ windows_semaphore(const windows_semaphore &);
+ windows_semaphore &operator=(const windows_semaphore &);
+ public:
+
+ windows_semaphore(unsigned int initialCount);
+ ~windows_semaphore();
+
+ void post(long release_count = 1);
+ void wait();
+ bool try_wait();
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ private:
+ const sync_id id_;
+};
+
+inline windows_semaphore::windows_semaphore(unsigned int initialCount)
+ : id_()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //Force smeaphore creation with the initial count
+ bool open_or_created;
+ handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
+ //The semaphore must be created, never opened
+ assert(open_or_created);
+ assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ (void)open_or_created;
+}
+
+inline windows_semaphore::~windows_semaphore()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ handles.destroy_handle(this->id_);
+}
+
+inline void windows_semaphore::wait(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool windows_semaphore::try_wait(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, 0);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline bool windows_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ boost::posix_time::ptime now
+ = boost::posix_time::microsec_clock::universal_time();
+
+ unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, ms);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline void windows_semaphore::post(long release_count)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ long prev_count;
+ int ret = winapi::release_semaphore(hnd, release_count, &prev_count);
+ (void)ret;
+ assert(ret);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp
new file mode 100644
index 0000000000..89c4aeda0b
--- /dev/null
+++ b/boost/interprocess/sync/windows/sync_utils.hpp
@@ -0,0 +1,173 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
+#define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/unordered/unordered_map.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
+{
+ const std::size_t need_mem = mem_length*2+1;
+ if(out_length < need_mem){
+ return false;
+ }
+
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ std::size_t char_counter = 0;
+ const char *buf = (const char *)mem;
+ for(std::size_t i = 0; i != mem_length; ++i){
+ out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
+ out_str[char_counter++] = Characters[(buf[i]&0x0F)];
+ }
+ out_str[char_counter] = 0;
+ return true;
+}
+
+struct sync_id
+{
+ sync_id()
+ { winapi::query_performance_counter(&rand); }
+
+ __int64 rand;
+
+ friend std::size_t hash_value(const sync_id &m)
+ { return boost::hash_value(m.rand); }
+
+ friend bool operator==(const sync_id &l, const sync_id &r)
+ { return l.rand == r.rand; }
+};
+/*
+#define BOOST_NO_LONG_LONG ss
+
+#if defined(BOOST_NO_LONG_LONG)
+
+#error "defined(BOOST_NO_LONG_LONG)"
+#else
+#error "NOT defined(BOOST_NO_LONG_LONG)"
+#endif
+*/
+class sync_handles
+{
+ public:
+ enum type { MUTEX, SEMAPHORE };
+
+ private:
+ typedef boost::unordered_map<sync_id, void*> map_type;
+ static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
+ static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
+ typedef char NameBuf[StrSize];
+
+ void fill_name(NameBuf &name, const sync_id &id)
+ {
+ const char *n = "Global\\boost.ipc";
+ std::size_t i = 0;
+ do{
+ name[i] = n[i];
+ ++i;
+ } while(n[i]);
+ std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
+ bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len);
+ }
+
+ void erase_and_throw_if_error(void *hnd_val, const sync_id &id)
+ {
+ if(!hnd_val){
+ map_.erase(id);
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ }
+
+ void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
+ {
+ NameBuf name;
+ fill_name(name, id);
+ void *hnd_val = winapi::open_or_create_semaphore
+ (name, (long)initial_count, (long)(((unsigned long)(-1))>>1), unrestricted_security.get_attributes());
+ erase_and_throw_if_error(hnd_val, id);
+ return hnd_val;
+ }
+
+ void* open_or_create_mutex(const sync_id &id)
+ {
+ NameBuf name;
+ fill_name(name, id);
+ void *hnd_val = winapi::open_or_create_mutex
+ (name, false, unrestricted_security.get_attributes());
+ erase_and_throw_if_error(hnd_val, id);
+ return hnd_val;
+ }
+
+ public:
+ void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ void *&hnd_val = map_[id];
+ if(!hnd_val){
+ hnd_val = open_or_create_mutex(id);
+ if(popen_created) *popen_created = true;
+ }
+ return hnd_val;
+ }
+
+ void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ void *&hnd_val = map_[id];
+ if(!hnd_val){
+ hnd_val = open_or_create_semaphore(id, initial_count);
+ if(popen_created) *popen_created = true;
+ }
+ return hnd_val;
+ }
+
+ void destroy_handle(const sync_id &id)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ map_type::iterator it = map_.find(id);
+ if(it != map_.end()){
+ winapi::close_handle(it->second);
+ map_.erase(it);
+ }
+ }
+
+ private:
+ winapi::interprocess_all_access_security unrestricted_security;
+ spin_mutex mtx_;
+ map_type map_;
+};
+
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP