diff options
Diffstat (limited to 'boost/interprocess/sync')
41 files changed, 2175 insertions, 711 deletions
diff --git a/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp new file mode 100644 index 0000000000..eaad671cdf --- /dev/null +++ b/boost/interprocess/sync/detail/condition_algorithm_8a.hpp @@ -0,0 +1,316 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CONDITION_ALGORITHM_8A_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// 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; +// } +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + +// Required interface for ConditionMembers +// class ConditionMembers +// { +// typedef implementation_defined semaphore_type; +// typedef implementation_defined mutex_type; +// typedef implementation_defined integer_type; +// +// integer_type &get_nwaiters_blocked() +// integer_type &get_nwaiters_gone() +// integer_type &get_nwaiters_to_unblock() +// semaphore_type &get_sem_block_queue() +// semaphore_type &get_sem_block_lock() +// mutex_type &get_mtx_unblock_lock() +// }; +// +template<class ConditionMembers> +class condition_algorithm_8a +{ + private: + condition_algorithm_8a(); + ~condition_algorithm_8a(); + condition_algorithm_8a(const condition_algorithm_8a &); + condition_algorithm_8a &operator=(const condition_algorithm_8a &); + + typedef typename ConditionMembers::semaphore_type semaphore_type; + typedef typename ConditionMembers::mutex_type mutex_type; + typedef typename ConditionMembers::integer_type integer_type; + + // nwaiters_blocked == 0 + // nwaiters_gone() == 0 + // nwaiters_to_unblock == 0 + // sem_block_queue() == initial count 0 + // sem_block_lock() == initial count 1 + // mtx_unblock_lock (unlocked) + + public: + template<class InterprocessMutex> + static bool wait (ConditionMembers &data, bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); + static void signal(ConditionMembers &data, bool broadcast); +}; + +template<class ConditionMembers> +inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast) +{ + integer_type nsignals_to_issue; + + { + scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock()); + + if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!! + if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + return; + } + if (broadcast) { + data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked(); + data.get_nwaiters_blocked() = 0; + } + else { + nsignals_to_issue = 1; + data.get_nwaiters_to_unblock()++; + data.get_nwaiters_blocked()--; + } + } + else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION! + data.get_sem_block_lock().wait(); // close the gate + if ( 0 != data.get_nwaiters_gone() ) { + data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); + data.get_nwaiters_gone() = 0; + } + if (broadcast) { + nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked(); + data.get_nwaiters_blocked() = 0; + } + else { + nsignals_to_issue = data.get_nwaiters_to_unblock() = 1; + data.get_nwaiters_blocked()--; + } + } + else { // NO-OP + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + return; + } + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + } + data.get_sem_block_queue().post(nsignals_to_issue); +} + +template<class ConditionMembers> +template<class InterprocessMutex> +inline bool condition_algorithm_8a<ConditionMembers>::wait + (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal) +{ + //Initialize to avoid warnings + integer_type nsignals_was_left = 0; + integer_type nwaiters_was_gone = 0; + + data.get_sem_block_lock().wait(); + ++data.get_nwaiters_blocked(); + data.get_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 ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false); + + { + scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock()); + if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) { + if ( bTimedOut ) { // timeout (or canceled) + if ( 0 != data.get_nwaiters_blocked() ) { + data.get_nwaiters_blocked()--; + } + else { + data.get_nwaiters_gone()++; // count spurious wakeups. + } + } + if ( 0 == --data.get_nwaiters_to_unblock() ) { + if ( 0 != data.get_nwaiters_blocked() ) { + data.get_sem_block_lock().post(); // open the gate. + nsignals_was_left = 0; // do not open the gate below again. + } + else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) { + data.get_nwaiters_gone() = 0; + } + } + } + else if ( (std::numeric_limits<integer_type>::max)()/2 + == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-) + data.get_sem_block_lock().wait(); + data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-) + data.get_sem_block_lock().post(); + data.get_nwaiters_gone() = 0; + } + //locker's destructor triggers data.get_mtx_unblock_lock().unlock() + } + + if ( 1 == nsignals_was_left ) { + if ( 0 != nwaiters_was_gone ) { + // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone ); + while ( nwaiters_was_gone-- ) { + data.get_sem_block_queue().wait(); // better now than spurious later + } + } + data.get_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_CONDITION_ALGORITHM_8A_HPP diff --git a/boost/interprocess/sync/file_lock.hpp b/boost/interprocess/sync/file_lock.hpp index a60b814a4f..e0f75465fb 100644 --- a/boost/interprocess/sync/file_lock.hpp +++ b/boost/interprocess/sync/file_lock.hpp @@ -53,21 +53,21 @@ class file_lock //!exist or there are no operating system resources. file_lock(const char *name); - //!Moves the ownership of "moved"'s file mapping object to *this. - //!After the call, "moved" does not represent any file mapping object. + //!Moves the ownership of "moved"'s file mapping object to *this. + //!After the call, "moved" does not represent any file mapping object. //!Does not throw file_lock(BOOST_RV_REF(file_lock) moved) : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) { this->swap(moved); } //!Moves the ownership of "moved"'s file mapping to *this. - //!After the call, "moved" does not represent any file mapping. + //!After the call, "moved" does not represent any file mapping. //!Does not throw file_lock &operator=(BOOST_RV_REF(file_lock) moved) - { + { file_lock tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Closes a file lock. Does not throw. @@ -81,7 +81,7 @@ class file_lock m_file_hnd = other.m_file_hnd; other.m_file_hnd = tmp; } - + //Exclusive locking //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, @@ -101,12 +101,12 @@ class file_lock //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, or sharable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock(); @@ -120,21 +120,21 @@ class file_lock //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership of the - //! mutex this succeeds. + //! mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! has to wait, returns false. //!Throws: interprocess_exception on error. bool try_lock_sharable(); //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! waiting if necessary until no other thread has exclusive ownership of - //! the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //! the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_sharable(); /// @cond @@ -171,7 +171,7 @@ class file_lock bool timed_acquire_file_lock_sharable (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) - { + { //Obtain current count and target time boost::posix_time::ptime now = microsec_clock::universal_time(); using namespace boost::detail; diff --git a/boost/interprocess/sync/interprocess_condition.hpp b/boost/interprocess/sync/interprocess_condition.hpp index b0e74fc342..9d0bea640e 100644 --- a/boost/interprocess/sync/interprocess_condition.hpp +++ b/boost/interprocess/sync/interprocess_condition.hpp @@ -30,9 +30,9 @@ #include <boost/interprocess/sync/posix/condition.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/condition.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/condition.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/condition.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -70,7 +70,7 @@ class interprocess_condition //!liberating system resources. ~interprocess_condition(){} - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. void notify_one() { m_condition.notify_one(); } @@ -80,8 +80,8 @@ class interprocess_condition void notify_all() { m_condition.notify_all(); } - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to //!this->notify_one() or this->notify_all(), and then reacquires the lock. template <typename L> void wait(L& lock) @@ -103,9 +103,9 @@ class interprocess_condition this->do_wait(*lock.mutex()); } - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, //!and then reacquires the lock. //!Returns: false if time abs_time is reached, otherwise true. template <typename L> @@ -120,8 +120,8 @@ class interprocess_condition return this->do_timed_wait(abs_time, *lock.mutex()); } - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); //! } return true; template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) diff --git a/boost/interprocess/sync/interprocess_mutex.hpp b/boost/interprocess/sync/interprocess_mutex.hpp index 478cf78cc3..8110c8472b 100644 --- a/boost/interprocess/sync/interprocess_mutex.hpp +++ b/boost/interprocess/sync/interprocess_mutex.hpp @@ -31,9 +31,9 @@ #include <boost/interprocess/sync/posix/mutex.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/mutex.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/mutex.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -61,7 +61,7 @@ namespace interprocess { class interprocess_condition; -//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!Wraps a interprocess_mutex that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_mutex { @@ -98,9 +98,9 @@ class interprocess_mutex //!Effects: The calling thread will try to obtain exclusive ownership of the //! mutex if it can do so in until the specified time is reached. If the //! mutex supports recursive locking, the mutex must be unlocked the same - //! number of times it is locked. + //! number of times it is locked. //!Returns: If the thread acquires ownership of the mutex, returns true, if - //! the timeout expires returns false. + //! the timeout expires returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); diff --git a/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/boost/interprocess/sync/interprocess_recursive_mutex.hpp index 308819ff27..3079108645 100644 --- a/boost/interprocess/sync/interprocess_recursive_mutex.hpp +++ b/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -43,9 +43,9 @@ #include <boost/interprocess/sync/posix/recursive_mutex.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/recursive_mutex.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/recursive_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/recursive_mutex.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -72,8 +72,8 @@ class mutex_traits; namespace boost { namespace interprocess { -//!Wraps a interprocess_mutex that can be placed in shared memory and can be -//!shared between processes. Allows several locking calls by the same +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows several locking calls by the same //!process. Allows timed lock tries class interprocess_recursive_mutex { @@ -99,7 +99,7 @@ class interprocess_recursive_mutex //!Throws: interprocess_exception on error. void lock(); - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. The mutex must be unlocked //!the same number of times it is locked. //!Throws: interprocess_exception if a severe error is found diff --git a/boost/interprocess/sync/interprocess_semaphore.hpp b/boost/interprocess/sync/interprocess_semaphore.hpp index 4ffcdcf691..2a2f34fdcf 100644 --- a/boost/interprocess/sync/interprocess_semaphore.hpp +++ b/boost/interprocess/sync/interprocess_semaphore.hpp @@ -29,9 +29,9 @@ #include <boost/interprocess/sync/posix/semaphore.hpp> #define BOOST_INTERPROCESS_USE_POSIX //Experimental... -//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) -// #include <boost/interprocess/sync/windows/semaphore.hpp> -// #define BOOST_INTERPROCESS_USE_WINDOWS +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/semaphore.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) #include <boost/interprocess/sync/spin/semaphore.hpp> #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION @@ -45,7 +45,7 @@ namespace boost { namespace interprocess { -//!Wraps a interprocess_semaphore that can be placed in shared memory and can be +//!Wraps a interprocess_semaphore that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_semaphore { @@ -55,7 +55,7 @@ class interprocess_semaphore interprocess_semaphore &operator=(const interprocess_semaphore &); /// @endcond public: - //!Creates a interprocess_semaphore with the given initial count. + //!Creates a interprocess_semaphore with the given initial count. //!interprocess_exception if there is an error.*/ interprocess_semaphore(unsigned int initialCount); @@ -69,7 +69,7 @@ class interprocess_semaphore void post(); //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. + //!then the calling process/thread blocks until it can decrement the counter. //!If there is an error an interprocess_exception exception is thrown. void wait(); @@ -95,7 +95,7 @@ class interprocess_semaphore #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) #undef BOOST_INTERPROCESS_USE_WINDOWS ipcdetail::windows_semaphore m_sem; - #else + #else #undef BOOST_INTERPROCESS_USE_POSIX ipcdetail::posix_semaphore m_sem; #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp index 048407f4b3..8d5a452626 100644 --- a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -30,7 +30,7 @@ namespace boost { namespace interprocess { -//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be +//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries class interprocess_upgradable_mutex { @@ -67,13 +67,13 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock(); @@ -87,21 +87,21 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! has to wait, returns false. //!Throws: interprocess_exception on error. bool try_lock_sharable(); //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_sharable(); @@ -115,7 +115,7 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -124,74 +124,74 @@ class interprocess_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release their sharable lock. + //! sharable ownership release their sharable lock. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. */ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! upgradable ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock_upgradable(); @@ -249,7 +249,7 @@ class interprocess_upgradable_mutex if(mp_ctrl){ //Recover upgradable lock mp_ctrl->upgradable_in = 1; - ++mp_ctrl->num_upr_shar; + ++mp_ctrl->num_upr_shar; //Execute the second half of exclusive locking mp_ctrl->exclusive_in = 0; } @@ -260,7 +260,7 @@ class interprocess_upgradable_mutex template<int Dummy> struct base_constants_t { - static const unsigned max_readers + static const unsigned max_readers = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); }; typedef base_constants_t<0> constants; @@ -309,10 +309,10 @@ inline bool interprocess_upgradable_mutex::try_lock() { scoped_lock_t lock(m_mut, try_to_lock); - //If we can't lock or any has there is any exclusive, upgradable + //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() - || this->m_ctrl.exclusive_in + if(!lock.owns() + || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar){ return false; } @@ -387,9 +387,9 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable() //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks - if(!lock.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ return false; } @@ -414,11 +414,11 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable //The upgradable lock must block in the first gate //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks - while(this->m_ctrl.exclusive_in + while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in + return!(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers); } @@ -561,7 +561,7 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -584,7 +584,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() } //Now unlock upgradable and mark exclusive this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; this->m_ctrl.exclusive_in = 1; return true; } @@ -598,7 +598,7 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -618,10 +618,10 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() { scoped_lock_t lock(m_mut, try_to_lock); - //If we can't lock or any has there is any exclusive, upgradable + //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() - || this->m_ctrl.exclusive_in + if(!lock.owns() + || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar != 1){ return false; @@ -638,7 +638,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradab //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired if(!lock.owns() - || this->m_ctrl.exclusive_in + || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ return false; } diff --git a/boost/interprocess/sync/mutex_family.hpp b/boost/interprocess/sync/mutex_family.hpp index a9215e24fe..b153ffea3e 100644 --- a/boost/interprocess/sync/mutex_family.hpp +++ b/boost/interprocess/sync/mutex_family.hpp @@ -29,7 +29,7 @@ namespace boost { namespace interprocess { -//!Describes interprocess_mutex family to use with Interprocess framework +//!Describes interprocess_mutex family to use with Interprocess framework //!based on boost::interprocess synchronization objects. struct mutex_family { @@ -37,7 +37,7 @@ struct mutex_family typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type; }; -//!Describes interprocess_mutex family to use with Interprocess frameworks +//!Describes interprocess_mutex family to use with Interprocess frameworks //!based on null operation synchronization objects. struct null_mutex_family { diff --git a/boost/interprocess/sync/named_condition.hpp b/boost/interprocess/sync/named_condition.hpp index c5529eda6c..ca0205ad73 100644 --- a/boost/interprocess/sync/named_condition.hpp +++ b/boost/interprocess/sync/named_condition.hpp @@ -22,7 +22,12 @@ #include <boost/interprocess/detail/interprocess_tester.hpp> #include <boost/interprocess/permissions.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> -#include <boost/interprocess/sync/shm/named_condition.hpp> +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_condition.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS +#else + #include <boost/interprocess/sync/shm/named_condition.hpp> +#endif //!\file //!Describes a named condition class for inter-process synchronization @@ -50,7 +55,7 @@ class named_condition //!If the condition can't be created throws interprocess_exception named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global condition with a name. + //!Opens or creates a global condition with a name. //!If the condition is created, this call is equivalent to //!named_condition(create_only_t, ... ) //!If the condition is already created, this call is equivalent @@ -71,7 +76,7 @@ class named_condition //!use remove(). ~named_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect.*/ void notify_one(); @@ -79,8 +84,8 @@ class named_condition //!If there are no waiting threads, notify_all() has no effect. void notify_all(); - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to //!this->notify_one() or this->notify_all(), and then reacquires the lock. template <typename L> void wait(L& lock); @@ -90,16 +95,16 @@ class named_condition template <typename L, typename Pr> void wait(L& lock, Pr pred); - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, //!and then reacquires the lock. //!Returns: false if time abs_time is reached, otherwise true. template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); //! } return true; template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); @@ -110,7 +115,12 @@ class named_condition /// @cond private: - ipcdetail::shm_named_condition m_cond; + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_condition condition_type; + #else + typedef ipcdetail::shm_named_condition condition_type; + #endif + condition_type m_cond; friend class ipcdetail::interprocess_tester; void dont_close_on_destruction() @@ -160,7 +170,7 @@ inline bool named_condition::timed_wait { return m_cond.timed_wait(lock, abs_time, pred); } inline bool named_condition::remove(const char *name) -{ return ipcdetail::shm_named_condition::remove(name); } +{ return condition_type::remove(name); } /// @endcond diff --git a/boost/interprocess/sync/named_mutex.hpp b/boost/interprocess/sync/named_mutex.hpp index 3e56b81794..c34193c697 100644 --- a/boost/interprocess/sync/named_mutex.hpp +++ b/boost/interprocess/sync/named_mutex.hpp @@ -24,7 +24,11 @@ #include <boost/interprocess/permissions.hpp> #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) -#include <boost/interprocess/sync/posix/named_mutex.hpp> + #include <boost/interprocess/sync/posix/named_mutex.hpp> + #define BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #else #include <boost/interprocess/sync/shm/named_mutex.hpp> #endif @@ -37,7 +41,7 @@ namespace interprocess { class named_condition; -//!A mutex with a global name, so it can be found from different +//!A mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named_mutex. class named_mutex @@ -56,7 +60,7 @@ class named_mutex //!Throws interprocess_exception on error. named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global mutex with a name. + //!Opens or creates a global mutex with a name. //!If the mutex is created, this call is equivalent to //!named_mutex(create_only_t, ... ) //!If the mutex is already created, this call is equivalent @@ -85,7 +89,7 @@ class named_mutex //!Throws interprocess_exception if a severe error is found void lock(); - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found bool try_lock(); @@ -104,15 +108,20 @@ class named_mutex friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); - #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_mutex impl_t; - impl_t m_mut; + #if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES) + typedef ipcdetail::posix_named_mutex impl_t; + impl_t m_mut; + #undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_mutex impl_t; + impl_t m_mut; + #undef BOOST_INTERPROCESS_USE_WINDOWS #else - typedef ipcdetail::shm_named_mutex impl_t; - impl_t m_mut; - public: - interprocess_mutex *mutex() const - { return m_mut.mutex(); } + typedef ipcdetail::shm_named_mutex impl_t; + impl_t m_mut; + public: + interprocess_mutex *mutex() const + { return m_mut.mutex(); } #endif /// @endcond diff --git a/boost/interprocess/sync/named_recursive_mutex.hpp b/boost/interprocess/sync/named_recursive_mutex.hpp index 28768cea6f..2d4b9b2416 100644 --- a/boost/interprocess/sync/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/named_recursive_mutex.hpp @@ -20,7 +20,12 @@ #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> #include <boost/interprocess/permissions.hpp> -#include <boost/interprocess/sync/shm/named_recursive_mutex.hpp> +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_recursive_mutex.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS +#else + #include <boost/interprocess/sync/shm/named_recursive_mutex.hpp> +#endif //!\file //!Describes a named named_recursive_mutex class for inter-process synchronization @@ -32,7 +37,7 @@ namespace interprocess { namespace ipcdetail{ class interprocess_tester; } /// @endcond -//!A recursive mutex with a global name, so it can be found from different +//!A recursive mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named_recursive_mutex. class named_recursive_mutex @@ -49,7 +54,7 @@ class named_recursive_mutex //!If the recursive_mutex can't be created throws interprocess_exception named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global recursive_mutex with a name. + //!Opens or creates a global recursive_mutex with a name. //!If the recursive_mutex is created, this call is equivalent to //!named_recursive_mutex(create_only_t, ... ) //!If the recursive_mutex is already created, this call is equivalent @@ -78,7 +83,7 @@ class named_recursive_mutex //!Throws interprocess_exception if a severe error is found. void lock(); - //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex + //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found. bool try_lock(); @@ -97,7 +102,12 @@ class named_recursive_mutex friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); - typedef ipcdetail::shm_named_recursive_mutex impl_t; + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_recursive_mutex impl_t; + #undef BOOST_INTERPROCESS_USE_WINDOWS + #else + typedef ipcdetail::shm_named_recursive_mutex impl_t; + #endif impl_t m_mut; /// @endcond diff --git a/boost/interprocess/sync/named_semaphore.hpp b/boost/interprocess/sync/named_semaphore.hpp index 33e06964f9..39c9096fb6 100644 --- a/boost/interprocess/sync/named_semaphore.hpp +++ b/boost/interprocess/sync/named_semaphore.hpp @@ -25,6 +25,10 @@ #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) #include <boost/interprocess/sync/posix/named_semaphore.hpp> +//Experimental... +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include <boost/interprocess/sync/windows/named_semaphore.hpp> + #define BOOST_INTERPROCESS_USE_WINDOWS #else #include <boost/interprocess/sync/shm/named_semaphore.hpp> #endif @@ -35,8 +39,8 @@ namespace boost { namespace interprocess { -//!A semaphore with a global name, so it can be found from different -//!processes. Allows several resource sharing patterns and efficient +//!A semaphore with a global name, so it can be found from different +//!processes. Allows several resource sharing patterns and efficient //!acknowledgment mechanisms. class named_semaphore { @@ -49,11 +53,11 @@ class named_semaphore /// @endcond public: - //!Creates a global semaphore with a name, and an initial count. + //!Creates a global semaphore with a name, and an initial count. //!If the semaphore can't be created throws interprocess_exception named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - //!Opens or creates a global semaphore with a name, and an initial count. + //!Opens or creates a global semaphore with a name, and an initial count. //!If the semaphore is created, this call is equivalent to //!named_semaphore(create_only_t, ...) //!If the semaphore is already created, this call is equivalent to @@ -80,7 +84,7 @@ class named_semaphore void post(); //!Decrements the semaphore. If the semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. + //!then the calling process/thread blocks until it can decrement the counter. //!If there is an error an interprocess_exception exception is thrown. void wait(); @@ -106,9 +110,12 @@ class named_semaphore void dont_close_on_destruction(); #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_semaphore impl_t; + typedef ipcdetail::posix_named_semaphore impl_t; + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + #undef BOOST_INTERPROCESS_USE_WINDOWS + typedef ipcdetail::windows_named_semaphore impl_t; #else - typedef ipcdetail::shm_named_semaphore impl_t; + typedef ipcdetail::shm_named_semaphore impl_t; #endif impl_t m_sem; /// @endcond diff --git a/boost/interprocess/sync/named_upgradable_mutex.hpp b/boost/interprocess/sync/named_upgradable_mutex.hpp index 61c6bb4086..c45fd08270 100644 --- a/boost/interprocess/sync/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -38,7 +38,7 @@ namespace ipcdetail{ class interprocess_tester; } class named_condition; -//!A upgradable mutex with a global name, so it can be found from different +//!A upgradable mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named upgradable mutex. class named_upgradable_mutex @@ -52,11 +52,11 @@ class named_upgradable_mutex /// @endcond public: - //!Creates a global upgradable mutex with a name. + //!Creates a global upgradable mutex with a name. //!If the upgradable mutex can't be created throws interprocess_exception named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!Opens or creates a global upgradable mutex with a name, and an initial count. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -95,13 +95,13 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock(); @@ -115,21 +115,21 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! has to wait, returns false. //!Throws: interprocess_exception on error. bool try_lock_sharable(); //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_sharable(); @@ -143,7 +143,7 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -152,66 +152,66 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. + //! sharable ownership release it. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); diff --git a/boost/interprocess/sync/posix/condition.hpp b/boost/interprocess/sync/posix/condition.hpp index 213e4ce8b5..48be099f60 100644 --- a/boost/interprocess/sync/posix/condition.hpp +++ b/boost/interprocess/sync/posix/condition.hpp @@ -19,7 +19,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/sync/posix/pthread_helpers.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -44,7 +44,7 @@ class posix_condition //!liberating system resources. ~posix_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. void notify_one(); @@ -52,8 +52,8 @@ class posix_condition //!If there are no waiting threads, notify_all() has no effect. void notify_all(); - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to //!this->notify_one() or this->notify_all(), and then reacquires the lock. template <typename L> void wait(L& lock) @@ -75,9 +75,9 @@ class posix_condition this->do_wait(*lock.mutex()); } - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, //!and then reacquires the lock. //!Returns: false if time abs_time is reached, otherwise true. template <typename L> @@ -92,8 +92,8 @@ class posix_condition return this->do_timed_wait(abs_time, *lock.mutex()); } - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); //! } return true; template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) diff --git a/boost/interprocess/sync/posix/mutex.hpp b/boost/interprocess/sync/posix/mutex.hpp index 22e2ec04b9..393807c97a 100644 --- a/boost/interprocess/sync/posix/mutex.hpp +++ b/boost/interprocess/sync/posix/mutex.hpp @@ -35,7 +35,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -80,7 +80,7 @@ inline posix_mutex::posix_mutex() mut.release(); } -inline posix_mutex::~posix_mutex() +inline posix_mutex::~posix_mutex() { int res = pthread_mutex_destroy(&m_mut); BOOST_ASSERT(res == 0);(void)res; @@ -88,7 +88,7 @@ inline posix_mutex::~posix_mutex() inline void posix_mutex::lock() { - if (pthread_mutex_lock(&m_mut) != 0) + if (pthread_mutex_lock(&m_mut) != 0) throw lock_exception(); } diff --git a/boost/interprocess/sync/posix/pthread_helpers.hpp b/boost/interprocess/sync/posix/pthread_helpers.hpp index c09ce200cf..bcbc44be33 100644 --- a/boost/interprocess/sync/posix/pthread_helpers.hpp +++ b/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -19,8 +19,8 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> -#include <boost/interprocess/exceptions.hpp> +#include <errno.h> +#include <boost/interprocess/exceptions.hpp> namespace boost { namespace interprocess { @@ -29,7 +29,7 @@ namespace ipcdetail{ #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED //!Makes pthread_mutexattr_t cleanup easy when using exceptions - struct mutexattr_wrapper + struct mutexattr_wrapper { //!Constructor mutexattr_wrapper(bool recursive = false) @@ -51,7 +51,7 @@ namespace ipcdetail{ }; //!Makes pthread_condattr_t cleanup easy when using exceptions - struct condattr_wrapper + struct condattr_wrapper { //!Constructor condattr_wrapper() @@ -86,7 +86,7 @@ namespace ipcdetail{ void release() {mp_mut = 0; } - private: + private: pthread_mutex_t *mp_mut; }; @@ -94,7 +94,7 @@ namespace ipcdetail{ class condition_initializer { public: - condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) + condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) : mp_cond(&cond) { if(pthread_cond_init(mp_cond, &cond_attr)!= 0) @@ -105,7 +105,7 @@ namespace ipcdetail{ void release() { mp_cond = 0; } - private: + private: pthread_cond_t *mp_cond; }; @@ -114,7 +114,7 @@ namespace ipcdetail{ #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) //!Makes pthread_barrierattr_t cleanup easy when using exceptions - struct barrierattr_wrapper + struct barrierattr_wrapper { //!Constructor barrierattr_wrapper() @@ -138,8 +138,8 @@ namespace ipcdetail{ { public: //!Constructor. Takes barrier attributes to initialize the barrier - barrier_initializer(pthread_barrier_t &mut, - pthread_barrierattr_t &mut_attr, + barrier_initializer(pthread_barrier_t &mut, + pthread_barrierattr_t &mut_attr, int count) : mp_barrier(&mut) { @@ -151,7 +151,7 @@ namespace ipcdetail{ void release() {mp_barrier = 0; } - private: + private: pthread_barrier_t *mp_barrier; }; diff --git a/boost/interprocess/sync/posix/recursive_mutex.hpp b/boost/interprocess/sync/posix/recursive_mutex.hpp index baa670fa9a..456c9a4874 100644 --- a/boost/interprocess/sync/posix/recursive_mutex.hpp +++ b/boost/interprocess/sync/posix/recursive_mutex.hpp @@ -31,7 +31,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <pthread.h> -#include <errno.h> +#include <errno.h> #include <boost/interprocess/sync/posix/pthread_helpers.hpp> #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> @@ -78,7 +78,7 @@ inline posix_recursive_mutex::~posix_recursive_mutex() inline void posix_recursive_mutex::lock() { - if (pthread_mutex_lock(&m_mut) != 0) + if (pthread_mutex_lock(&m_mut) != 0) throw lock_exception(); } diff --git a/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/boost/interprocess/sync/posix/semaphore_wrapper.hpp index 1aeef47662..22184cda9d 100644 --- a/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ b/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -18,7 +18,7 @@ #include <boost/interprocess/detail/tmp_dir_helpers.hpp> #include <boost/interprocess/permissions.hpp> -#include <fcntl.h> //O_CREAT, O_*... +#include <fcntl.h> //O_CREAT, O_*... #include <unistd.h> //close #include <string> //std::string #include <semaphore.h> //sem_* family, SEM_VALUE_MAX @@ -42,7 +42,7 @@ namespace interprocess { namespace ipcdetail { inline bool semaphore_open - (sem_t *&handle, create_enum_t type, const char *origname, + (sem_t *&handle, create_enum_t type, const char *origname, unsigned int count = 0, const permissions &perm = permissions()) { std::string name; @@ -103,7 +103,7 @@ inline bool semaphore_open inline void semaphore_close(sem_t *handle) { int ret = sem_close(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } @@ -138,7 +138,7 @@ inline void semaphore_init(sem_t *handle, unsigned int initialCount) inline void semaphore_destroy(sem_t *handle) { int ret = sem_destroy(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } diff --git a/boost/interprocess/sync/scoped_lock.hpp b/boost/interprocess/sync/scoped_lock.hpp index bfef63a30a..61fe93e5b3 100644 --- a/boost/interprocess/sync/scoped_lock.hpp +++ b/boost/interprocess/sync/scoped_lock.hpp @@ -89,7 +89,7 @@ class scoped_lock : mp_mutex(&m), m_locked(true) {} - //!Effects: m.try_lock(). + //!Effects: m.try_lock(). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.try_lock() executed within the constructor. //!Notes: The constructor will take ownership of the mutex if it can do @@ -101,7 +101,7 @@ class scoped_lock : mp_mutex(&m), m_locked(mp_mutex->try_lock()) {} - //!Effects: m.timed_lock(abs_time). + //!Effects: m.timed_lock(abs_time). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock(abs_time) executed within the constructor. //!Notes: The constructor will take ownership of the mutex if it can do @@ -128,7 +128,7 @@ class scoped_lock { mp_mutex = scop.release(); } //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the - //! referenced mutex. upgr.release() is called. + //! referenced mutex. upgr.release() is called. //!Postconditions: mutex() == the value upgr.mutex() had before the construction. //! upgr.mutex() == 0. owns() == upgr.owns() before the construction. //! upgr.owns() == false after the construction. @@ -155,12 +155,12 @@ class scoped_lock //!Effects: If upgr.owns() then calls try_unlock_upgradable_and_lock() on the //!referenced mutex: //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains - //! the value from upgr.release() and owns() is set to true. + //! the value from upgr.release() and owns() is set to true. //! b)if try_unlock_upgradable_and_lock() returns false then upgr is - //! unaffected and this scoped_lock construction as the same effects as - //! a default construction. + //! unaffected and this scoped_lock construction as the same effects as + //! a default construction. //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() - //! and owns() is set to false + //! and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex //! ownership from upgr immediately, while changing the lock type from a //! "read lock" to a "write lock". If the "read lock" isn't held in the @@ -186,12 +186,12 @@ class scoped_lock //!Effects: If upgr.owns() then calls timed_unlock_upgradable_and_lock(abs_time) //! on the referenced mutex: //! a)if timed_unlock_upgradable_and_lock(abs_time) returns true then mutex() - //! obtains the value from upgr.release() and owns() is set to true. + //! obtains the value from upgr.release() and owns() is set to true. //! b)if timed_unlock_upgradable_and_lock(abs_time) returns false then upgr //! is unaffected and this scoped_lock construction as the same effects //! as a default construction. //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() - //! and owns() is set to false + //! and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex ownership //! from upgr immediately, while changing the lock type from a "read lock" to a //! "write lock". If the "read lock" isn't held in the first place, the mutex @@ -214,14 +214,14 @@ class scoped_lock } //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the - //!referenced mutex. + //!referenced mutex. //! a)if try_unlock_sharable_and_lock() returns true then mutex() obtains - //! the value from shar.release() and owns() is set to true. + //! the value from shar.release() and owns() is set to true. //! b)if try_unlock_sharable_and_lock() returns false then shar is //! unaffected and this scoped_lock construction has the same - //! effects as a default construction. + //! effects as a default construction. //! c)Else shar.owns() is false. mutex() obtains the value from - //! shar.release() and owns() is set to false + //! shar.release() and owns() is set to false //!Notes: This construction will not block. It will try to obtain mutex //! ownership from shar immediately, while changing the lock type from a //! "read lock" to a "write lock". If the "read lock" isn't held in the @@ -253,13 +253,13 @@ class scoped_lock } //!Effects: If owns() before the call, then unlock() is called on mutex(). - //! *this gets the state of scop and scop gets set to a default constructed state. + //! *this gets the state of scop and scop gets set to a default constructed state. //!Notes: With a recursive mutex it is possible that both this and scop own //! the same mutex before the assignment. In this case, this will own the //! mutex after the assignment (and scop will not), but the mutex's lock //! count will be decremented by one. scoped_lock &operator=(BOOST_RV_REF(scoped_lock) scop) - { + { if(this->owns()) this->unlock(); m_locked = scop.owns(); @@ -281,7 +281,7 @@ class scoped_lock } //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() - //! exception. Calls try_lock() on the referenced mutex. + //! exception. Calls try_lock() on the referenced mutex. //!Postconditions: owns() == the value returned from mutex()->try_lock(). //!Notes: The scoped_lock changes from a state of not owning the mutex, to //! owning the mutex, but only if blocking was not required. If the @@ -348,8 +348,8 @@ class scoped_lock m_locked = false; return mut; } - - //!Effects: Swaps state with moved lock. + + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap( scoped_lock<mutex_type> &other) { @@ -359,7 +359,7 @@ class scoped_lock /// @cond private: - mutex_type *mp_mutex; + mutex_type *mp_mutex; bool m_locked; /// @endcond }; diff --git a/boost/interprocess/sync/sharable_lock.hpp b/boost/interprocess/sync/sharable_lock.hpp index c8b7c1d26e..9342e45a46 100644 --- a/boost/interprocess/sync/sharable_lock.hpp +++ b/boost/interprocess/sync/sharable_lock.hpp @@ -67,7 +67,7 @@ class sharable_lock {} //!Effects: m.lock_sharable(). - //!Postconditions: owns() == true and mutex() == &m. + //!Postconditions: owns() == true and mutex() == &m. //!Notes: The constructor will take sharable-ownership of the mutex. If //! another thread already owns the mutex with exclusive ownership //! (scoped_lock), this thread will block until the mutex is released. @@ -104,7 +104,7 @@ class sharable_lock : mp_mutex(&m), m_locked(false) { m_locked = mp_mutex->try_lock_sharable(); } - //!Effects: m.timed_lock_sharable(abs_time) + //!Effects: m.timed_lock_sharable(abs_time) //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock_sharable() executed within the constructor. //!Notes: The constructor will take sharable-ownership of the mutex if it @@ -132,7 +132,7 @@ class sharable_lock //! referenced mutex. //!Postconditions: mutex() == the value upgr.mutex() had before the construction. //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction. - //! upgr.owns() == false after the construction. + //! upgr.owns() == false after the construction. //!Notes: If upgr is locked, this constructor will lock this sharable_lock while //! unlocking upgr. Only a moved sharable_lock's will match this //! signature. An non-moved upgradable_lock can be moved with the expression: @@ -156,7 +156,7 @@ class sharable_lock //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the //! construction, scop.owns() == false. //!Notes: If scop is locked, this constructor will transfer the exclusive ownership - //! to a sharable-ownership of this sharable_lock. + //! to a sharable-ownership of this sharable_lock. //! Only a moved scoped_lock's will match this //! signature. An non-moved scoped_lock can be moved with the expression: //! "boost::move(lock);". @@ -184,12 +184,12 @@ class sharable_lock } //!Effects: If owns() before the call, then unlock_sharable() is called on mutex(). - //! *this gets the state of upgr and upgr gets set to a default constructed state. + //! *this gets the state of upgr and upgr gets set to a default constructed state. //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex //! before the assignment. In this case, this will own the mutex after the assignment //! (and upgr will not), but the mutex's lock count will be decremented by one. sharable_lock &operator=(BOOST_RV_REF(sharable_lock<mutex_type>) upgr) - { + { if(this->owns()) this->unlock(); m_locked = upgr.owns(); @@ -203,7 +203,7 @@ class sharable_lock //!Notes: The sharable_lock changes from a state of not owning the //! mutex, to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_sharable(); @@ -219,7 +219,7 @@ class sharable_lock //! mutex_type does not support try_lock_sharable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_sharable(); @@ -236,7 +236,7 @@ class sharable_lock //! timed_lock_sharable(), this function will fail at compile time if //! instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_sharable(abs_time); @@ -282,7 +282,7 @@ class sharable_lock return mut; } - //!Effects: Swaps state with moved lock. + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap(sharable_lock<mutex_type> &other) { diff --git a/boost/interprocess/sync/shm/named_condition.hpp b/boost/interprocess/sync/shm/named_condition.hpp index 0d67c25757..9d7cd77e11 100644 --- a/boost/interprocess/sync/shm/named_condition.hpp +++ b/boost/interprocess/sync/shm/named_condition.hpp @@ -28,7 +28,7 @@ #include <boost/interprocess/sync/shm/named_creation_functor.hpp> #include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/permissions.hpp> -#if defined BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES +#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #endif @@ -42,7 +42,7 @@ namespace interprocess { namespace ipcdetail { /// @cond -namespace ipcdetail{ class interprocess_tester; } +class interprocess_tester; /// @endcond //! A global condition variable that can be created by name. @@ -61,7 +61,7 @@ class shm_named_condition //!If the condition can't be created throws interprocess_exception shm_named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global condition with a name. + //!Opens or creates a global condition with a name. //!If the condition is created, this call is equivalent to //!shm_named_condition(create_only_t, ... ) //!If the condition is already created, this call is equivalent @@ -82,7 +82,7 @@ class shm_named_condition //!use remove(). ~shm_named_condition(); - //!If there is a thread waiting on *this, change that + //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect.*/ void notify_one(); @@ -90,8 +90,8 @@ class shm_named_condition //!If there are no waiting threads, notify_all() has no effect. void notify_all(); - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to //!this->notify_one() or this->notify_all(), and then reacquires the lock. template <typename L> void wait(L& lock); @@ -101,16 +101,16 @@ class shm_named_condition template <typename L, typename Pr> void wait(L& lock, Pr pred); - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, //!and then reacquires the lock. //!Returns: false if time abs_time is reached, otherwise true. template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); //! } return true; template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); @@ -147,6 +147,9 @@ class shm_named_condition void unlock() { l_.lock(); } }; + //If named mutex uses POSIX semaphores, then the shm based condition variable + //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t + //instance needed by pthread_mutex_cond_t #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) interprocess_mutex *mutex() const { return &static_cast<condition_holder*>(m_shmem.get_user_address())->mutex_; } @@ -156,7 +159,7 @@ class shm_named_condition { //shm_named_condition only works with named_mutex BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true)); - + //lock internal before unlocking external to avoid race with a notifier scoped_lock<interprocess_mutex> internal_lock(*this->mutex()); lock_inverter<Lock> inverted_lock(lock); @@ -173,18 +176,18 @@ class shm_named_condition { //shm_named_condition only works with named_mutex BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true)); - //lock internal before unlocking external to avoid race with a notifier - scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time); + //lock internal before unlocking external to avoid race with a notifier + scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time); if(!internal_lock) return false; - lock_inverter<Lock> inverted_lock(lock); - scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); + lock_inverter<Lock> inverted_lock(lock); + scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); - //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock<interprocess_mutex> internal_unlock; - internal_lock.swap(internal_unlock); - return this->condition()->timed_wait(internal_unlock, abs_time); + //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock<interprocess_mutex> internal_unlock; + internal_lock.swap(internal_unlock); + return this->condition()->timed_wait(internal_unlock, abs_time); } - #else + #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) template<class Lock> class lock_wrapper { @@ -210,7 +213,7 @@ class shm_named_condition private: Lock &l_; }; - #endif + #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) friend class boost::interprocess::ipcdetail::interprocess_tester; void dont_close_on_destruction(); diff --git a/boost/interprocess/sync/shm/named_creation_functor.hpp b/boost/interprocess/sync/shm/named_creation_functor.hpp index 11a1db1d6f..9d752c837a 100644 --- a/boost/interprocess/sync/shm/named_creation_functor.hpp +++ b/boost/interprocess/sync/shm/named_creation_functor.hpp @@ -38,7 +38,7 @@ class named_creation_functor { new(address)T(m_arg); } bool operator()(void *address, std::size_t, bool created) const - { + { switch(m_creation_type){ case DoOpen: return true; diff --git a/boost/interprocess/sync/shm/named_mutex.hpp b/boost/interprocess/sync/shm/named_mutex.hpp index a71eb4fe68..f32fa70044 100644 --- a/boost/interprocess/sync/shm/named_mutex.hpp +++ b/boost/interprocess/sync/shm/named_mutex.hpp @@ -37,7 +37,7 @@ namespace ipcdetail { class named_condition; -//!A mutex with a global name, so it can be found from different +//!A mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named mutex. class shm_named_mutex @@ -56,7 +56,7 @@ class shm_named_mutex //!Throws interprocess_exception on error. shm_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global mutex with a name. + //!Opens or creates a global mutex with a name. //!If the mutex is created, this call is equivalent to //!shm_named_mutex(create_only_t, ... ) //!If the mutex is already created, this call is equivalent @@ -85,7 +85,7 @@ class shm_named_mutex //!Throws interprocess_exception if a severe error is found void lock(); - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found bool try_lock(); diff --git a/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/boost/interprocess/sync/shm/named_recursive_mutex.hpp index 461c97eb32..7235571254 100644 --- a/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ b/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -51,7 +51,7 @@ class shm_named_recursive_mutex //!If the recursive_mutex can't be created throws interprocess_exception shm_named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global recursive_mutex with a name. + //!Opens or creates a global recursive_mutex with a name. //!If the recursive_mutex is created, this call is equivalent to //!shm_named_recursive_mutex(create_only_t, ... ) //!If the recursive_mutex is already created, this call is equivalent @@ -80,7 +80,7 @@ class shm_named_recursive_mutex //!Throws interprocess_exception if a severe error is found. void lock(); - //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex + //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex //!is already locked, returns true when success. //!Throws interprocess_exception if a severe error is found. bool try_lock(); diff --git a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp index 338fa98f7d..0975a6ed2b 100644 --- a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp +++ b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp @@ -38,7 +38,7 @@ namespace ipcdetail{ class interprocess_tester; } class named_condition; -//!A upgradable mutex with a global name, so it can be found from different +//!A upgradable mutex with a global name, so it can be found from different //!processes. This mutex can't be placed in shared memory, and //!each process should have it's own named upgradable mutex. class named_upgradable_mutex @@ -52,11 +52,11 @@ class named_upgradable_mutex /// @endcond public: - //!Creates a global upgradable mutex with a name. + //!Creates a global upgradable mutex with a name. //!If the upgradable mutex can't be created throws interprocess_exception named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!Opens or creates a global upgradable mutex with a name, and an initial count. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -95,13 +95,13 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire exclusive ownership of the mutex //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock(); @@ -115,21 +115,21 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. + //! has to wait, returns false. //!Throws: interprocess_exception on error. bool try_lock_sharable(); //!Effects: The calling thread tries to acquire sharable ownership of the mutex //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_sharable(); @@ -143,7 +143,7 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. + //! of the mutex this succeeds. //!Returns: If it can acquire upgradable ownership immediately returns true. //! If it has to wait, returns false. //!Throws: interprocess_exception on error. @@ -152,66 +152,66 @@ class named_upgradable_mutex //!Effects: The calling thread tries to acquire upgradable ownership of the mutex //! waiting if necessary until no other thread has exclusive or upgradable //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. //!Throws: interprocess_exception on error. bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable(); //Demotions - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. + //! upgradable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_upgradable(); - //!Precondition: The thread must have exclusive ownership of the mutex. + //!Precondition: The thread must have exclusive ownership of the mutex. //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_and_lock_sharable(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. + //! sharable ownership. This operation is non-blocking. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock_sharable(); //Promotions - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and acquires //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. + //! sharable ownership release it. //!Throws: An exception derived from interprocess_exception on error. void unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. + //! with sharable ownership, but it will maintain upgradable ownership. //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_upgradable_and_lock(); - //!Precondition: The thread must have upgradable ownership of the mutex. + //!Precondition: The thread must have upgradable ownership of the mutex. //!Effects: The thread atomically releases upgradable ownership and tries to acquire //! exclusive ownership, waiting if necessary until abs_time. This operation will //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); - //!Precondition: The thread must have sharable ownership of the mutex. + //!Precondition: The thread must have sharable ownership of the mutex. //!Effects: The thread atomically releases sharable ownership and tries to acquire //! exclusive ownership. This operation will fail if there are threads with sharable //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); diff --git a/boost/interprocess/sync/spin/condition.hpp b/boost/interprocess/sync/spin/condition.hpp index 5a37d9be2d..55dd79b406 100644 --- a/boost/interprocess/sync/spin/condition.hpp +++ b/boost/interprocess/sync/spin/condition.hpp @@ -110,7 +110,7 @@ inline spin_condition::spin_condition() } inline spin_condition::~spin_condition() -{ +{ //Trivial destructor } @@ -126,15 +126,15 @@ inline void spin_condition::notify_all() inline void spin_condition::notify(boost::uint32_t command) { - //This mutex guarantees that no other thread can enter to the + //This mutex guarantees that no other thread can enter to the //do_timed_wait method logic, so that thread count will be //constant until the function writes a NOTIFY_ALL command. - //It also guarantees that no other notification can be signaled + //It also guarantees that no other notification can be signaled //on this spin_condition before this one ends m_enter_mut.lock(); //Return if there are no waiters - if(!atomic_read32(&m_num_waiters)) { + if(!atomic_read32(&m_num_waiters)) { m_enter_mut.unlock(); return; } @@ -167,18 +167,18 @@ inline bool spin_condition::do_timed_wait template<class InterprocessMutex> inline bool spin_condition::do_timed_wait(bool tout_enabled, - const boost::posix_time::ptime &abs_time, + const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) { boost::posix_time::ptime now = microsec_clock::universal_time(); - + if(tout_enabled){ if(now >= abs_time) return false; } typedef boost::interprocess::scoped_lock<spin_mutex> InternalLock; - //The enter mutex guarantees that while executing a notification, - //no other thread can execute the do_timed_wait method. + //The enter mutex guarantees that while executing a notification, + //no other thread can execute the do_timed_wait method. { //--------------------------------------------------------------- InternalLock lock; @@ -205,8 +205,8 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, //By default, we suppose that no timeout has happened bool timed_out = false, unlock_enter_mut= false; - - //Loop until a notification indicates that the thread should + + //Loop until a notification indicates that the thread should //exit or timeout occurs while(1){ //The thread sleeps/spins until a spin_condition commands a notification @@ -229,8 +229,8 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, //There is an ongoing notification, we will try again later continue; } - //No notification in execution, since enter mutex is locked. - //We will execute time-out logic, so we will decrement count, + //No notification in execution, since enter mutex is locked. + //We will execute time-out logic, so we will decrement count, //release the enter mutex and return false. break; } @@ -253,7 +253,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, continue; } else if(result == NOTIFY_ONE){ - //If it was a NOTIFY_ONE command, only this thread should + //If it was a NOTIFY_ONE command, only this thread should //exit. This thread has atomically marked command as sleep before //so no other thread will exit. //Decrement wait count. @@ -262,8 +262,8 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, break; } else{ - //If it is a NOTIFY_ALL command, all threads should return - //from do_timed_wait function. Decrement wait count. + //If it is a NOTIFY_ALL command, all threads should return + //from do_timed_wait function. Decrement wait count. unlock_enter_mut = 1 == atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters)); //Check if this is the last thread of notify_all waiters //Only the last thread will release the mutex @@ -275,7 +275,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, } } - //Unlock the enter mutex if it is a single notification, if this is + //Unlock the enter mutex if it is a single notification, if this is //the last notified thread in a notify_all or a timeout has occurred if(unlock_enter_mut){ m_enter_mut.unlock(); diff --git a/boost/interprocess/sync/spin/mutex.hpp b/boost/interprocess/sync/spin/mutex.hpp index ef0b47d95a..926f7237c0 100644 --- a/boost/interprocess/sync/spin/mutex.hpp +++ b/boost/interprocess/sync/spin/mutex.hpp @@ -45,15 +45,15 @@ class spin_mutex volatile boost::uint32_t m_s; }; -inline spin_mutex::spin_mutex() - : m_s(0) +inline spin_mutex::spin_mutex() + : m_s(0) { //Note that this class is initialized to zero. //So zeroed memory can be interpreted as an //initialized mutex } -inline spin_mutex::~spin_mutex() +inline spin_mutex::~spin_mutex() { //Trivial destructor } @@ -73,7 +73,7 @@ inline void spin_mutex::lock(void) inline bool spin_mutex::try_lock(void) { - boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0); + boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0); return m_s == 1 && prev_s == 0; } diff --git a/boost/interprocess/sync/spin/recursive_mutex.hpp b/boost/interprocess/sync/spin/recursive_mutex.hpp index 05ad65eac0..a763f9c72d 100644 --- a/boost/interprocess/sync/spin/recursive_mutex.hpp +++ b/boost/interprocess/sync/spin/recursive_mutex.hpp @@ -68,7 +68,7 @@ class spin_recursive_mutex volatile boost::uint32_t m_s; }; -inline spin_recursive_mutex::spin_recursive_mutex() +inline spin_recursive_mutex::spin_recursive_mutex() : m_nLockCount(0), m_nOwner(ipcdetail::get_invalid_systemwide_thread_id()){} inline spin_recursive_mutex::~spin_recursive_mutex(){} @@ -83,7 +83,7 @@ inline void spin_recursive_mutex::lock() if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; } else{ @@ -103,7 +103,7 @@ inline bool spin_recursive_mutex::try_lock() if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; return true; } @@ -129,7 +129,7 @@ inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs if((unsigned int)(m_nLockCount+1) == 0){ //Overflow, throw an exception throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } + } ++m_nLockCount; return true; } diff --git a/boost/interprocess/sync/upgradable_lock.hpp b/boost/interprocess/sync/upgradable_lock.hpp index 93c2ed6bc4..fb86374ca1 100644 --- a/boost/interprocess/sync/upgradable_lock.hpp +++ b/boost/interprocess/sync/upgradable_lock.hpp @@ -85,7 +85,7 @@ class upgradable_lock : mp_mutex(&m), m_locked(true) {} - //!Effects: m.try_lock_upgradable(). + //!Effects: m.try_lock_upgradable(). //!Postconditions: mutex() == &m. owns() == the return value of the //! m.try_lock_upgradable() executed within the constructor. //!Notes: The constructor will take upgradable-ownership of the mutex @@ -97,7 +97,7 @@ class upgradable_lock : mp_mutex(&m), m_locked(false) { m_locked = mp_mutex->try_lock_upgradable(); } - //!Effects: m.timed_lock_upgradable(abs_time) + //!Effects: m.timed_lock_upgradable(abs_time) //!Postconditions: mutex() == &m. owns() == the return value of the //! m.timed_lock_upgradable() executed within the constructor. //!Notes: The constructor will take upgradable-ownership of the mutex if it @@ -123,7 +123,7 @@ class upgradable_lock : mp_mutex(0), m_locked(upgr.owns()) { mp_mutex = upgr.release(); } - //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). + //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). //!Postconditions: mutex() == the value scop.mutex() had before the construction. //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the //! construction, scop.owns() == false. @@ -146,12 +146,12 @@ class upgradable_lock } //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable() - //! on the referenced mutex. + //! on the referenced mutex. //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex() - //! obtains the value from shar.release() and owns() is set to true. + //! obtains the value from shar.release() and owns() is set to true. //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is //! unaffected and this upgradable_lock construction has the same - //! effects as a default construction. + //! effects as a default construction. //! c)Else shar.owns() is false. mutex() obtains the value from shar.release() //! and owns() is set to false. //!Notes: This construction will not block. It will try to obtain mutex @@ -207,7 +207,7 @@ class upgradable_lock //!Notes: The sharable_lock changes from a state of not owning the mutex, //! to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_upgradable(); @@ -223,7 +223,7 @@ class upgradable_lock //! mutex_type does not support try_lock_upgradable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_upgradable(); @@ -240,7 +240,7 @@ class upgradable_lock //! timed_lock_upgradable(abs_time), this function will fail at compile //! time if instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_upgradable(abs_time); @@ -286,7 +286,7 @@ class upgradable_lock return mut; } - //!Effects: Swaps state with moved lock. + //!Effects: Swaps state with moved lock. //!Throws: Nothing. void swap(upgradable_lock<mutex_type> &other) { diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp index 167b8730c3..9695c21044 100644 --- a/boost/interprocess/sync/windows/condition.hpp +++ b/boost/interprocess/sync/windows/condition.hpp @@ -20,133 +20,8 @@ #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; -// } -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// +#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> + namespace boost { namespace interprocess { @@ -156,6 +31,7 @@ class windows_condition { windows_condition(const windows_condition &); windows_condition &operator=(const windows_condition &); + public: windows_condition(); ~windows_condition(); @@ -217,162 +93,71 @@ class windows_condition 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; + struct condition_data + { + typedef boost::int32_t integer_type; + typedef windows_semaphore semaphore_type; + typedef windows_mutex mutex_type; + + condition_data() + : 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() + {} + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + 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; + } m_condition_data; + + typedef condition_algorithm_8a<condition_data> algorithm_type; }; 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() + : m_condition_data() {} inline windows_condition::~windows_condition() {} inline void windows_condition::notify_one() -{ this->do_signal(false); } +{ algorithm_type::signal(m_condition_data, 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); -} +{ algorithm_type::signal(m_condition_data, true); } template<class InterprocessMutex> inline void windows_condition::do_wait(InterprocessMutex &mut) -{ this->do_timed_wait(false, boost::posix_time::ptime(), mut); } +{ algorithm_type::wait(m_condition_data, 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; -} +{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } } //namespace ipcdetail } //namespace interprocess diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp index 5eca522339..477acd396a 100644 --- a/boost/interprocess/sync/windows/mutex.hpp +++ b/boost/interprocess/sync/windows/mutex.hpp @@ -19,8 +19,9 @@ #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/detail/windows_intermodule_singleton.hpp> #include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> #include <boost/interprocess/exceptions.hpp> @@ -47,85 +48,61 @@ class windows_mutex const sync_id id_; }; -inline windows_mutex::windows_mutex() - : id_() +inline windows_mutex::windows_mutex() + : id_(this) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); //Create mutex with the initial count bool open_or_created; - handles.obtain_mutex(this->id_, &open_or_created); + (void)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() +inline windows_mutex::~windows_mutex() { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); handles.destroy_handle(this->id_); } inline void windows_mutex::lock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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); - } + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + mut.lock(); } inline bool windows_mutex::try_lock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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; + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.try_lock(); } 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(); + windows_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; + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.timed_lock(abs_time); } inline void windows_mutex::unlock(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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); + winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); + return mut.unlock(); } } //namespace ipcdetail { diff --git a/boost/interprocess/sync/windows/named_condition.hpp b/boost/interprocess/sync/windows/named_condition.hpp new file mode 100644 index 0000000000..403e826178 --- /dev/null +++ b/boost/interprocess/sync/windows/named_condition.hpp @@ -0,0 +1,334 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/interprocess_tester.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/named_sync.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> +#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_condition +{ + /// @cond + + //Non-copyable + windows_named_condition(); + windows_named_condition(const windows_named_condition &); + windows_named_condition &operator=(const windows_named_condition &); + /// @endcond + + public: + windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions()); + + windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); + + windows_named_condition(open_only_t, const char *name); + + ~windows_named_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template <typename L> + void wait(L& lock); + + //!The same as: + //!while (!pred()) wait(lock) + template <typename L, typename Pr> + void wait(L& lock, Pr pred); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template <typename L> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template <typename L, typename Pr> + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); + + static bool remove(const char *name); + + /// @cond + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + + template <class InterprocessMutex> + void do_wait(InterprocessMutex& lock); + + template <class InterprocessMutex> + bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock); + + struct condition_data + { + typedef boost::int32_t integer_type; + typedef winapi_semaphore_wrapper semaphore_type; + typedef winapi_mutex_wrapper mutex_type; + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + integer_type m_nwaiters_blocked; + integer_type m_nwaiters_gone; + integer_type m_nwaiters_to_unblock; + winapi_semaphore_wrapper m_sem_block_queue; + winapi_semaphore_wrapper m_sem_block_lock; + winapi_mutex_wrapper m_mtx_unblock_lock; + } m_condition_data; + + typedef condition_algorithm_8a<condition_data> algorithm_type; + + class named_cond_callbacks : public windows_named_sync_interface + { + typedef __int64 sem_count_t; + mutable sem_count_t sem_counts [2]; + + public: + named_cond_callbacks(condition_data &cond_data) + : m_condition_data(cond_data) + {} + + virtual std::size_t get_data_size() const + { return sizeof(sem_counts); } + + virtual const void *buffer_with_final_data_to_file() + { + sem_counts[0] = m_condition_data.m_sem_block_queue.value(); + sem_counts[1] = m_condition_data.m_sem_block_lock.value(); + return &sem_counts; + } + + virtual const void *buffer_with_init_data_to_file() + { + sem_counts[0] = 0; + sem_counts[1] = 1; + return &sem_counts; + } + + virtual void *buffer_to_store_init_data_from_file() + { return &sem_counts; } + + virtual bool open(create_enum_t, const char *id_name) + { + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + + //Now open semaphores and mutex. + //Use local variables + swap to guarantee consistent + //initialization and cleanup in case any opening fails + permissions perm; + perm.set_unrestricted(); + std::string aux_str = "Global\\bipc.cond."; + aux_str += id_name; + std::size_t pos = aux_str.size(); + + //sem_block_queue + aux_str += "_bq"; + winapi_semaphore_wrapper sem_block_queue; + bool created; + if(!sem_block_queue.open_or_create + (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //sem_block_lock + aux_str += "_bl"; + winapi_semaphore_wrapper sem_block_lock; + if(!sem_block_lock.open_or_create + (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //mtx_unblock_lock + aux_str += "_ul"; + winapi_mutex_wrapper mtx_unblock_lock; + if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) + return false; + + //All ok, commit data + m_condition_data.m_sem_block_queue.swap(sem_block_queue); + m_condition_data.m_sem_block_lock.swap(sem_block_lock); + m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); + return true; + } + + virtual void close() + { + m_condition_data.m_sem_block_queue.close(); + m_condition_data.m_sem_block_lock.close(); + m_condition_data.m_mtx_unblock_lock.close(); + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + } + + virtual ~named_cond_callbacks() + {} + + private: + condition_data &m_condition_data; + }; + + windows_named_sync m_named_sync; + /// @endcond +}; + +inline windows_named_condition::~windows_named_condition() +{ + named_cond_callbacks callbacks(m_condition_data); + m_named_sync.close(callbacks); +} + +inline void windows_named_condition::dont_close_on_destruction() +{} + +inline windows_named_condition::windows_named_condition + (create_only_t, const char *name, const permissions &perm) + : m_condition_data() +{ + named_cond_callbacks callbacks(m_condition_data); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_condition::windows_named_condition + (open_or_create_t, const char *name, const permissions &perm) + : m_condition_data() +{ + named_cond_callbacks callbacks(m_condition_data); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_condition::windows_named_condition(open_only_t, const char *name) + : m_condition_data() +{ + named_cond_callbacks callbacks(m_condition_data); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void windows_named_condition::notify_one() +{ algorithm_type::signal(m_condition_data, false); } + +inline void windows_named_condition::notify_all() +{ algorithm_type::signal(m_condition_data, true); } + +template<class InterprocessMutex> +inline void windows_named_condition::do_wait(InterprocessMutex &mut) +{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); } + +template<class InterprocessMutex> +inline bool windows_named_condition::do_timed_wait + (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) +{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } + +template <typename L> +inline void windows_named_condition::wait(L& lock) +{ + if (!lock) + throw lock_exception(); + this->do_wait(*lock.mutex()); +} + +template <typename L, typename Pr> +inline void windows_named_condition::wait(L& lock, Pr pred) +{ + if (!lock) + throw lock_exception(); + while (!pred()) + this->do_wait(*lock.mutex()); +} + +template <typename L> +inline bool windows_named_condition::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> +inline bool windows_named_condition::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; +} + +inline bool windows_named_condition::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP diff --git a/boost/interprocess/sync/windows/named_mutex.hpp b/boost/interprocess/sync/windows/named_mutex.hpp new file mode 100644 index 0000000000..8ea6b3e1e4 --- /dev/null +++ b/boost/interprocess/sync/windows/named_mutex.hpp @@ -0,0 +1,175 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/interprocess_tester.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/sync/windows/named_sync.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class windows_named_mutex +{ + /// @cond + + //Non-copyable + windows_named_mutex(); + windows_named_mutex(const windows_named_mutex &); + windows_named_mutex &operator=(const windows_named_mutex &); + /// @endcond + + public: + windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + windows_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + windows_named_mutex(open_only_t, const char *name); + + ~windows_named_mutex(); + + void unlock(); + void lock(); + bool try_lock(); + bool timed_lock(const boost::posix_time::ptime &abs_time); + + static bool remove(const char *name); + + /// @cond + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_mutex_wrapper m_mtx_wrapper; + windows_named_sync m_named_sync; + + class named_mut_callbacks : public windows_named_sync_interface + { + public: + named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper) + : m_mtx_wrapper(mtx_wrapper) + {} + + virtual std::size_t get_data_size() const + { return 0u; } + + virtual const void *buffer_with_init_data_to_file() + { return 0; } + + virtual const void *buffer_with_final_data_to_file() + { return 0; } + + virtual void *buffer_to_store_init_data_from_file() + { return 0; } + + virtual bool open(create_enum_t, const char *id_name) + { + std::string aux_str = "Global\\bipc.mut."; + aux_str += id_name; + // + permissions mut_perm; + mut_perm.set_unrestricted(); + return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); + } + + virtual void close() + { + m_mtx_wrapper.close(); + } + + virtual ~named_mut_callbacks() + {} + + private: + winapi_mutex_wrapper& m_mtx_wrapper; + }; + /// @endcond +}; + +inline windows_named_mutex::~windows_named_mutex() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.close(callbacks); +} + +inline void windows_named_mutex::dont_close_on_destruction() +{} + +inline windows_named_mutex::windows_named_mutex + (create_only_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex(open_only_t, const char *name) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void windows_named_mutex::unlock() +{ + m_mtx_wrapper.unlock(); +} + +inline void windows_named_mutex::lock() +{ + m_mtx_wrapper.lock(); +} + +inline bool windows_named_mutex::try_lock() +{ + return m_mtx_wrapper.try_lock(); +} + +inline bool windows_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + return m_mtx_wrapper.timed_lock(abs_time); +} + +inline bool windows_named_mutex::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
\ No newline at end of file diff --git a/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/boost/interprocess/sync/windows/named_recursive_mutex.hpp new file mode 100644 index 0000000000..cb2ef79ac1 --- /dev/null +++ b/boost/interprocess/sync/windows/named_recursive_mutex.hpp @@ -0,0 +1,58 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_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/named_mutex.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + +class windows_named_recursive_mutex + //Windows mutexes based on CreateMutex are already recursive... + : public windows_named_mutex +{ + /// @cond + + //Non-copyable + windows_named_recursive_mutex(); + windows_named_recursive_mutex(const windows_named_mutex &); + windows_named_recursive_mutex &operator=(const windows_named_mutex &); + /// @endcond + + public: + windows_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()) + : windows_named_mutex(create_only_t(), name, perm) + {} + + windows_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()) + : windows_named_mutex(open_or_create_t(), name, perm) + {} + + windows_named_recursive_mutex(open_only_t, const char *name) + : windows_named_mutex(open_only_t(), name) + {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP diff --git a/boost/interprocess/sync/windows/named_semaphore.hpp b/boost/interprocess/sync/windows/named_semaphore.hpp new file mode 100644 index 0000000000..8f48d4df96 --- /dev/null +++ b/boost/interprocess/sync/windows/named_semaphore.hpp @@ -0,0 +1,178 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/interprocess_tester.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/sync/windows/named_sync.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class windows_named_semaphore +{ + /// @cond + + //Non-copyable + windows_named_semaphore(); + windows_named_semaphore(const windows_named_semaphore &); + windows_named_semaphore &operator=(const windows_named_semaphore &); + /// @endcond + + public: + windows_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_only_t, const char *name); + + ~windows_named_semaphore(); + + void post(); + void wait(); + bool try_wait(); + bool timed_wait(const boost::posix_time::ptime &abs_time); + + static bool remove(const char *name); + + /// @cond + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_semaphore_wrapper m_sem_wrapper; + windows_named_sync m_named_sync; + + class named_sem_callbacks : public windows_named_sync_interface + { + public: + typedef __int64 sem_count_t; + named_sem_callbacks(winapi_semaphore_wrapper &sem_wrapper, sem_count_t sem_cnt) + : m_sem_wrapper(sem_wrapper), m_sem_count(sem_cnt) + {} + + virtual std::size_t get_data_size() const + { return sizeof(sem_count_t); } + + virtual const void *buffer_with_final_data_to_file() + { return &m_sem_count; } + + virtual const void *buffer_with_init_data_to_file() + { return &m_sem_count; } + + virtual void *buffer_to_store_init_data_from_file() + { return &m_sem_count; } + + virtual bool open(create_enum_t, const char *id_name) + { + std::string aux_str = "Global\\bipc.sem."; + aux_str += id_name; + // + permissions sem_perm; + sem_perm.set_unrestricted(); + bool created; + return m_sem_wrapper.open_or_create + ( aux_str.c_str(), static_cast<long>(m_sem_count) + , winapi_semaphore_wrapper::MaxCount, sem_perm, created); + } + + virtual void close() + { + m_sem_wrapper.close(); + } + + virtual ~named_sem_callbacks() + {} + + private: + sem_count_t m_sem_count; + winapi_semaphore_wrapper& m_sem_wrapper; + }; + + /// @endcond +}; + +inline windows_named_semaphore::~windows_named_semaphore() +{ + named_sem_callbacks callbacks(m_sem_wrapper, m_sem_wrapper.value()); + m_named_sync.close(callbacks); +} + +inline void windows_named_semaphore::dont_close_on_destruction() +{} + +inline windows_named_semaphore::windows_named_semaphore + (create_only_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore + (open_or_create_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore(open_only_t, const char *name) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, 0); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void windows_named_semaphore::post() +{ + m_sem_wrapper.post(); +} + +inline void windows_named_semaphore::wait() +{ + m_sem_wrapper.wait(); +} + +inline bool windows_named_semaphore::try_wait() +{ + return m_sem_wrapper.try_wait(); +} + +inline bool windows_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ + return m_sem_wrapper.timed_wait(abs_time); +} + +inline bool windows_named_semaphore::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP diff --git a/boost/interprocess/sync/windows/named_sync.hpp b/boost/interprocess/sync/windows/named_sync.hpp new file mode 100644 index 0000000000..41f299f8eb --- /dev/null +++ b/boost/interprocess/sync/windows/named_sync.hpp @@ -0,0 +1,215 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_SYNC_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <string> +#include <cassert> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_sync_interface +{ + public: + virtual std::size_t get_data_size() const = 0; + virtual const void *buffer_with_final_data_to_file() = 0; + virtual const void *buffer_with_init_data_to_file() = 0; + virtual void *buffer_to_store_init_data_from_file() = 0; + virtual bool open(create_enum_t creation_type, const char *id_name) = 0; + virtual void close() = 0; + virtual ~windows_named_sync_interface() = 0; +}; + +inline windows_named_sync_interface::~windows_named_sync_interface() +{} + +class windows_named_sync +{ + /// @cond + + //Non-copyable + windows_named_sync(const windows_named_sync &); + windows_named_sync &operator=(const windows_named_sync &); + /// @endcond + + public: + windows_named_sync(); + void open_or_create(create_enum_t creation_type, const char *name, const permissions &perm, windows_named_sync_interface &sync_interface); + void close(windows_named_sync_interface &sync_interface); + + static bool remove(const char *name); + + /// @cond + private: + void *m_file_hnd; + + /// @endcond +}; + +inline windows_named_sync::windows_named_sync() + : m_file_hnd(winapi::invalid_handle_value) +{} + +inline void windows_named_sync::close(windows_named_sync_interface &sync_interface) +{ + const std::size_t buflen = sync_interface.get_data_size(); + const std::size_t sizeof_file_info = sizeof(sync_id::internal_type) + buflen; + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){ + if(winapi::set_file_pointer_ex(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ + const void *buf = sync_interface.buffer_with_final_data_to_file(); + + unsigned long written_or_read = 0; + if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){ + //... + } + } + } + sync_interface.close(); + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } +} + +inline void windows_named_sync::open_or_create + ( create_enum_t creation_type + , const char *name + , const permissions &perm + , windows_named_sync_interface &sync_interface) +{ + std::string aux_str(name); + m_file_hnd = winapi::invalid_handle_value; + //Use a file to emulate POSIX lifetime semantics. After this logic + //we'll obtain the ID of the native handle to open in aux_str + { + create_tmp_and_clean_old_and_get_filename(name, aux_str); + //Create a file with required permissions. + m_file_hnd = winapi::create_file + ( aux_str.c_str() + , winapi::generic_read | winapi::generic_write + , creation_type == DoOpen ? winapi::open_existing : + (creation_type == DoCreate ? winapi::create_new : winapi::open_always) + , 0 + , (winapi::interprocess_security_attributes*)perm.get_permissions()); + + //Obtain OS error in case something has failed + error_info err; + bool success = false; + if(m_file_hnd != winapi::invalid_handle_value){ + //Now lock the file + const std::size_t buflen = sync_interface.get_data_size(); + typedef __int64 unique_id_type; + const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen; + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){ + __int64 filesize = 0; + //Obtain the unique id to open the native semaphore. + //If file size was created + if(winapi::get_file_size(m_file_hnd, filesize)){ + unsigned long written_or_read = 0; + unique_id_type unique_id_val; + if(static_cast<std::size_t>(filesize) != sizeof_file_info){ + winapi::set_end_of_file(m_file_hnd); + winapi::query_performance_counter(&unique_id_val); + const void *buf = sync_interface.buffer_with_init_data_to_file(); + //Write unique ID in file. This ID will be used to calculate the semaphore name + if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + winapi::get_file_size(m_file_hnd, filesize); + assert(std::size_t(filesize) == sizeof_file_info); + } + else{ + void *buf = sync_interface.buffer_to_store_init_data_from_file(); + if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + } + if(success){ + //Now create a global semaphore name based on the unique id + char unique_id_name[sizeof(unique_id_val)*2+1]; + std::size_t name_suffix_length = sizeof(unique_id_name); + bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length); + success = sync_interface.open(creation_type, unique_id_name); + } + } + + //Obtain OS error in case something has failed + err = system_error_code(); + + //If this fails we have no possible rollback so don't check the return + if(!winapi::unlock_file_ex(m_file_hnd, 0, sizeof_file_info, 0, &overlapped)){ + err = system_error_code(); + } + } + else{ + //Obtain OS error in case something has failed + err = system_error_code(); + } + } + else{ + err = system_error_code(); + } + + if(!success){ + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } + //Throw as something went wrong + throw interprocess_exception(err); + } + } +} + +inline bool windows_named_sync::remove(const char *name) +{ + try{ + //Make sure a temporary path is created for shared memory + std::string semfile; + ipcdetail::tmp_filename(name, semfile); + return winapi::unlink_file(semfile.c_str()); + } + catch(...){ + return false; + } +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp index d5835ceec7..af336df48a 100644 --- a/boost/interprocess/sync/windows/semaphore.hpp +++ b/boost/interprocess/sync/windows/semaphore.hpp @@ -19,8 +19,9 @@ #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/detail/windows_intermodule_singleton.hpp> #include <boost/interprocess/sync/windows/sync_utils.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> #include <boost/interprocess/exceptions.hpp> @@ -46,11 +47,11 @@ class windows_semaphore const sync_id id_; }; -inline windows_semaphore::windows_semaphore(unsigned int initialCount) - : id_() +inline windows_semaphore::windows_semaphore(unsigned int initialCount) + : id_(this) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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); @@ -60,72 +61,46 @@ inline windows_semaphore::windows_semaphore(unsigned int initialCount) (void)open_or_created; } -inline windows_semaphore::~windows_semaphore() +inline windows_semaphore::~windows_semaphore() { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_intermodule_singleton<sync_handles>::get(); handles.destroy_handle(this->id_); } inline void windows_semaphore::wait(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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); - } + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + sem.wait(); } inline bool windows_semaphore::try_wait(void) { sync_handles &handles = - intermodule_singleton<sync_handles>::get(); + windows_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; + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + return sem.try_wait(); } 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(); + windows_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; + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + return sem.timed_wait(abs_time); } 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); + windows_intermodule_singleton<sync_handles>::get(); + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0)); + sem.post(release_count); } } //namespace ipcdetail { diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp index 89c4aeda0b..0281da1266 100644 --- a/boost/interprocess/sync/windows/sync_utils.hpp +++ b/boost/interprocess/sync/windows/sync_utils.hpp @@ -21,7 +21,10 @@ #include <boost/interprocess/sync/spin/mutex.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> +#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp> #include <boost/unordered/unordered_map.hpp> +#include <boost/container/map.hpp> #include <cstddef> namespace boost { @@ -32,6 +35,7 @@ inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *ou { const std::size_t need_mem = mem_length*2+1; if(out_length < need_mem){ + out_length = need_mem; return false; } @@ -49,40 +53,57 @@ inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *ou return true; } -struct sync_id +class sync_id { - sync_id() - { winapi::query_performance_counter(&rand); } + public: + typedef __int64 internal_type; + sync_id(const void *map_addr) + : map_addr_(map_addr) + { winapi::query_performance_counter(&rand_); } + + explicit sync_id(internal_type val, const void *map_addr) + : map_addr_(map_addr) + { rand_ = val; } + + const internal_type &internal_pod() const + { return rand_; } - __int64 rand; + internal_type &internal_pod() + { return rand_; } + + const void *map_addr() const + { return map_addr_; } friend std::size_t hash_value(const sync_id &m) - { return boost::hash_value(m.rand); } + { 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 + { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; } -#if defined(BOOST_NO_LONG_LONG) + private: + internal_type rand_; + const void * const map_addr_; +}; -#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; + struct address_less + { + bool operator()(sync_id const * const l, sync_id const * const r) const + { return l->map_addr() < r->map_addr(); } + }; + + typedef boost::unordered_map<sync_id, void*> umap_type; + typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> 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"; @@ -92,13 +113,12 @@ class sync_handles ++i; } while(n[i]); std::size_t len = sizeof(NameBuf) - LengthOfGlobal; - bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len); + bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len); } - void erase_and_throw_if_error(void *hnd_val, const sync_id &id) + void throw_if_error(void *hnd_val) { if(!hnd_val){ - map_.erase(id); error_info err(winapi::get_last_error()); throw interprocess_exception(err); } @@ -108,27 +128,36 @@ class sync_handles { 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; + permissions unrestricted_security; + unrestricted_security.set_unrestricted(); + winapi_semaphore_wrapper sem_wrapper; + bool created; + sem_wrapper.open_or_create + (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created); + throw_if_error(sem_wrapper.handle()); + return sem_wrapper.release(); } 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; + permissions unrestricted_security; + unrestricted_security.set_unrestricted(); + winapi_mutex_wrapper mtx_wrapper; + mtx_wrapper.open_or_create(name, unrestricted_security); + throw_if_error(mtx_wrapper.handle()); + return mtx_wrapper.release(); } public: void *obtain_mutex(const sync_id &id, bool *popen_created = 0) { + umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); - void *&hnd_val = map_[id]; + umap_type::iterator it = umap_.insert(v).first; + map_[&it->first] = it; + void *&hnd_val = it->second; if(!hnd_val){ hnd_val = open_or_create_mutex(id); if(popen_created) *popen_created = true; @@ -138,8 +167,11 @@ class sync_handles void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0) { + umap_type::value_type v(id, (void*)0); scoped_lock<spin_mutex> lock(mtx_); - void *&hnd_val = map_[id]; + umap_type::iterator it = umap_.insert(v).first; + map_[&it->first] = it; + void *&hnd_val = it->second; if(!hnd_val){ hnd_val = open_or_create_semaphore(id, initial_count); if(popen_created) *popen_created = true; @@ -150,16 +182,35 @@ class sync_handles void destroy_handle(const sync_id &id) { scoped_lock<spin_mutex> lock(mtx_); - map_type::iterator it = map_.find(id); - if(it != map_.end()){ + umap_type::iterator it = umap_.find(id); + umap_type::iterator itend = umap_.end(); + + if(it != itend){ winapi::close_handle(it->second); - map_.erase(it); + const map_type::key_type &k = &it->first; + map_.erase(k); + umap_.erase(it); + } + } + + void destroy_syncs_in_range(const void *addr, std::size_t size) + { + sync_id low_id(addr); + sync_id hig_id(static_cast<const char*>(addr)+size); + scoped_lock<spin_mutex> lock(mtx_); + map_type::iterator itlow(map_.lower_bound(&low_id)), + ithig(map_.lower_bound(&hig_id)); + while(itlow != ithig){ + void *hnd = umap_[*itlow->first]; + winapi::close_handle(hnd); + umap_.erase(*itlow->first); + itlow = map_.erase(itlow); } } private: - winapi::interprocess_all_access_security unrestricted_security; spin_mutex mtx_; + umap_type umap_; map_type map_; }; diff --git a/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp new file mode 100644 index 0000000000..0be96011cf --- /dev/null +++ b/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp @@ -0,0 +1,163 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINAPI_MUTEX_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_mutex_functions +{ + /// @cond + + //Non-copyable + winapi_mutex_functions(const winapi_mutex_functions &); + winapi_mutex_functions &operator=(const winapi_mutex_functions &); + /// @endcond + + public: + winapi_mutex_functions(void *mtx_hnd) + : m_mtx_hnd(mtx_hnd) + {} + + void unlock() + { + winapi::release_mutex(m_mtx_hnd); + } + + void lock() + { + if(winapi::wait_for_single_object(m_mtx_hnd, winapi::infinite_time) != winapi::wait_object_0){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + bool try_lock() + { + unsigned long ret = winapi::wait_for_single_object(m_mtx_hnd, 0); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + bool timed_lock(const boost::posix_time::ptime &abs_time) + { + if(abs_time == boost::posix_time::pos_infin){ + this->lock(); + return true; + } + + unsigned long ret = winapi::wait_for_single_object + (m_mtx_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds()); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + /// @cond + protected: + void *m_mtx_hnd; + /// @endcond +}; + +//Swappable mutex wrapper +class winapi_mutex_wrapper + : public winapi_mutex_functions +{ + /// @cond + + //Non-copyable + winapi_mutex_wrapper(const winapi_mutex_wrapper &); + winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &); + /// @endcond + + public: + winapi_mutex_wrapper(void *mtx_hnd = winapi::invalid_handle_value) + : winapi_mutex_functions(mtx_hnd) + {} + + ~winapi_mutex_wrapper() + { this->close(); } + + void *release() + { + void *hnd = m_mtx_hnd; + m_mtx_hnd = winapi::invalid_handle_value; + return hnd; + } + + void *handle() const + { return m_mtx_hnd; } + + bool open_or_create(const char *name, const permissions &perm) + { + if(m_mtx_hnd == winapi::invalid_handle_value){ + m_mtx_hnd = winapi::open_or_create_mutex + ( name + , false + , (winapi::interprocess_security_attributes*)perm.get_permissions() + ); + return m_mtx_hnd != winapi::invalid_handle_value; + } + else{ + return false; + } + } + + void close() + { + if(m_mtx_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_mtx_hnd); + m_mtx_hnd = winapi::invalid_handle_value; + } + } + + void swap(winapi_mutex_wrapper &other) + { void *tmp = m_mtx_hnd; m_mtx_hnd = other.m_mtx_hnd; other.m_mtx_hnd = tmp; } +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP diff --git a/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp new file mode 100644 index 0000000000..2dd7845627 --- /dev/null +++ b/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp @@ -0,0 +1,198 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINAPI_SEMAPHORE_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_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/creation_tags.hpp> +#include <boost/interprocess/permissions.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <boost/interprocess/errors.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <limits> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_semaphore_functions +{ + /// @cond + + //Non-copyable + winapi_semaphore_functions(const winapi_semaphore_functions &); + winapi_semaphore_functions &operator=(const winapi_semaphore_functions &); + /// @endcond + + public: + winapi_semaphore_functions(void *hnd) + : m_sem_hnd(hnd) + {} + + void post(long count = 1) + { + long prev_count; + winapi::release_semaphore(m_sem_hnd, count, &prev_count); + } + + void wait() + { + if(winapi::wait_for_single_object(m_sem_hnd, winapi::infinite_time) != winapi::wait_object_0){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + bool try_wait() + { + unsigned long ret = winapi::wait_for_single_object(m_sem_hnd, 0); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + bool timed_wait(const boost::posix_time::ptime &abs_time) + { + if(abs_time == boost::posix_time::pos_infin){ + this->wait(); + return true; + } + + unsigned long ret = winapi::wait_for_single_object + (m_sem_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds()); + if(ret == winapi::wait_object_0){ + return true; + } + else if(ret == winapi::wait_timeout){ + return false; + } + else{ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + + long value() const + { + long count, limit; + if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + return 0; + return count; + } + + long limit() const + { + long count, limit; + if(!winapi::get_semaphore_info(m_sem_hnd, count, limit)) + return 0; + return limit; + } + + /// @cond + protected: + void *m_sem_hnd; + /// @endcond +}; + + +//Swappable semaphore wrapper +class winapi_semaphore_wrapper + : public winapi_semaphore_functions +{ + winapi_semaphore_wrapper(const winapi_semaphore_wrapper &); + winapi_semaphore_wrapper &operator=(const winapi_semaphore_wrapper &); + + public: + + //Long is 32 bits in windows + static const long MaxCount = long(0x7FFFFFFF); + + winapi_semaphore_wrapper(void *hnd = winapi::invalid_handle_value) + : winapi_semaphore_functions(hnd) + {} + + ~winapi_semaphore_wrapper() + { this->close(); } + + void *release() + { + void *hnd = m_sem_hnd; + m_sem_hnd = winapi::invalid_handle_value; + return hnd; + } + + void *handle() const + { return m_sem_hnd; } + + bool open_or_create( const char *name + , long sem_count + , long max_count + , const permissions &perm + , bool &created) + { + if(m_sem_hnd == winapi::invalid_handle_value){ + m_sem_hnd = winapi::open_or_create_semaphore + ( name + , sem_count + , max_count + , (winapi::interprocess_security_attributes*)perm.get_permissions() + ); + created = winapi::get_last_error() != winapi::error_already_exists; + return m_sem_hnd != winapi::invalid_handle_value; + } + else{ + return false; + } + } + + bool open_semaphore(const char *name) + { + if(m_sem_hnd == winapi::invalid_handle_value){ + m_sem_hnd = winapi::open_semaphore(name); + return m_sem_hnd != winapi::invalid_handle_value; + } + else{ + return false; + } + } + + void close() + { + if(m_sem_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_sem_hnd); + m_sem_hnd = winapi::invalid_handle_value; + } + } + + void swap(winapi_semaphore_wrapper &other) + { void *tmp = m_sem_hnd; m_sem_hnd = other.m_sem_hnd; other.m_sem_hnd = tmp; } +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP diff --git a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp index 3dffdcc2ed..485b1ac101 100644 --- a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp +++ b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp @@ -62,20 +62,20 @@ class xsi_named_mutex xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666) { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, path, id, perm); } - //!Moves the ownership of "moved"'s named mutex to *this. - //!After the call, "moved" does not represent any named mutex + //!Moves the ownership of "moved"'s named mutex to *this. + //!After the call, "moved" does not represent any named mutex //!Does not throw xsi_named_mutex(BOOST_RV_REF(xsi_named_mutex) moved) { this->swap(moved); } //!Moves the ownership of "moved"'s named mutex to *this. - //!After the call, "moved" does not represent any named mutex. + //!After the call, "moved" does not represent any named mutex. //!Does not throw xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved) - { + { xsi_named_mutex tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_named_mutex. Does not throw @@ -126,11 +126,11 @@ class xsi_named_mutex /// @cond -inline xsi_named_mutex::xsi_named_mutex() +inline xsi_named_mutex::xsi_named_mutex() : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path() {} -inline xsi_named_mutex::~xsi_named_mutex() +inline xsi_named_mutex::~xsi_named_mutex() { this->priv_close(); } inline const char *xsi_named_mutex::get_path() const @@ -142,7 +142,7 @@ inline void xsi_named_mutex::swap(xsi_named_mutex &other) std::swap(m_id, other.m_id); std::swap(m_semid, other.m_semid); std::swap(m_perm, other.m_perm); - m_path.swap(other.m_path); + m_path.swap(other.m_path); } inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const |