stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
+81
@@ -0,0 +1,81 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-2013. 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_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
|
||||
#define BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class MutexType>
|
||||
bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Same as lock()
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
m.lock();
|
||||
return true;
|
||||
}
|
||||
//Always try to lock to achieve POSIX guarantees:
|
||||
// "Under no circumstance shall the function fail with a timeout if the mutex
|
||||
// can be locked immediately. The validity of the abs_timeout parameter need not
|
||||
// be checked if the mutex can be locked immediately."
|
||||
else if(m.try_lock()){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
spin_wait swait;
|
||||
while(microsec_clock::universal_time() < abs_time){
|
||||
if(m.try_lock()){
|
||||
return true;
|
||||
}
|
||||
swait.yield();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<class MutexType>
|
||||
void try_based_lock(MutexType &m)
|
||||
{
|
||||
if(!m.try_lock()){
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(m.try_lock()){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
swait.yield();
|
||||
}
|
||||
}
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
|
||||
+395
@@ -0,0 +1,395 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_CONDITION_ALGORITHM_8A_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.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()
|
||||
// };
|
||||
//
|
||||
// Must be initialized as following
|
||||
//
|
||||
// get_nwaiters_blocked() == 0
|
||||
// get_nwaiters_gone() == 0
|
||||
// get_nwaiters_to_unblock() == 0
|
||||
// get_sem_block_queue() == initial count 0
|
||||
// get_sem_block_lock() == initial count 1
|
||||
// get_mtx_unblock_lock() (unlocked)
|
||||
//
|
||||
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;
|
||||
|
||||
public:
|
||||
template<class Lock>
|
||||
static bool wait ( ConditionMembers &data, Lock &lock
|
||||
, bool timeout_enabled, const boost::posix_time::ptime &abs_time);
|
||||
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 Lock>
|
||||
inline bool condition_algorithm_8a<ConditionMembers>::wait
|
||||
( ConditionMembers &data
|
||||
, Lock &lock
|
||||
, bool tout_enabled
|
||||
, const boost::posix_time::ptime &abs_time
|
||||
)
|
||||
{
|
||||
//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();
|
||||
|
||||
//Unlock external lock and program for relock
|
||||
lock_inverter<Lock> inverted_lock(lock);
|
||||
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
//lock.lock(); called from unlocker destructor
|
||||
|
||||
return ( bTimedOut ) ? false : true;
|
||||
}
|
||||
|
||||
|
||||
template<class ConditionMembers>
|
||||
class condition_8a_wrapper
|
||||
{
|
||||
//Non-copyable
|
||||
condition_8a_wrapper(const condition_8a_wrapper &);
|
||||
condition_8a_wrapper &operator=(const condition_8a_wrapper &);
|
||||
|
||||
ConditionMembers m_data;
|
||||
typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
|
||||
|
||||
public:
|
||||
|
||||
condition_8a_wrapper(){}
|
||||
|
||||
//Compiler-generated destructor is OK
|
||||
//~condition_8a_wrapper(){}
|
||||
|
||||
ConditionMembers & get_members()
|
||||
{ return m_data; }
|
||||
|
||||
const ConditionMembers & get_members() const
|
||||
{ return m_data; }
|
||||
|
||||
void notify_one()
|
||||
{ algo_type::signal(m_data, false); }
|
||||
|
||||
void notify_all()
|
||||
{ algo_type::signal(m_data, true); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
|
||||
while (!pred())
|
||||
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
return algo_type::wait(m_data, lock, true, abs_time);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
while (!pred()){
|
||||
if (!algo_type::wait(m_data, lock, true, abs_time))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_ALGORITHM_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Condition variable 'any' (able to use any type of external mutex)
|
||||
//
|
||||
// The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
|
||||
// Many thanks to Howard for his support and comments.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Required interface for ConditionAnyMembers
|
||||
// class ConditionAnyMembers
|
||||
// {
|
||||
// typedef implementation_defined mutex_type;
|
||||
// typedef implementation_defined condvar_type;
|
||||
//
|
||||
// condvar &get_condvar()
|
||||
// mutex_type &get_mutex()
|
||||
// };
|
||||
//
|
||||
// Must be initialized as following
|
||||
//
|
||||
// get_condvar() [no threads blocked]
|
||||
// get_mutex() [unlocked]
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
class condition_any_algorithm
|
||||
{
|
||||
private:
|
||||
condition_any_algorithm();
|
||||
~condition_any_algorithm();
|
||||
condition_any_algorithm(const condition_any_algorithm &);
|
||||
condition_any_algorithm &operator=(const condition_any_algorithm &);
|
||||
|
||||
typedef typename ConditionAnyMembers::mutex_type mutex_type;
|
||||
typedef typename ConditionAnyMembers::condvar_type condvar_type;
|
||||
|
||||
template <class Lock>
|
||||
static void do_wait(ConditionAnyMembers &data, Lock& lock);
|
||||
|
||||
template <class Lock>
|
||||
static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
|
||||
|
||||
public:
|
||||
template<class Lock>
|
||||
static bool wait ( ConditionAnyMembers &data, Lock &mut
|
||||
, bool timeout_enabled, const boost::posix_time::ptime &abs_time);
|
||||
static void signal( ConditionAnyMembers &data, bool broadcast);
|
||||
};
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
|
||||
{
|
||||
scoped_lock<mutex_type> internal_lock(data.get_mutex());
|
||||
if(broadcast){
|
||||
data.get_condvar().notify_all();
|
||||
}
|
||||
else{
|
||||
data.get_condvar().notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
template<class Lock>
|
||||
bool condition_any_algorithm<ConditionAnyMembers>::wait
|
||||
( ConditionAnyMembers &data
|
||||
, Lock &lock
|
||||
, bool tout_enabled
|
||||
, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if(tout_enabled){
|
||||
return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
|
||||
}
|
||||
else{
|
||||
condition_any_algorithm::do_wait(data, lock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
template <class Lock>
|
||||
void condition_any_algorithm<ConditionAnyMembers>::do_wait
|
||||
(ConditionAnyMembers &data, Lock& lock)
|
||||
{
|
||||
//lock internal before unlocking external to avoid race with a notifier
|
||||
scoped_lock<mutex_type> internal_lock(data.get_mutex());
|
||||
{
|
||||
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<mutex_type> internal_unlock;
|
||||
internal_lock.swap(internal_unlock);
|
||||
data.get_condvar().wait(internal_unlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
template <class Lock>
|
||||
bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
|
||||
(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//lock internal before unlocking external to avoid race with a notifier
|
||||
scoped_lock<mutex_type> internal_lock(data.get_mutex());
|
||||
{
|
||||
//Unlock external lock and program for relock
|
||||
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<mutex_type> internal_unlock;
|
||||
internal_lock.swap(internal_unlock);
|
||||
return data.get_condvar().timed_wait(internal_unlock, abs_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class ConditionAnyMembers>
|
||||
class condition_any_wrapper
|
||||
{
|
||||
//Non-copyable
|
||||
condition_any_wrapper(const condition_any_wrapper &);
|
||||
condition_any_wrapper &operator=(const condition_any_wrapper &);
|
||||
|
||||
ConditionAnyMembers m_data;
|
||||
typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
|
||||
|
||||
public:
|
||||
|
||||
condition_any_wrapper(){}
|
||||
|
||||
~condition_any_wrapper(){}
|
||||
|
||||
ConditionAnyMembers & get_members()
|
||||
{ return m_data; }
|
||||
|
||||
const ConditionAnyMembers & get_members() const
|
||||
{ return m_data; }
|
||||
|
||||
void notify_one()
|
||||
{ algo_type::signal(m_data, false); }
|
||||
|
||||
void notify_all()
|
||||
{ algo_type::signal(m_data, true); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
|
||||
while (!pred())
|
||||
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
return algo_type::wait(m_data, lock, true, abs_time);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
while (!pred()){
|
||||
if (!algo_type::wait(m_data, lock, true, abs_time))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
|
||||
@@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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_LOCKS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class Lock>
|
||||
class internal_mutex_lock
|
||||
{
|
||||
typedef void (internal_mutex_lock::*unspecified_bool_type)();
|
||||
public:
|
||||
|
||||
typedef typename Lock::mutex_type::internal_mutex_type mutex_type;
|
||||
|
||||
|
||||
internal_mutex_lock(Lock &l)
|
||||
: l_(l)
|
||||
{}
|
||||
|
||||
mutex_type* mutex() const
|
||||
{ return l_ ? &l_.mutex()->internal_mutex() : 0; }
|
||||
|
||||
void lock() { l_.lock(); }
|
||||
|
||||
void unlock() { l_.unlock(); }
|
||||
|
||||
operator unspecified_bool_type() const
|
||||
{ return l_ ? &internal_mutex_lock::lock : 0; }
|
||||
|
||||
private:
|
||||
Lock &l_;
|
||||
};
|
||||
|
||||
template <class Lock>
|
||||
class lock_inverter
|
||||
{
|
||||
Lock &l_;
|
||||
public:
|
||||
lock_inverter(Lock &l)
|
||||
: l_(l)
|
||||
{}
|
||||
void lock() { l_.unlock(); }
|
||||
void unlock() { l_.lock(); }
|
||||
};
|
||||
|
||||
template <class Lock>
|
||||
class lock_to_sharable
|
||||
{
|
||||
Lock &l_;
|
||||
|
||||
public:
|
||||
explicit lock_to_sharable(Lock &l)
|
||||
: l_(l)
|
||||
{}
|
||||
void lock() { l_.lock_sharable(); }
|
||||
bool try_lock(){ return l_.try_lock_sharable(); }
|
||||
void unlock() { l_.unlock_sharable(); }
|
||||
};
|
||||
|
||||
template <class Lock>
|
||||
class lock_to_wait
|
||||
{
|
||||
Lock &l_;
|
||||
|
||||
public:
|
||||
explicit lock_to_wait(Lock &l)
|
||||
: l_(l)
|
||||
{}
|
||||
void lock() { l_.wait(); }
|
||||
bool try_lock(){ return l_.try_wait(); }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
|
||||
@@ -0,0 +1,237 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_FILE_LOCK_HPP
|
||||
#define BOOST_INTERPROCESS_FILE_LOCK_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a class that wraps file locking capabilities.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
//!A file lock, is a mutual exclusion utility similar to a mutex using a
|
||||
//!file. A file lock has sharable and exclusive locking capabilities and
|
||||
//!can be used with scoped_lock and sharable_lock classes.
|
||||
//!A file lock can't guarantee synchronization between threads of the same
|
||||
//!process so just use file locks to synchronize threads from different processes.
|
||||
class file_lock
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock)
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Constructs an empty file mapping.
|
||||
//!Does not throw
|
||||
file_lock()
|
||||
: m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
|
||||
{}
|
||||
|
||||
//!Opens a file lock. Throws interprocess_exception if the file does not
|
||||
//!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.
|
||||
//!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.
|
||||
//!Does not throw
|
||||
file_lock &operator=(BOOST_RV_REF(file_lock) moved)
|
||||
{
|
||||
file_lock tmp(boost::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Closes a file lock. Does not throw.
|
||||
~file_lock();
|
||||
|
||||
//!Swaps two file_locks.
|
||||
//!Does not throw.
|
||||
void swap(file_lock &other)
|
||||
{
|
||||
file_handle_t tmp = m_file_hnd;
|
||||
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,
|
||||
//! and if another thread has exclusive, or sharable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive, or sharable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex, waits until
|
||||
//! it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
file_handle_t m_file_hnd;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
inline file_lock::file_lock(const char *name)
|
||||
{
|
||||
m_file_hnd = ipcdetail::open_existing_file(name, read_write);
|
||||
|
||||
if(m_file_hnd == ipcdetail::invalid_file()){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline file_lock::~file_lock()
|
||||
{
|
||||
if(m_file_hnd != ipcdetail::invalid_file()){
|
||||
ipcdetail::close_file(m_file_hnd);
|
||||
m_file_hnd = ipcdetail::invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
inline void file_lock::lock()
|
||||
{
|
||||
if(!ipcdetail::acquire_file_lock(m_file_hnd)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool file_lock::try_lock()
|
||||
{
|
||||
bool result;
|
||||
if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
|
||||
|
||||
inline void file_lock::unlock()
|
||||
{
|
||||
if(!ipcdetail::release_file_lock(m_file_hnd)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void file_lock::lock_sharable()
|
||||
{
|
||||
if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool file_lock::try_lock_sharable()
|
||||
{
|
||||
bool result;
|
||||
if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
ipcdetail::lock_to_sharable<file_lock> lsh(*this);
|
||||
return ipcdetail::try_based_timed_lock(lsh, abs_time);
|
||||
}
|
||||
|
||||
inline void file_lock::unlock_sharable()
|
||||
{
|
||||
if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_FILE_LOCK_HPP
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
|
||||
#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_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/condition.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!\file
|
||||
//!Describes process-shared variables interprocess_condition class
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace posix_time
|
||||
{ class ptime; }
|
||||
|
||||
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!This class is a condition variable that can be placed in shared memory or
|
||||
//!memory mapped files.
|
||||
//!Destroys the object of type std::condition_variable_any
|
||||
//!
|
||||
//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all
|
||||
//!threads have been only notified. It is required that they have exited their respective wait
|
||||
//!functions.
|
||||
class interprocess_condition
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
interprocess_condition(const interprocess_condition &);
|
||||
interprocess_condition &operator=(const interprocess_condition &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Constructs a interprocess_condition. On error throws interprocess_exception.
|
||||
interprocess_condition()
|
||||
{}
|
||||
|
||||
//!Destroys *this
|
||||
//!liberating system resources.
|
||||
~interprocess_condition()
|
||||
{}
|
||||
|
||||
//!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(); }
|
||||
|
||||
//!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()
|
||||
{ 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
|
||||
//!this->notify_one() or this->notify_all(), and then reacquires the lock.
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
m_condition.wait(internal_lock);
|
||||
}
|
||||
|
||||
//!The same as:
|
||||
//!while (!pred()) wait(lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
m_condition.wait(internal_lock, pred);
|
||||
}
|
||||
|
||||
//!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>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
return m_condition.timed_wait(internal_lock, 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)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
return m_condition.timed_wait(internal_lock, abs_time, pred);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
private:
|
||||
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
ipcdetail::spin_condition m_condition;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
|
||||
#undef BOOST_INTERPROCESS_USE_POSIX
|
||||
ipcdetail::posix_condition m_condition;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
#undef BOOST_INTERPROCESS_USE_WINDOWS
|
||||
ipcdetail::windows_condition m_condition;
|
||||
#else
|
||||
#error "Unknown platform for interprocess_mutex"
|
||||
#endif
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_CONDITION_HPP
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_HPP
|
||||
#define BOOST_INTERPROCESS_CONDITION_ANY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!\file
|
||||
//!Describes process-shared variables interprocess_condition_any class
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace posix_time
|
||||
{ class ptime; }
|
||||
|
||||
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!This class is a condition variable that can be placed in shared memory or
|
||||
//!memory mapped files.
|
||||
//!
|
||||
//!The interprocess_condition_any class is a generalization of interprocess_condition.
|
||||
//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex
|
||||
//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable
|
||||
//!requirements (lock()/unlock() member functions).
|
||||
//!
|
||||
//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all
|
||||
//!threads have been only notified. It is required that they have exited their respective wait
|
||||
//!functions.
|
||||
class interprocess_condition_any
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
interprocess_condition_any(const interprocess_condition_any &);
|
||||
interprocess_condition_any &operator=(const interprocess_condition_any &);
|
||||
|
||||
class members
|
||||
{
|
||||
public:
|
||||
typedef interprocess_condition condvar_type;
|
||||
typedef interprocess_mutex mutex_type;
|
||||
|
||||
condvar_type &get_condvar() { return m_cond; }
|
||||
mutex_type &get_mutex() { return m_mut; }
|
||||
|
||||
private:
|
||||
condvar_type m_cond;
|
||||
mutex_type m_mut;
|
||||
};
|
||||
|
||||
ipcdetail::condition_any_wrapper<members> m_cond;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Constructs a interprocess_condition_any. On error throws interprocess_exception.
|
||||
interprocess_condition_any(){}
|
||||
|
||||
//!Destroys *this
|
||||
//!liberating system resources.
|
||||
~interprocess_condition_any(){}
|
||||
|
||||
//!If there is a thread waiting on *this, change that
|
||||
//!thread's state to ready. Otherwise there is no effect.
|
||||
void notify_one()
|
||||
{ m_cond.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()
|
||||
{ m_cond.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
|
||||
//!this->notify_one() or this->notify_all(), and then reacquires the lock.
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{ m_cond.wait(lock); }
|
||||
|
||||
//!The same as:
|
||||
//!while (!pred()) wait(lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{ m_cond.wait(lock, pred); }
|
||||
|
||||
//!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>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{ return m_cond.timed_wait(lock, 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)
|
||||
{ return m_cond.timed_wait(lock, abs_time, pred); }
|
||||
};
|
||||
|
||||
} //namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP
|
||||
@@ -0,0 +1,188 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_MUTEX_HPP
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
|
||||
#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_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
namespace robust_emulation_helpers {
|
||||
|
||||
template<class T>
|
||||
class mutex_traits;
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!\file
|
||||
//!Describes a mutex class that can be placed in memory shared by
|
||||
//!several processes.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
class interprocess_condition;
|
||||
|
||||
//!Wraps a interprocess_mutex that can be placed in shared memory and can be
|
||||
//!shared between processes. Allows timed lock tries
|
||||
class interprocess_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
interprocess_mutex(const interprocess_mutex &);
|
||||
interprocess_mutex &operator=(const interprocess_mutex &);
|
||||
friend class interprocess_condition;
|
||||
|
||||
public:
|
||||
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
typedef ipcdetail::spin_mutex internal_mutex_type;
|
||||
private:
|
||||
friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
|
||||
void take_ownership(){ m_mutex.take_ownership(); }
|
||||
public:
|
||||
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
|
||||
#undef BOOST_INTERPROCESS_USE_POSIX
|
||||
typedef ipcdetail::posix_mutex internal_mutex_type;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
#undef BOOST_INTERPROCESS_USE_WINDOWS
|
||||
typedef ipcdetail::windows_mutex internal_mutex_type;
|
||||
#else
|
||||
#error "Unknown platform for interprocess_mutex"
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Constructor.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_mutex();
|
||||
|
||||
//!Destructor. If any process uses the mutex after the destructor is called
|
||||
//!the result is undefined. Does not throw.
|
||||
~interprocess_mutex();
|
||||
|
||||
//!Effects: The calling thread tries to obtain ownership of the mutex, and
|
||||
//! if another thread has ownership of the mutex, it waits until it can
|
||||
//! obtain the ownership. If a thread takes ownership of the mutex the
|
||||
//! mutex must be unlocked by the same mutex.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to obtain ownership of the mutex, and
|
||||
//! if another thread has ownership of the mutex returns immediately.
|
||||
//!Returns: If the thread acquires ownership of the mutex, returns true, if
|
||||
//! the another thread has ownership of the mutex, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock();
|
||||
|
||||
//!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.
|
||||
//!Returns: If the thread acquires ownership of the mutex, returns true, if
|
||||
//! the timeout expires returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Effects: The calling thread releases the exclusive ownership of the mutex.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
internal_mutex_type &internal_mutex()
|
||||
{ return m_mutex; }
|
||||
|
||||
const internal_mutex_type &internal_mutex() const
|
||||
{ return m_mutex; }
|
||||
|
||||
private:
|
||||
internal_mutex_type m_mutex;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
inline interprocess_mutex::interprocess_mutex(){}
|
||||
|
||||
inline interprocess_mutex::~interprocess_mutex(){}
|
||||
|
||||
inline void interprocess_mutex::lock()
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
|
||||
boost::posix_time::ptime wait_time
|
||||
= microsec_clock::universal_time()
|
||||
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
|
||||
if (!m_mutex.timed_lock(wait_time))
|
||||
{
|
||||
throw interprocess_exception(timeout_when_locking_error
|
||||
, "Interprocess mutex timeout when locking. Possible deadlock: "
|
||||
"owner died without unlocking?");
|
||||
}
|
||||
#else
|
||||
m_mutex.lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool interprocess_mutex::try_lock()
|
||||
{ return m_mutex.try_lock(); }
|
||||
|
||||
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_mutex.timed_lock(abs_time); }
|
||||
|
||||
inline void interprocess_mutex::unlock()
|
||||
{ m_mutex.unlock(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MUTEX_HPP
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
|
||||
(defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES))
|
||||
#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_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
#endif
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
namespace robust_emulation_helpers {
|
||||
|
||||
template<class T>
|
||||
class mutex_traits;
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!\file
|
||||
//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes
|
||||
|
||||
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
|
||||
//!process. Allows timed lock tries
|
||||
class interprocess_recursive_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
interprocess_recursive_mutex(const interprocess_recursive_mutex &);
|
||||
interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_recursive_mutex();
|
||||
|
||||
//!Destructor. If any process uses the mutex after the destructor is called
|
||||
//!the result is undefined. Does not throw.
|
||||
~interprocess_recursive_mutex();
|
||||
|
||||
//!Effects: The calling thread tries to obtain ownership of the mutex, and
|
||||
//! if another thread has ownership of the mutex, it waits until it can
|
||||
//! obtain the ownership. If a thread takes ownership of the mutex the
|
||||
//! mutex must be unlocked by the same mutex. The mutex must be unlocked
|
||||
//! the same number of times it is locked.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!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
|
||||
bool try_lock();
|
||||
|
||||
//!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before
|
||||
//!abs_time time, returns false. The mutex must be unlocked
|
||||
//! the same number of times it is locked.
|
||||
//!Throws: interprocess_exception if a severe error is found
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Effects: The calling thread releases the exclusive ownership of the mutex.
|
||||
//! If the mutex supports recursive locking, the mutex must be unlocked the
|
||||
//! same number of times it is locked.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void unlock();
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
void take_ownership(){ mutex.take_ownership(); }
|
||||
friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_recursive_mutex>;
|
||||
ipcdetail::spin_recursive_mutex mutex;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
|
||||
#undef BOOST_INTERPROCESS_USE_POSIX
|
||||
ipcdetail::posix_recursive_mutex mutex;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
#undef BOOST_INTERPROCESS_USE_WINDOWS
|
||||
ipcdetail::windows_recursive_mutex mutex;
|
||||
#else
|
||||
#error "Unknown platform for interprocess_mutex"
|
||||
#endif
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
inline interprocess_recursive_mutex::interprocess_recursive_mutex(){}
|
||||
|
||||
inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
|
||||
|
||||
inline void interprocess_recursive_mutex::lock()
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
|
||||
boost::posix_time::ptime wait_time
|
||||
= microsec_clock::universal_time()
|
||||
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
|
||||
if (!mutex.timed_lock(wait_time)){
|
||||
throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?");
|
||||
}
|
||||
#else
|
||||
mutex.lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool interprocess_recursive_mutex::try_lock()
|
||||
{ return mutex.try_lock(); }
|
||||
|
||||
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return mutex.timed_lock(abs_time); }
|
||||
|
||||
inline void interprocess_recursive_mutex::unlock()
|
||||
{ mutex.unlock(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_SEMAPHORE_HPP
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
|
||||
(defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES))
|
||||
#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_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/semaphore.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!\file
|
||||
//!Describes a interprocess_semaphore class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!Wraps a interprocess_semaphore that can be placed in shared memory and can be
|
||||
//!shared between processes. Allows timed lock tries
|
||||
class interprocess_semaphore
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
interprocess_semaphore(const interprocess_semaphore &);
|
||||
interprocess_semaphore &operator=(const interprocess_semaphore &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Creates a interprocess_semaphore with the given initial count.
|
||||
//!interprocess_exception if there is an error.*/
|
||||
interprocess_semaphore(unsigned int initialCount);
|
||||
|
||||
//!Destroys the interprocess_semaphore.
|
||||
//!Does not throw
|
||||
~interprocess_semaphore();
|
||||
|
||||
//!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting
|
||||
//!for the interprocess_semaphore, then one of these processes will return successfully from
|
||||
//!its wait function. If there is an error an interprocess_exception exception is thrown.
|
||||
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.
|
||||
//!If there is an error an interprocess_exception exception is thrown.
|
||||
void wait();
|
||||
|
||||
//!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero
|
||||
//!and returns true. If the value is not greater than zero returns false.
|
||||
//!If there is an error an interprocess_exception exception is thrown.
|
||||
bool try_wait();
|
||||
|
||||
//!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater
|
||||
//!than zero and returns true. Otherwise, waits for the interprocess_semaphore
|
||||
//!to the posted or the timeout expires. If the timeout expires, the
|
||||
//!function returns false. If the interprocess_semaphore is posted the function
|
||||
//!returns true. If there is an error throws sem_exception
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Returns the interprocess_semaphore count
|
||||
// int get_count() const;
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
ipcdetail::spin_semaphore m_sem;
|
||||
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
#undef BOOST_INTERPROCESS_USE_WINDOWS
|
||||
ipcdetail::windows_semaphore m_sem;
|
||||
#else
|
||||
#undef BOOST_INTERPROCESS_USE_POSIX
|
||||
ipcdetail::posix_semaphore m_sem;
|
||||
#endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount)
|
||||
: m_sem(initialCount)
|
||||
{}
|
||||
|
||||
inline interprocess_semaphore::~interprocess_semaphore(){}
|
||||
|
||||
inline void interprocess_semaphore::wait()
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
|
||||
boost::posix_time::ptime wait_time
|
||||
= microsec_clock::universal_time()
|
||||
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
|
||||
if (!m_sem.timed_wait(wait_time))
|
||||
{
|
||||
throw interprocess_exception(timeout_when_waiting_error, "Interprocess semaphore timeout when waiting. Possible deadlock: owner died without posting?");
|
||||
}
|
||||
#else
|
||||
m_sem.wait();
|
||||
#endif
|
||||
}
|
||||
inline bool interprocess_semaphore::try_wait()
|
||||
{ return m_sem.try_wait(); }
|
||||
|
||||
inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_sem.timed_wait(abs_time); }
|
||||
|
||||
inline void interprocess_semaphore::post()
|
||||
{ m_sem.post(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SEMAPHORE_HPP
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Code based on Howard Hinnant's shared_mutex class
|
||||
//
|
||||
// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost
|
||||
// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHARABLE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <climits>
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes interprocess_sharable_mutex class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be
|
||||
//!shared between processes. Allows timed lock tries
|
||||
class interprocess_sharable_mutex
|
||||
{
|
||||
//Non-copyable
|
||||
interprocess_sharable_mutex(const interprocess_sharable_mutex &);
|
||||
interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &);
|
||||
|
||||
friend class interprocess_condition;
|
||||
public:
|
||||
|
||||
//!Constructs the sharable lock.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_sharable_mutex();
|
||||
|
||||
//!Destroys the sharable lock.
|
||||
//!Does not throw.
|
||||
~interprocess_sharable_mutex();
|
||||
|
||||
//Exclusive locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
|
||||
//! and if another thread has exclusive or sharable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive or sharable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
typedef scoped_lock<interprocess_mutex> scoped_lock_t;
|
||||
|
||||
//Pack all the control data in a word to be able
|
||||
//to use atomic instructions in the future
|
||||
struct control_word_t
|
||||
{
|
||||
unsigned exclusive_in : 1;
|
||||
unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1;
|
||||
} m_ctrl;
|
||||
|
||||
interprocess_mutex m_mut;
|
||||
interprocess_condition m_first_gate;
|
||||
interprocess_condition m_second_gate;
|
||||
|
||||
private:
|
||||
//Rollback structures for exceptions or failure return values
|
||||
struct exclusive_rollback
|
||||
{
|
||||
exclusive_rollback(control_word_t &ctrl
|
||||
,interprocess_condition &first_gate)
|
||||
: mp_ctrl(&ctrl), m_first_gate(first_gate)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ mp_ctrl = 0; }
|
||||
|
||||
~exclusive_rollback()
|
||||
{
|
||||
if(mp_ctrl){
|
||||
mp_ctrl->exclusive_in = 0;
|
||||
m_first_gate.notify_all();
|
||||
}
|
||||
}
|
||||
control_word_t *mp_ctrl;
|
||||
interprocess_condition &m_first_gate;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
struct base_constants_t
|
||||
{
|
||||
static const unsigned max_readers
|
||||
= ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1));
|
||||
};
|
||||
typedef base_constants_t<0> constants;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
template <int Dummy>
|
||||
const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers;
|
||||
|
||||
inline interprocess_sharable_mutex::interprocess_sharable_mutex()
|
||||
{
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
this->m_ctrl.num_shared = 0;
|
||||
}
|
||||
|
||||
inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
|
||||
{}
|
||||
|
||||
inline void interprocess_sharable_mutex::lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
|
||||
//The exclusive lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
while (this->m_ctrl.exclusive_in){
|
||||
this->m_first_gate.wait(lck);
|
||||
}
|
||||
|
||||
//Mark that exclusive lock has been acquired
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
|
||||
|
||||
//Now wait until all readers are gone
|
||||
while (this->m_ctrl.num_shared){
|
||||
this->m_second_gate.wait(lck);
|
||||
}
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
inline bool interprocess_sharable_mutex::try_lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//If we can't lock or any has there is any exclusive
|
||||
//or sharable mark return false;
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_shared){
|
||||
return false;
|
||||
}
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_sharable_mutex::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//The exclusive lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
while (this->m_ctrl.exclusive_in){
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
if(!this->m_first_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.exclusive_in){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Mark that exclusive lock has been acquired
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
|
||||
|
||||
//Now wait until all readers are gone
|
||||
while (this->m_ctrl.num_shared){
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
if(!this->m_second_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.num_shared){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
rollback.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void interprocess_sharable_mutex::unlock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
this->m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
//Sharable locking
|
||||
|
||||
inline void interprocess_sharable_mutex::lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
|
||||
//The sharable lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
while(this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_shared == constants::max_readers){
|
||||
this->m_first_gate.wait(lck);
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_shared;
|
||||
}
|
||||
|
||||
inline bool interprocess_sharable_mutex::try_lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//The sharable lock must fail
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_shared == constants::max_readers){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_shared;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_sharable_mutex::timed_lock_sharable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//The sharable lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
while (this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_shared == constants::max_readers){
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
if(!this->m_first_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_shared == constants::max_readers){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_shared;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void interprocess_sharable_mutex::unlock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Decrement sharable count
|
||||
--this->m_ctrl.num_shared;
|
||||
if (this->m_ctrl.num_shared == 0){
|
||||
this->m_second_gate.notify_one();
|
||||
}
|
||||
//Check if there are blocked sharables because of
|
||||
//there were too many sharables
|
||||
else if(this->m_ctrl.num_shared == (constants::max_readers-1)){
|
||||
this->m_first_gate.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
|
||||
+677
@@ -0,0 +1,677 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Code based on Howard Hinnant's upgrade_mutex class
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_UPGRADABLE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <climits>
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes interprocess_upgradable_mutex class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!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
|
||||
{
|
||||
//Non-copyable
|
||||
interprocess_upgradable_mutex(const interprocess_upgradable_mutex &);
|
||||
interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &);
|
||||
|
||||
friend class interprocess_condition;
|
||||
public:
|
||||
|
||||
//!Constructs the upgradable lock.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_upgradable_mutex();
|
||||
|
||||
//!Destroys the upgradable lock.
|
||||
//!Does not throw.
|
||||
~interprocess_upgradable_mutex();
|
||||
|
||||
//Exclusive locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
|
||||
//! and if another thread has exclusive, sharable or upgradable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive, sharable or upgradable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
|
||||
//Upgradable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
|
||||
//! and if another thread has exclusive or upgradable ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire upgradable ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_upgradable();
|
||||
|
||||
//Demotions
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_upgradable_and_lock();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
bool try_unlock_sharable_and_lock_upgradable();
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
typedef scoped_lock<interprocess_mutex> scoped_lock_t;
|
||||
|
||||
//Pack all the control data in a word to be able
|
||||
//to use atomic instructions in the future
|
||||
struct control_word_t
|
||||
{
|
||||
unsigned exclusive_in : 1;
|
||||
unsigned upgradable_in : 1;
|
||||
unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2;
|
||||
} m_ctrl;
|
||||
|
||||
interprocess_mutex m_mut;
|
||||
interprocess_condition m_first_gate;
|
||||
interprocess_condition m_second_gate;
|
||||
|
||||
private:
|
||||
//Rollback structures for exceptions or failure return values
|
||||
struct exclusive_rollback
|
||||
{
|
||||
exclusive_rollback(control_word_t &ctrl
|
||||
,interprocess_condition &first_gate)
|
||||
: mp_ctrl(&ctrl), m_first_gate(first_gate)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ mp_ctrl = 0; }
|
||||
|
||||
~exclusive_rollback()
|
||||
{
|
||||
if(mp_ctrl){
|
||||
mp_ctrl->exclusive_in = 0;
|
||||
m_first_gate.notify_all();
|
||||
}
|
||||
}
|
||||
control_word_t *mp_ctrl;
|
||||
interprocess_condition &m_first_gate;
|
||||
};
|
||||
|
||||
struct upgradable_to_exclusive_rollback
|
||||
{
|
||||
upgradable_to_exclusive_rollback(control_word_t &ctrl)
|
||||
: mp_ctrl(&ctrl)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ mp_ctrl = 0; }
|
||||
|
||||
~upgradable_to_exclusive_rollback()
|
||||
{
|
||||
if(mp_ctrl){
|
||||
//Recover upgradable lock
|
||||
mp_ctrl->upgradable_in = 1;
|
||||
++mp_ctrl->num_upr_shar;
|
||||
//Execute the second half of exclusive locking
|
||||
mp_ctrl->exclusive_in = 0;
|
||||
}
|
||||
}
|
||||
control_word_t *mp_ctrl;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
struct base_constants_t
|
||||
{
|
||||
static const unsigned max_readers
|
||||
= ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
|
||||
};
|
||||
typedef base_constants_t<0> constants;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
template <int Dummy>
|
||||
const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
|
||||
|
||||
inline interprocess_upgradable_mutex::interprocess_upgradable_mutex()
|
||||
{
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
this->m_ctrl.num_upr_shar = 0;
|
||||
}
|
||||
|
||||
inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
|
||||
{}
|
||||
|
||||
inline void interprocess_upgradable_mutex::lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
|
||||
//The exclusive lock must block in the first gate
|
||||
//if an exclusive or upgradable lock has been acquired
|
||||
while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
|
||||
this->m_first_gate.wait(lck);
|
||||
}
|
||||
|
||||
//Mark that exclusive lock has been acquired
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
|
||||
|
||||
//Now wait until all readers are gone
|
||||
while (this->m_ctrl.num_upr_shar){
|
||||
this->m_second_gate.wait(lck);
|
||||
}
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//If we can't lock or any has there is any exclusive, upgradable
|
||||
//or sharable mark return false;
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_upr_shar){
|
||||
return false;
|
||||
}
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//The exclusive lock must block in the first gate
|
||||
//if an exclusive or upgradable lock has been acquired
|
||||
while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
|
||||
if(!this->m_first_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Mark that exclusive lock has been acquired
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
|
||||
|
||||
//Now wait until all readers are gone
|
||||
while (this->m_ctrl.num_upr_shar){
|
||||
if(!this->m_second_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.num_upr_shar){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
rollback.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
this->m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
//Upgradable locking
|
||||
|
||||
inline void interprocess_upgradable_mutex::lock_upgradable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
|
||||
//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 || this->m_ctrl.upgradable_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
this->m_first_gate.wait(lck);
|
||||
}
|
||||
|
||||
//Mark that upgradable lock has been acquired
|
||||
//And add upgradable to the sharable count
|
||||
this->m_ctrl.upgradable_in = 1;
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_lock_upgradable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//The upgradable lock must fail
|
||||
//if an exclusive or upgradable lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.upgradable_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Mark that upgradable lock has been acquired
|
||||
//And add upgradable to the sharable count
|
||||
this->m_ctrl.upgradable_in = 1;
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::timed_lock_upgradable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//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
|
||||
|| this->m_ctrl.upgradable_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
if(!this->m_first_gate.timed_wait(lck, abs_time)){
|
||||
if((this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.upgradable_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers)){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Mark that upgradable lock has been acquired
|
||||
//And add upgradable to the sharable count
|
||||
this->m_ctrl.upgradable_in = 1;
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_upgradable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Mark that upgradable lock has been acquired
|
||||
//And add upgradable to the sharable count
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
--this->m_ctrl.num_upr_shar;
|
||||
this->m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
//Sharable locking
|
||||
|
||||
inline void interprocess_upgradable_mutex::lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
|
||||
//The sharable lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
while(this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
this->m_first_gate.wait(lck);
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//The sharable lock must fail
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::timed_lock_sharable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//The sharable lock must block in the first gate
|
||||
//if an exclusive lock has been acquired
|
||||
//or there are too many sharable locks
|
||||
while (this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
if(!this->m_first_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.num_upr_shar == constants::max_readers){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Increment sharable count
|
||||
++this->m_ctrl.num_upr_shar;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Decrement sharable count
|
||||
--this->m_ctrl.num_upr_shar;
|
||||
if (this->m_ctrl.num_upr_shar == 0){
|
||||
this->m_second_gate.notify_one();
|
||||
}
|
||||
//Check if there are blocked sharables because of
|
||||
//there were too many sharables
|
||||
else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){
|
||||
this->m_first_gate.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
//Downgrading
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Unmark it as exclusive
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
//Mark it as upgradable
|
||||
this->m_ctrl.upgradable_in = 1;
|
||||
//The sharable count should be 0 so increment it
|
||||
this->m_ctrl.num_upr_shar = 1;
|
||||
//Notify readers that they can enter
|
||||
m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Unmark it as exclusive
|
||||
this->m_ctrl.exclusive_in = 0;
|
||||
//The sharable count should be 0 so increment it
|
||||
this->m_ctrl.num_upr_shar = 1;
|
||||
//Notify readers that they can enter
|
||||
m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Unmark it as upgradable (we don't have to decrement count)
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
//Notify readers/upgradable that they can enter
|
||||
m_first_gate.notify_all();
|
||||
}
|
||||
|
||||
//Upgrading
|
||||
|
||||
inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut);
|
||||
//Simulate unlock_upgradable() without
|
||||
//notifying sharables.
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
--this->m_ctrl.num_upr_shar;
|
||||
//Execute the second half of exclusive locking
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
upgradable_to_exclusive_rollback rollback(m_ctrl);
|
||||
|
||||
while (this->m_ctrl.num_upr_shar){
|
||||
this->m_second_gate.wait(lck);
|
||||
}
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
//Check if there are no readers
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.num_upr_shar != 1){
|
||||
return false;
|
||||
}
|
||||
//Now unlock upgradable and mark exclusive
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
--this->m_ctrl.num_upr_shar;
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Mutexes and condvars handle just fine infinite abs_times
|
||||
//so avoid checking it here
|
||||
scoped_lock_t lck(m_mut, abs_time);
|
||||
if(!lck.owns()) return false;
|
||||
|
||||
//Simulate unlock_upgradable() without
|
||||
//notifying sharables.
|
||||
this->m_ctrl.upgradable_in = 0;
|
||||
--this->m_ctrl.num_upr_shar;
|
||||
//Execute the second half of exclusive locking
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
|
||||
//Prepare rollback
|
||||
upgradable_to_exclusive_rollback rollback(m_ctrl);
|
||||
|
||||
while (this->m_ctrl.num_upr_shar){
|
||||
if(!this->m_second_gate.timed_wait(lck, abs_time)){
|
||||
if(this->m_ctrl.num_upr_shar){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
rollback.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//If we can't lock or any has there is any exclusive, upgradable
|
||||
//or sharable mark return false;
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.upgradable_in
|
||||
|| this->m_ctrl.num_upr_shar != 1){
|
||||
return false;
|
||||
}
|
||||
this->m_ctrl.exclusive_in = 1;
|
||||
this->m_ctrl.num_upr_shar = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
|
||||
{
|
||||
scoped_lock_t lck(m_mut, try_to_lock);
|
||||
|
||||
//The upgradable lock must fail
|
||||
//if an exclusive or upgradable lock has been acquired
|
||||
if(!lck.owns()
|
||||
|| this->m_ctrl.exclusive_in
|
||||
|| this->m_ctrl.upgradable_in){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Mark that upgradable lock has been acquired
|
||||
this->m_ctrl.upgradable_in = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
|
||||
@@ -0,0 +1,63 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_LOCK_OPTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes the lock options with associated with interprocess_mutex lock constructors.
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace posix_time
|
||||
{ class ptime; }
|
||||
|
||||
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!Type to indicate to a mutex lock constructor that must not lock the mutex.
|
||||
struct defer_lock_type{};
|
||||
//!Type to indicate to a mutex lock constructor that must try to lock the mutex.
|
||||
struct try_to_lock_type {};
|
||||
//!Type to indicate to a mutex lock constructor that the mutex is already locked.
|
||||
struct accept_ownership_type{};
|
||||
|
||||
//!An object indicating that the locking
|
||||
//!must be deferred.
|
||||
static const defer_lock_type defer_lock = defer_lock_type();
|
||||
|
||||
//!An object indicating that a try_lock()
|
||||
//!operation must be executed.
|
||||
static const try_to_lock_type try_to_lock = try_to_lock_type();
|
||||
|
||||
//!An object indicating that the ownership of lockable
|
||||
//!object must be accepted by the new owner.
|
||||
static const accept_ownership_type accept_ownership = accept_ownership_type();
|
||||
|
||||
} // namespace interprocess {
|
||||
} // namespace boost{
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
|
||||
@@ -0,0 +1,60 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_MUTEX_FAMILY_HPP
|
||||
#define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
||||
#include <boost/interprocess/sync/null_mutex.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a shared interprocess_mutex family fit algorithm used to allocate objects in shared memory.
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!Describes interprocess_mutex family to use with Interprocess framework
|
||||
//!based on boost::interprocess synchronization objects.
|
||||
struct mutex_family
|
||||
{
|
||||
typedef boost::interprocess::interprocess_mutex mutex_type;
|
||||
typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type;
|
||||
};
|
||||
|
||||
//!Describes interprocess_mutex family to use with Interprocess frameworks
|
||||
//!based on null operation synchronization objects.
|
||||
struct null_mutex_family
|
||||
{
|
||||
typedef boost::interprocess::null_mutex mutex_type;
|
||||
typedef boost::interprocess::null_mutex recursive_mutex_type;
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#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/detail/locks.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
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//! A global condition variable that can be created by name.
|
||||
//! This condition variable is designed to work with named_mutex and
|
||||
//! can't be placed in shared memory or memory mapped files.
|
||||
class named_condition
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_condition();
|
||||
named_condition(const named_condition &);
|
||||
named_condition &operator=(const named_condition &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Creates a global condition with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!named_condition(open_only_t, ... )
|
||||
//!Does not throw
|
||||
named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global condition with a name if that condition is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_condition(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~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);
|
||||
|
||||
//!Erases a named condition from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
#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()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_condition::~named_condition()
|
||||
{}
|
||||
|
||||
inline named_condition::named_condition(create_only_t, const char *name, const permissions &perm)
|
||||
: m_cond(create_only_t(), name, perm)
|
||||
{}
|
||||
|
||||
inline named_condition::named_condition(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_cond(open_or_create_t(), name, perm)
|
||||
{}
|
||||
|
||||
inline named_condition::named_condition(open_only_t, const char *name)
|
||||
: m_cond(open_only_t(), name)
|
||||
{}
|
||||
|
||||
inline void named_condition::notify_one()
|
||||
{ m_cond.notify_one(); }
|
||||
|
||||
inline void named_condition::notify_all()
|
||||
{ m_cond.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
inline void named_condition::wait(L& lock)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
m_cond.wait(internal_lock);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
inline void named_condition::wait(L& lock, Pr pred)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
m_cond.wait(internal_lock, pred);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
inline bool named_condition::timed_wait
|
||||
(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
return m_cond.timed_wait(internal_lock, abs_time);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
inline bool named_condition::timed_wait
|
||||
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{
|
||||
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
|
||||
return m_cond.timed_wait(internal_lock, abs_time, pred);
|
||||
}
|
||||
|
||||
inline bool named_condition::remove(const char *name)
|
||||
{
|
||||
return condition_type::remove(name);
|
||||
}
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_NAMED_CONDITION_HPP
|
||||
@@ -0,0 +1,155 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_CONDITION_ANY_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#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/detail/locks.hpp>
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
#include <boost/interprocess/sync/windows/named_condition_any.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_WINDOWS
|
||||
#else
|
||||
#include <boost/interprocess/sync/shm/named_condition_any.hpp>
|
||||
#endif
|
||||
|
||||
//!\file
|
||||
//!Describes a named condition class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//! A global condition variable that can be created by name.
|
||||
//! This condition variable is designed to work with named_mutex and
|
||||
//! can't be placed in shared memory or memory mapped files.
|
||||
class named_condition_any
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_condition_any();
|
||||
named_condition_any(const named_condition_any &);
|
||||
named_condition_any &operator=(const named_condition_any &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Creates a global condition with a name.
|
||||
//!If the condition can't be created throws interprocess_exception
|
||||
named_condition_any(create_only_t, const char *name, const permissions &perm = permissions())
|
||||
: m_cond(create_only_t(), name, perm)
|
||||
{}
|
||||
|
||||
//!Opens or creates a global condition with a name.
|
||||
//!If the condition is created, this call is equivalent to
|
||||
//!named_condition_any(create_only_t, ... )
|
||||
//!If the condition is already created, this call is equivalent
|
||||
//!named_condition_any(open_only_t, ... )
|
||||
//!Does not throw
|
||||
named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions())
|
||||
: m_cond(open_or_create_t(), name, perm)
|
||||
{}
|
||||
|
||||
//!Opens a global condition with a name if that condition is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_condition_any(open_only_t, const char *name)
|
||||
: m_cond(open_only_t(), name)
|
||||
{}
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_condition_any()
|
||||
{}
|
||||
|
||||
//!If there is a thread waiting on *this, change that
|
||||
//!thread's state to ready. Otherwise there is no effect.*/
|
||||
void notify_one()
|
||||
{ m_cond.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()
|
||||
{ m_cond.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)
|
||||
{ return m_cond.wait(lock); }
|
||||
|
||||
//!The same as:
|
||||
//!while (!pred()) wait(lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{ return m_cond.wait(lock, 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)
|
||||
{ return m_cond.timed_wait(lock, 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)
|
||||
{ return m_cond.timed_wait(lock, abs_time, pred); }
|
||||
|
||||
//!Erases a named condition from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name)
|
||||
{ return condition_any_type::remove(name); }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
#if defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
typedef ipcdetail::windows_named_condition_any condition_any_type;
|
||||
#else
|
||||
typedef ipcdetail::shm_named_condition_any condition_any_type;
|
||||
#endif
|
||||
condition_any_type m_cond;
|
||||
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
|
||||
@@ -0,0 +1,175 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
|
||||
#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
|
||||
|
||||
//!\file
|
||||
//!Describes a named mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
named_mutex();
|
||||
named_mutex(const named_mutex &);
|
||||
named_mutex &operator=(const named_mutex &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Creates a global mutex with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!named_mutex(open_only_t, ... )
|
||||
//!Does not throw
|
||||
named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global mutex with a name if that mutex is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_mutex();
|
||||
|
||||
//!Unlocks a previously locked
|
||||
//!mutex.
|
||||
void unlock();
|
||||
|
||||
//!Locks the mutex, sleeps when the mutex is already locked.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
void lock();
|
||||
|
||||
//!Tries to lock the mutex, returns false when the mutex
|
||||
//!is already locked, returns true when success.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
bool try_lock();
|
||||
|
||||
//!Tries to lock the the mutex until time abs_time,
|
||||
//!Returns false when timeout expires, returns true when locks.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Erases a named mutex from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
public:
|
||||
#if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES)
|
||||
typedef ipcdetail::posix_named_mutex internal_mutex_type;
|
||||
#undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
|
||||
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
|
||||
typedef ipcdetail::windows_named_mutex internal_mutex_type;
|
||||
#undef BOOST_INTERPROCESS_USE_WINDOWS
|
||||
#else
|
||||
typedef ipcdetail::shm_named_mutex internal_mutex_type;
|
||||
#endif
|
||||
internal_mutex_type &internal_mutex()
|
||||
{ return m_mut; }
|
||||
|
||||
internal_mutex_type m_mut;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm)
|
||||
: m_mut(create_only_t(), name, perm)
|
||||
{}
|
||||
|
||||
inline named_mutex::named_mutex(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_mut(open_or_create_t(), name, perm)
|
||||
{}
|
||||
|
||||
inline named_mutex::named_mutex(open_only_t, const char *name)
|
||||
: m_mut(open_only_t(), name)
|
||||
{}
|
||||
|
||||
inline void named_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); }
|
||||
|
||||
inline named_mutex::~named_mutex()
|
||||
{}
|
||||
|
||||
inline void named_mutex::lock()
|
||||
{ m_mut.lock(); }
|
||||
|
||||
inline void named_mutex::unlock()
|
||||
{ m_mut.unlock(); }
|
||||
|
||||
inline bool named_mutex::try_lock()
|
||||
{ return m_mut.try_lock(); }
|
||||
|
||||
inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_mut.timed_lock(abs_time); }
|
||||
|
||||
inline bool named_mutex::remove(const char *name)
|
||||
{ return internal_mutex_type::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NAMED_MUTEX_HPP
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/permissions.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
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_recursive_mutex();
|
||||
named_recursive_mutex(const named_recursive_mutex &);
|
||||
named_recursive_mutex &operator=(const named_recursive_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Creates a global recursive_mutex with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!named_recursive_mutex(open_only_t, ... )
|
||||
//!Does not throw
|
||||
named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_recursive_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_recursive_mutex();
|
||||
|
||||
//!Unlocks a previously locked
|
||||
//!named_recursive_mutex.
|
||||
void unlock();
|
||||
|
||||
//!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked.
|
||||
//!Throws interprocess_exception if a severe error is found.
|
||||
void lock();
|
||||
|
||||
//!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();
|
||||
|
||||
//!Tries to lock the named_recursive_mutex until time abs_time,
|
||||
//!Returns false when timeout expires, returns true when locks.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Erases a named recursive mutex
|
||||
//!from the system
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
#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;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_recursive_mutex::~named_recursive_mutex()
|
||||
{}
|
||||
|
||||
inline void named_recursive_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); }
|
||||
|
||||
inline named_recursive_mutex::named_recursive_mutex(create_only_t, const char *name, const permissions &perm)
|
||||
: m_mut (create_only, name, perm)
|
||||
{}
|
||||
|
||||
inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_mut (open_or_create, name, perm)
|
||||
{}
|
||||
|
||||
inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *name)
|
||||
: m_mut (open_only, name)
|
||||
{}
|
||||
|
||||
inline void named_recursive_mutex::lock()
|
||||
{ m_mut.lock(); }
|
||||
|
||||
inline void named_recursive_mutex::unlock()
|
||||
{ m_mut.unlock(); }
|
||||
|
||||
inline bool named_recursive_mutex::try_lock()
|
||||
{ return m_mut.try_lock(); }
|
||||
|
||||
inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_mut.timed_lock(abs_time); }
|
||||
|
||||
inline bool named_recursive_mutex::remove(const char *name)
|
||||
{ return impl_t::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
|
||||
@@ -0,0 +1,173 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
#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
|
||||
|
||||
//!\file
|
||||
//!Describes a named semaphore class for inter-process synchronization
|
||||
|
||||
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
|
||||
//!acknowledgment mechanisms.
|
||||
class named_semaphore
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
named_semaphore();
|
||||
named_semaphore(const named_semaphore &);
|
||||
named_semaphore &operator=(const named_semaphore &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!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.
|
||||
//!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
|
||||
//!named_semaphore(open_only_t, ... )
|
||||
//!and initialCount is ignored.
|
||||
named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global semaphore with a name if that semaphore is previously.
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_semaphore(open_only_t, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_semaphore();
|
||||
|
||||
//!Increments the semaphore count. If there are processes/threads blocked waiting
|
||||
//!for the semaphore, then one of these processes will return successfully from
|
||||
//!its wait function. If there is an error an interprocess_exception exception is thrown.
|
||||
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.
|
||||
//!If there is an error an interprocess_exception exception is thrown.
|
||||
void wait();
|
||||
|
||||
//!Decrements the semaphore if the semaphore's value is greater than zero
|
||||
//!and returns true. If the value is not greater than zero returns false.
|
||||
//!If there is an error an interprocess_exception exception is thrown.
|
||||
bool try_wait();
|
||||
|
||||
//!Decrements the semaphore if the semaphore's value is greater
|
||||
//!than zero and returns true. Otherwise, waits for the semaphore
|
||||
//!to the posted or the timeout expires. If the timeout expires, the
|
||||
//!function returns false. If the semaphore is posted the function
|
||||
//!returns true. If there is an error throws sem_exception
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Erases a named semaphore from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
|
||||
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;
|
||||
#endif
|
||||
impl_t m_sem;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_semaphore::named_semaphore
|
||||
(create_only_t, const char *name, unsigned int initialCount, const permissions &perm)
|
||||
: m_sem(create_only, name, initialCount, perm)
|
||||
{}
|
||||
|
||||
inline named_semaphore::named_semaphore
|
||||
(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm)
|
||||
: m_sem(open_or_create, name, initialCount, perm)
|
||||
{}
|
||||
|
||||
inline named_semaphore::named_semaphore(open_only_t, const char *name)
|
||||
: m_sem(open_only, name)
|
||||
{}
|
||||
|
||||
inline named_semaphore::~named_semaphore()
|
||||
{}
|
||||
|
||||
inline void named_semaphore::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_sem); }
|
||||
|
||||
inline void named_semaphore::wait()
|
||||
{ m_sem.wait(); }
|
||||
|
||||
inline void named_semaphore::post()
|
||||
{ m_sem.post(); }
|
||||
|
||||
inline bool named_semaphore::try_wait()
|
||||
{ return m_sem.try_wait(); }
|
||||
|
||||
inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_sem.timed_wait(abs_time); }
|
||||
|
||||
inline bool named_semaphore::remove(const char *name)
|
||||
{ return impl_t::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
|
||||
@@ -0,0 +1,234 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_SHARABLE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_sharable_mutex.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named sharable mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!A sharable 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 sharable mutex.
|
||||
class named_sharable_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_sharable_mutex();
|
||||
named_sharable_mutex(const named_sharable_mutex &);
|
||||
named_sharable_mutex &operator=(const named_sharable_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Creates a global sharable mutex with a name.
|
||||
//!If the sharable mutex can't be created throws interprocess_exception
|
||||
named_sharable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens or creates a global sharable mutex with a name.
|
||||
//!If the sharable mutex is created, this call is equivalent to
|
||||
//!named_sharable_mutex(create_only_t, ...)
|
||||
//!If the sharable mutex is already created, this call is equivalent to
|
||||
//!named_sharable_mutex(open_only_t, ... ).
|
||||
named_sharable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global sharable mutex with a name if that sharable mutex
|
||||
//!is previously.
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_sharable_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_sharable_mutex();
|
||||
|
||||
//Exclusive locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
|
||||
//! and if another thread has exclusive or sharable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive or sharable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
|
||||
//!Erases a named sharable mutex from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
interprocess_sharable_mutex *mutex() const
|
||||
{ return static_cast<interprocess_sharable_mutex*>(m_shmem.get_user_address()); }
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef ipcdetail::named_creation_functor<interprocess_sharable_mutex> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_sharable_mutex::~named_sharable_mutex()
|
||||
{}
|
||||
|
||||
inline named_sharable_mutex::named_sharable_mutex
|
||||
(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_sharable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_sharable_mutex::named_sharable_mutex
|
||||
(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_sharable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_sharable_mutex::named_sharable_mutex
|
||||
(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
inline void named_sharable_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline void named_sharable_mutex::lock()
|
||||
{ this->mutex()->lock(); }
|
||||
|
||||
inline void named_sharable_mutex::unlock()
|
||||
{ this->mutex()->unlock(); }
|
||||
|
||||
inline bool named_sharable_mutex::try_lock()
|
||||
{ return this->mutex()->try_lock(); }
|
||||
|
||||
inline bool named_sharable_mutex::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock(abs_time); }
|
||||
|
||||
inline void named_sharable_mutex::lock_sharable()
|
||||
{ this->mutex()->lock_sharable(); }
|
||||
|
||||
inline void named_sharable_mutex::unlock_sharable()
|
||||
{ this->mutex()->unlock_sharable(); }
|
||||
|
||||
inline bool named_sharable_mutex::try_lock_sharable()
|
||||
{ return this->mutex()->try_lock_sharable(); }
|
||||
|
||||
inline bool named_sharable_mutex::timed_lock_sharable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock_sharable(abs_time); }
|
||||
|
||||
inline bool named_sharable_mutex::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
|
||||
+363
@@ -0,0 +1,363 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_named_upgradable_mutex_HPP
|
||||
#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named upgradable mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_upgradable_mutex();
|
||||
named_upgradable_mutex(const named_upgradable_mutex &);
|
||||
named_upgradable_mutex &operator=(const named_upgradable_mutex &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!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.
|
||||
//!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
|
||||
//!named_upgradable_mutex(open_only_t, ... ).
|
||||
named_upgradable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global upgradable mutex with a name if that upgradable mutex
|
||||
//!is previously.
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_upgradable_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_upgradable_mutex();
|
||||
|
||||
//Exclusive locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
|
||||
//! and if another thread has exclusive, sharable or upgradable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive, sharable or upgradable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
|
||||
//Upgradable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
|
||||
//! and if another thread has exclusive or upgradable ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire upgradable ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_upgradable();
|
||||
|
||||
//Demotions
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Effects: The thread atomically releases upgradable ownership and acquires
|
||||
//! exclusive ownership. This operation will block until all threads with
|
||||
//! 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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
bool try_unlock_sharable_and_lock_upgradable();
|
||||
|
||||
//!Erases a named upgradable mutex from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
interprocess_upgradable_mutex *mutex() const
|
||||
{ return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_upgradable_mutex::~named_upgradable_mutex()
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_upgradable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_upgradable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
inline void named_upgradable_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline void named_upgradable_mutex::lock()
|
||||
{ this->mutex()->lock(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock()
|
||||
{ this->mutex()->unlock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock()
|
||||
{ return this->mutex()->try_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::lock_upgradable()
|
||||
{ this->mutex()->lock_upgradable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable()
|
||||
{ this->mutex()->unlock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock_upgradable()
|
||||
{ return this->mutex()->try_lock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock_upgradable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock_upgradable(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::lock_sharable()
|
||||
{ this->mutex()->lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_sharable()
|
||||
{ this->mutex()->unlock_sharable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock_sharable()
|
||||
{ return this->mutex()->try_lock_sharable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock_sharable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock_sharable(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
|
||||
{ this->mutex()->unlock_and_lock_upgradable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_and_lock_sharable()
|
||||
{ this->mutex()->unlock_and_lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable()
|
||||
{ this->mutex()->unlock_upgradable_and_lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable_and_lock()
|
||||
{ this->mutex()->unlock_upgradable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
|
||||
{ return this->mutex()->try_unlock_upgradable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
|
||||
{ return this->mutex()->try_unlock_sharable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
|
||||
{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP
|
||||
@@ -0,0 +1,155 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NULL_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_NULL_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes null_mutex classes
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace posix_time
|
||||
{ class ptime; }
|
||||
|
||||
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!Implements a mutex that simulates a mutex without doing any operation and
|
||||
//!simulates a successful operation.
|
||||
class null_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
null_mutex(const null_mutex&);
|
||||
null_mutex &operator= (const null_mutex&);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Constructor.
|
||||
//!Empty.
|
||||
null_mutex(){}
|
||||
|
||||
//!Destructor.
|
||||
//!Empty.
|
||||
~null_mutex(){}
|
||||
|
||||
//!Simulates a mutex lock() operation. Empty function.
|
||||
void lock(){}
|
||||
|
||||
//!Simulates a mutex try_lock() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool try_lock()
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex timed_lock() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool timed_lock(const boost::posix_time::ptime &)
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex unlock() operation.
|
||||
//!Empty function.
|
||||
void unlock(){}
|
||||
|
||||
//!Simulates a mutex lock_sharable() operation.
|
||||
//!Empty function.
|
||||
void lock_sharable(){}
|
||||
|
||||
//!Simulates a mutex try_lock_sharable() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool try_lock_sharable()
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex timed_lock_sharable() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool timed_lock_sharable(const boost::posix_time::ptime &)
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex unlock_sharable() operation.
|
||||
//!Empty function.
|
||||
void unlock_sharable(){}
|
||||
|
||||
//!Simulates a mutex lock_upgradable() operation.
|
||||
//!Empty function.
|
||||
void lock_upgradable(){}
|
||||
|
||||
//!Simulates a mutex try_lock_upgradable() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool try_lock_upgradable()
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex timed_lock_upgradable() operation.
|
||||
//!Equivalent to "return true;"
|
||||
bool timed_lock_upgradable(const boost::posix_time::ptime &)
|
||||
{ return true; }
|
||||
|
||||
//!Simulates a mutex unlock_upgradable() operation.
|
||||
//!Empty function.
|
||||
void unlock_upgradable(){}
|
||||
|
||||
//!Simulates unlock_and_lock_upgradable().
|
||||
//!Empty function.
|
||||
void unlock_and_lock_upgradable(){}
|
||||
|
||||
//!Simulates unlock_and_lock_sharable().
|
||||
//!Empty function.
|
||||
void unlock_and_lock_sharable(){}
|
||||
|
||||
//!Simulates unlock_upgradable_and_lock_sharable().
|
||||
//!Empty function.
|
||||
void unlock_upgradable_and_lock_sharable(){}
|
||||
|
||||
//Promotions
|
||||
|
||||
//!Simulates unlock_upgradable_and_lock().
|
||||
//!Empty function.
|
||||
void unlock_upgradable_and_lock(){}
|
||||
|
||||
//!Simulates try_unlock_upgradable_and_lock().
|
||||
//!Equivalent to "return true;"
|
||||
bool try_unlock_upgradable_and_lock()
|
||||
{ return true; }
|
||||
|
||||
//!Simulates timed_unlock_upgradable_and_lock().
|
||||
//!Equivalent to "return true;"
|
||||
bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &)
|
||||
{ return true; }
|
||||
|
||||
//!Simulates try_unlock_sharable_and_lock().
|
||||
//!Equivalent to "return true;"
|
||||
bool try_unlock_sharable_and_lock()
|
||||
{ return true; }
|
||||
|
||||
//!Simulates try_unlock_sharable_and_lock_upgradable().
|
||||
//!Equivalent to "return true;"
|
||||
bool try_unlock_sharable_and_lock_upgradable()
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NULL_MUTEX_HPP
|
||||
@@ -0,0 +1,196 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <pthread.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>
|
||||
#include <boost/interprocess/sync/posix/mutex.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class posix_condition
|
||||
{
|
||||
//Non-copyable
|
||||
posix_condition(const posix_condition &);
|
||||
posix_condition &operator=(const posix_condition &);
|
||||
|
||||
public:
|
||||
//!Constructs a posix_condition. On error throws interprocess_exception.
|
||||
posix_condition();
|
||||
|
||||
//!Destroys *this
|
||||
//!liberating system resources.
|
||||
~posix_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 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)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
this->do_wait(*lock.mutex());
|
||||
}
|
||||
|
||||
//!The same as:
|
||||
//!while (!pred()) wait(lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
|
||||
while (!pred())
|
||||
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,
|
||||
//!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)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
//Posix does not support infinity absolute time so handle it here
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->wait(lock);
|
||||
return true;
|
||||
}
|
||||
return this->do_timed_wait(abs_time, *lock.mutex());
|
||||
}
|
||||
|
||||
//!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)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
//Posix does not support infinity absolute time so handle it here
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->wait(lock, pred);
|
||||
return true;
|
||||
}
|
||||
while (!pred()){
|
||||
if (!this->do_timed_wait(abs_time, *lock.mutex()))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void do_wait(posix_mutex &mut);
|
||||
|
||||
bool do_timed_wait(const boost::posix_time::ptime &abs_time, posix_mutex &mut);
|
||||
|
||||
private:
|
||||
pthread_cond_t m_condition;
|
||||
};
|
||||
|
||||
inline posix_condition::posix_condition()
|
||||
{
|
||||
int res;
|
||||
pthread_condattr_t cond_attr;
|
||||
res = pthread_condattr_init(&cond_attr);
|
||||
if(res != 0){
|
||||
throw interprocess_exception("pthread_condattr_init failed");
|
||||
}
|
||||
res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
|
||||
if(res != 0){
|
||||
pthread_condattr_destroy(&cond_attr);
|
||||
throw interprocess_exception(res);
|
||||
}
|
||||
res = pthread_cond_init(&m_condition, &cond_attr);
|
||||
pthread_condattr_destroy(&cond_attr);
|
||||
if(res != 0){
|
||||
throw interprocess_exception(res);
|
||||
}
|
||||
}
|
||||
|
||||
inline posix_condition::~posix_condition()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_destroy(&m_condition);
|
||||
BOOST_ASSERT(res == 0); (void)res;
|
||||
}
|
||||
|
||||
inline void posix_condition::notify_one()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_signal(&m_condition);
|
||||
BOOST_ASSERT(res == 0); (void)res;
|
||||
}
|
||||
|
||||
inline void posix_condition::notify_all()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_broadcast(&m_condition);
|
||||
BOOST_ASSERT(res == 0); (void)res;
|
||||
}
|
||||
|
||||
inline void posix_condition::do_wait(posix_mutex &mut)
|
||||
{
|
||||
pthread_mutex_t* pmutex = &mut.m_mut;
|
||||
int res = 0;
|
||||
res = pthread_cond_wait(&m_condition, pmutex);
|
||||
BOOST_ASSERT(res == 0); (void)res;
|
||||
}
|
||||
|
||||
inline bool posix_condition::do_timed_wait
|
||||
(const boost::posix_time::ptime &abs_time, posix_mutex &mut)
|
||||
{
|
||||
timespec ts = ptime_to_timespec(abs_time);
|
||||
pthread_mutex_t* pmutex = &mut.m_mut;
|
||||
int res = 0;
|
||||
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
|
||||
BOOST_ASSERT(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
return res != ETIMEDOUT;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP
|
||||
@@ -0,0 +1,143 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <pthread.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>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
# include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
# include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
#endif
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class posix_condition;
|
||||
|
||||
class posix_mutex
|
||||
{
|
||||
posix_mutex(const posix_mutex &);
|
||||
posix_mutex &operator=(const posix_mutex &);
|
||||
public:
|
||||
|
||||
posix_mutex();
|
||||
~posix_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
|
||||
friend class posix_condition;
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_mut;
|
||||
};
|
||||
|
||||
inline posix_mutex::posix_mutex()
|
||||
{
|
||||
mutexattr_wrapper mut_attr;
|
||||
mutex_initializer mut(m_mut, mut_attr);
|
||||
mut.release();
|
||||
}
|
||||
|
||||
inline posix_mutex::~posix_mutex()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&m_mut);
|
||||
BOOST_ASSERT(res == 0);(void)res;
|
||||
}
|
||||
|
||||
inline void posix_mutex::lock()
|
||||
{
|
||||
if (pthread_mutex_lock(&m_mut) != 0)
|
||||
throw lock_exception();
|
||||
}
|
||||
|
||||
inline bool posix_mutex::try_lock()
|
||||
{
|
||||
int res = pthread_mutex_trylock(&m_mut);
|
||||
if (!(res == 0 || res == EBUSY))
|
||||
throw lock_exception();
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
//Posix does not support infinity absolute time so handle it here
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->lock();
|
||||
return true;
|
||||
}
|
||||
timespec ts = ptime_to_timespec(abs_time);
|
||||
int res = pthread_mutex_timedlock(&m_mut, &ts);
|
||||
if (res != 0 && res != ETIMEDOUT)
|
||||
throw lock_exception();
|
||||
return res == 0;
|
||||
|
||||
#else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
|
||||
return ipcdetail::try_based_timed_lock(*this, abs_time);
|
||||
|
||||
#endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
}
|
||||
|
||||
inline void posix_mutex::unlock()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_mutex_unlock(&m_mut);
|
||||
(void)res;
|
||||
BOOST_ASSERT(res == 0);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
|
||||
@@ -0,0 +1,114 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_NAMED_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/posix/named_semaphore.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class named_condition;
|
||||
|
||||
class posix_named_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
posix_named_mutex();
|
||||
posix_named_mutex(const posix_named_mutex &);
|
||||
posix_named_mutex &operator=(const posix_named_mutex &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
posix_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
|
||||
|
||||
posix_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
posix_named_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
~posix_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);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
posix_named_semaphore m_sem;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm)
|
||||
: m_sem(create_only, name, 1, perm)
|
||||
{}
|
||||
|
||||
inline posix_named_mutex::posix_named_mutex(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_sem(open_or_create, name, 1, perm)
|
||||
{}
|
||||
|
||||
inline posix_named_mutex::posix_named_mutex(open_only_t, const char *name)
|
||||
: m_sem(open_only, name)
|
||||
{}
|
||||
|
||||
inline void posix_named_mutex::dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_sem); }
|
||||
|
||||
inline posix_named_mutex::~posix_named_mutex()
|
||||
{}
|
||||
|
||||
inline void posix_named_mutex::lock()
|
||||
{ m_sem.wait(); }
|
||||
|
||||
inline void posix_named_mutex::unlock()
|
||||
{ m_sem.post(); }
|
||||
|
||||
inline bool posix_named_mutex::try_lock()
|
||||
{ return m_sem.try_wait(); }
|
||||
|
||||
inline bool posix_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_sem.timed_wait(abs_time); }
|
||||
|
||||
inline bool posix_named_mutex::remove(const char *name)
|
||||
{ return posix_named_semaphore::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
|
||||
@@ -0,0 +1,88 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_NAMED_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
class posix_named_semaphore
|
||||
{
|
||||
posix_named_semaphore();
|
||||
posix_named_semaphore(const posix_named_semaphore&);
|
||||
posix_named_semaphore &operator= (const posix_named_semaphore &);
|
||||
|
||||
public:
|
||||
posix_named_semaphore
|
||||
(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions())
|
||||
{ semaphore_open(mp_sem, DoCreate, name, initialCount, perm); }
|
||||
|
||||
posix_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions())
|
||||
{ semaphore_open(mp_sem, DoOpenOrCreate, name, initialCount, perm); }
|
||||
|
||||
posix_named_semaphore(open_only_t, const char *name)
|
||||
{ semaphore_open(mp_sem, DoOpen, name); }
|
||||
|
||||
~posix_named_semaphore()
|
||||
{
|
||||
if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED)
|
||||
semaphore_close(mp_sem);
|
||||
}
|
||||
|
||||
void post()
|
||||
{ semaphore_post(mp_sem); }
|
||||
|
||||
void wait()
|
||||
{ semaphore_wait(mp_sem); }
|
||||
|
||||
bool try_wait()
|
||||
{ return semaphore_try_wait(mp_sem); }
|
||||
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return semaphore_timed_wait(mp_sem, abs_time); }
|
||||
|
||||
static bool remove(const char *name)
|
||||
{ return semaphore_unlink(name); }
|
||||
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; }
|
||||
|
||||
sem_t *mp_sem;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_PTHREAD_HELPERS_HPP
|
||||
#define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
|
||||
|
||||
//!Makes pthread_mutexattr_t cleanup easy when using exceptions
|
||||
struct mutexattr_wrapper
|
||||
{
|
||||
//!Constructor
|
||||
mutexattr_wrapper(bool recursive = false)
|
||||
{
|
||||
if(pthread_mutexattr_init(&m_attr)!=0 ||
|
||||
pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 ||
|
||||
(recursive &&
|
||||
pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 ))
|
||||
throw interprocess_exception("pthread_mutexattr_xxxx failed");
|
||||
}
|
||||
|
||||
//!Destructor
|
||||
~mutexattr_wrapper() { pthread_mutexattr_destroy(&m_attr); }
|
||||
|
||||
//!This allows using mutexattr_wrapper as pthread_mutexattr_t
|
||||
operator pthread_mutexattr_t&() { return m_attr; }
|
||||
|
||||
pthread_mutexattr_t m_attr;
|
||||
};
|
||||
|
||||
//!Makes pthread_condattr_t cleanup easy when using exceptions
|
||||
struct condattr_wrapper
|
||||
{
|
||||
//!Constructor
|
||||
condattr_wrapper()
|
||||
{
|
||||
if(pthread_condattr_init(&m_attr)!=0 ||
|
||||
pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
|
||||
throw interprocess_exception("pthread_condattr_xxxx failed");
|
||||
}
|
||||
|
||||
//!Destructor
|
||||
~condattr_wrapper() { pthread_condattr_destroy(&m_attr); }
|
||||
|
||||
//!This allows using condattr_wrapper as pthread_condattr_t
|
||||
operator pthread_condattr_t&(){ return m_attr; }
|
||||
|
||||
pthread_condattr_t m_attr;
|
||||
};
|
||||
|
||||
//!Makes initialized pthread_mutex_t cleanup easy when using exceptions
|
||||
class mutex_initializer
|
||||
{
|
||||
public:
|
||||
//!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex
|
||||
mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr)
|
||||
: mp_mut(&mut)
|
||||
{
|
||||
if(pthread_mutex_init(mp_mut, &mut_attr) != 0)
|
||||
throw interprocess_exception("pthread_mutex_init failed");
|
||||
}
|
||||
|
||||
~mutex_initializer() { if(mp_mut) pthread_mutex_destroy(mp_mut); }
|
||||
|
||||
void release() {mp_mut = 0; }
|
||||
|
||||
private:
|
||||
pthread_mutex_t *mp_mut;
|
||||
};
|
||||
|
||||
//!Makes initialized pthread_cond_t cleanup easy when using exceptions
|
||||
class condition_initializer
|
||||
{
|
||||
public:
|
||||
condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr)
|
||||
: mp_cond(&cond)
|
||||
{
|
||||
if(pthread_cond_init(mp_cond, &cond_attr)!= 0)
|
||||
throw interprocess_exception("pthread_cond_init failed");
|
||||
}
|
||||
|
||||
~condition_initializer() { if(mp_cond) pthread_cond_destroy(mp_cond); }
|
||||
|
||||
void release() { mp_cond = 0; }
|
||||
|
||||
private:
|
||||
pthread_cond_t *mp_cond;
|
||||
};
|
||||
|
||||
#endif // #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
|
||||
|
||||
//!Makes pthread_barrierattr_t cleanup easy when using exceptions
|
||||
struct barrierattr_wrapper
|
||||
{
|
||||
//!Constructor
|
||||
barrierattr_wrapper()
|
||||
{
|
||||
if(pthread_barrierattr_init(&m_attr)!=0 ||
|
||||
pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
|
||||
throw interprocess_exception("pthread_barrierattr_xxx failed");
|
||||
}
|
||||
|
||||
//!Destructor
|
||||
~barrierattr_wrapper() { pthread_barrierattr_destroy(&m_attr); }
|
||||
|
||||
//!This allows using mutexattr_wrapper as pthread_barrierattr_t
|
||||
operator pthread_barrierattr_t&() { return m_attr; }
|
||||
|
||||
pthread_barrierattr_t m_attr;
|
||||
};
|
||||
|
||||
//!Makes initialized pthread_barrier_t cleanup easy when using exceptions
|
||||
class barrier_initializer
|
||||
{
|
||||
public:
|
||||
//!Constructor. Takes barrier attributes to initialize the barrier
|
||||
barrier_initializer(pthread_barrier_t &mut,
|
||||
pthread_barrierattr_t &mut_attr,
|
||||
int count)
|
||||
: mp_barrier(&mut)
|
||||
{
|
||||
if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0)
|
||||
throw interprocess_exception("pthread_barrier_init failed");
|
||||
}
|
||||
|
||||
~barrier_initializer() { if(mp_barrier) pthread_barrier_destroy(mp_barrier); }
|
||||
|
||||
void release() {mp_barrier = 0; }
|
||||
|
||||
private:
|
||||
pthread_barrier_t *mp_barrier;
|
||||
};
|
||||
|
||||
#endif //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
|
||||
|
||||
}//namespace ipcdetail
|
||||
|
||||
}//namespace interprocess
|
||||
|
||||
}//namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_PTIME_TO_TIMESPEC_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm)
|
||||
{
|
||||
const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
|
||||
//Avoid negative absolute times
|
||||
boost::posix_time::time_duration duration = (tm <= epoch) ? boost::posix_time::time_duration(epoch - epoch)
|
||||
: boost::posix_time::time_duration(tm - epoch);
|
||||
timespec ts;
|
||||
ts.tv_sec = duration.total_seconds();
|
||||
ts.tv_nsec = duration.total_nanoseconds() % 1000000000;
|
||||
return ts;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#endif //ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <pthread.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>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
# include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
# include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
#endif
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class posix_recursive_mutex
|
||||
{
|
||||
posix_recursive_mutex(const posix_recursive_mutex &);
|
||||
posix_recursive_mutex &operator=(const posix_recursive_mutex &);
|
||||
public:
|
||||
|
||||
posix_recursive_mutex();
|
||||
~posix_recursive_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_mut;
|
||||
};
|
||||
|
||||
inline posix_recursive_mutex::posix_recursive_mutex()
|
||||
{
|
||||
mutexattr_wrapper mut_attr(true);
|
||||
mutex_initializer mut(m_mut, mut_attr);
|
||||
mut.release();
|
||||
}
|
||||
|
||||
inline posix_recursive_mutex::~posix_recursive_mutex()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&m_mut);
|
||||
BOOST_ASSERT(res == 0);(void)res;
|
||||
}
|
||||
|
||||
inline void posix_recursive_mutex::lock()
|
||||
{
|
||||
if (pthread_mutex_lock(&m_mut) != 0)
|
||||
throw lock_exception();
|
||||
}
|
||||
|
||||
inline bool posix_recursive_mutex::try_lock()
|
||||
{
|
||||
int res = pthread_mutex_trylock(&m_mut);
|
||||
if (!(res == 0 || res == EBUSY))
|
||||
throw lock_exception();
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
//Posix does not support infinity absolute time so handle it here
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
timespec ts = ptime_to_timespec(abs_time);
|
||||
int res = pthread_mutex_timedlock(&m_mut, &ts);
|
||||
if (res != 0 && res != ETIMEDOUT)
|
||||
throw lock_exception();
|
||||
return res == 0;
|
||||
|
||||
#else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
|
||||
return ipcdetail::try_based_timed_lock(*this, abs_time);
|
||||
|
||||
#endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
}
|
||||
|
||||
inline void posix_recursive_mutex::unlock()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_mutex_unlock(&m_mut);
|
||||
BOOST_ASSERT(res == 0); (void)res;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
|
||||
@@ -0,0 +1,67 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class posix_semaphore
|
||||
{
|
||||
posix_semaphore();
|
||||
posix_semaphore(const posix_semaphore&);
|
||||
posix_semaphore &operator= (const posix_semaphore &);
|
||||
|
||||
public:
|
||||
posix_semaphore(unsigned int initialCount)
|
||||
{ semaphore_init(&m_sem, initialCount); }
|
||||
|
||||
~posix_semaphore()
|
||||
{ semaphore_destroy(&m_sem); }
|
||||
|
||||
void post()
|
||||
{ semaphore_post(&m_sem); }
|
||||
|
||||
void wait()
|
||||
{ semaphore_wait(&m_sem); }
|
||||
|
||||
bool try_wait()
|
||||
{ return semaphore_try_wait(&m_sem); }
|
||||
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return semaphore_timed_wait(&m_sem, abs_time); }
|
||||
|
||||
private:
|
||||
sem_t m_sem;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_SEMAPHORE_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/shared_dir_helpers.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
#include <fcntl.h> //O_CREAT, O_*...
|
||||
#include <unistd.h> //close
|
||||
#include <string> //std::string
|
||||
#include <semaphore.h> //sem_* family, SEM_VALUE_MAX
|
||||
#include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifdef SEM_FAILED
|
||||
#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
|
||||
#else
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
|
||||
inline bool semaphore_open
|
||||
(sem_t *&handle, create_enum_t type, const char *origname,
|
||||
unsigned int count = 0, const permissions &perm = permissions())
|
||||
{
|
||||
std::string name;
|
||||
#ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
|
||||
add_leading_slash(origname, name);
|
||||
#else
|
||||
create_shared_dir_cleaning_old_and_get_filepath(origname, name);
|
||||
#endif
|
||||
|
||||
//Create new mapping
|
||||
int oflag = 0;
|
||||
switch(type){
|
||||
case DoOpen:
|
||||
{
|
||||
//No addition
|
||||
handle = ::sem_open(name.c_str(), oflag);
|
||||
}
|
||||
break;
|
||||
case DoOpenOrCreate:
|
||||
case DoCreate:
|
||||
{
|
||||
while(1){
|
||||
oflag = (O_CREAT | O_EXCL);
|
||||
handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count);
|
||||
if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
|
||||
//We can't change semaphore permissions!
|
||||
//::fchmod(handle, perm.get_permissions());
|
||||
break;
|
||||
}
|
||||
else if(errno == EEXIST && type == DoOpenOrCreate){
|
||||
oflag = 0;
|
||||
if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
|
||||
|| (errno != ENOENT) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err(other_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Check for error
|
||||
if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
|
||||
throw interprocess_exception(error_info(errno));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void semaphore_close(sem_t *handle)
|
||||
{
|
||||
int ret = sem_close(handle);
|
||||
if(ret != 0){
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool semaphore_unlink(const char *semname)
|
||||
{
|
||||
try{
|
||||
std::string sem_str;
|
||||
#ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
|
||||
add_leading_slash(semname, sem_str);
|
||||
#else
|
||||
shared_filepath(semname, sem_str);
|
||||
#endif
|
||||
return 0 == sem_unlink(sem_str.c_str());
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
|
||||
|
||||
inline void semaphore_init(sem_t *handle, unsigned int initialCount)
|
||||
{
|
||||
int ret = sem_init(handle, 1, initialCount);
|
||||
//According to SUSV3 version 2003 edition, the return value of a successful
|
||||
//sem_init call is not defined, but -1 is returned on failure.
|
||||
//In the future, a successful call might be required to return 0.
|
||||
if(ret == -1){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void semaphore_destroy(sem_t *handle)
|
||||
{
|
||||
int ret = sem_destroy(handle);
|
||||
if(ret != 0){
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
|
||||
|
||||
inline void semaphore_post(sem_t *handle)
|
||||
{
|
||||
int ret = sem_post(handle);
|
||||
if(ret != 0){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void semaphore_wait(sem_t *handle)
|
||||
{
|
||||
int ret = sem_wait(handle);
|
||||
if(ret != 0){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool semaphore_try_wait(sem_t *handle)
|
||||
{
|
||||
int res = sem_trywait(handle);
|
||||
if(res == 0)
|
||||
return true;
|
||||
if(system_error_code() == EAGAIN){
|
||||
return false;
|
||||
}
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
|
||||
struct semaphore_wrapper_try_wrapper
|
||||
{
|
||||
explicit semaphore_wrapper_try_wrapper(sem_t *handle)
|
||||
: m_handle(handle)
|
||||
{}
|
||||
|
||||
void wait()
|
||||
{ semaphore_wait(m_handle); }
|
||||
|
||||
bool try_wait()
|
||||
{ return semaphore_try_wait(m_handle); }
|
||||
|
||||
private:
|
||||
sem_t *m_handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
//Posix does not support infinity absolute time so handle it here
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
semaphore_wait(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
timespec tspec = ptime_to_timespec(abs_time);
|
||||
for (;;){
|
||||
int res = sem_timedwait(handle, &tspec);
|
||||
if(res == 0)
|
||||
return true;
|
||||
if (res > 0){
|
||||
//buggy glibc, copy the returned error code to errno
|
||||
errno = res;
|
||||
}
|
||||
if(system_error_code() == ETIMEDOUT){
|
||||
return false;
|
||||
}
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
return false;
|
||||
#else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
|
||||
semaphore_wrapper_try_wrapper swtw(handle);
|
||||
ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
|
||||
return ipcdetail::try_based_timed_lock(lw, abs_time);
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
|
||||
@@ -0,0 +1,377 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This interface is inspired by Howard Hinnant's lock proposal.
|
||||
// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_SCOPED_LOCK_HPP
|
||||
#define BOOST_INTERPROCESS_SCOPED_LOCK_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/sync/lock_options.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/simple_swap.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes the scoped_lock class.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
//!scoped_lock is meant to carry out the tasks for locking, unlocking, try-locking
|
||||
//!and timed-locking (recursive or not) for the Mutex. The Mutex need not supply all
|
||||
//!of this functionality. If the client of scoped_lock<Mutex> does not use
|
||||
//!functionality which the Mutex does not supply, no harm is done. Mutex ownership
|
||||
//!transfer is supported through the syntax of move semantics. Ownership transfer
|
||||
//!is allowed both by construction and assignment. The scoped_lock does not support
|
||||
//!copy semantics. A compile time error results if copy construction or copy
|
||||
//!assignment is attempted. Mutex ownership can also be moved from an
|
||||
//!upgradable_lock and sharable_lock via constructor. In this role, scoped_lock
|
||||
//!shares the same functionality as a write_lock.
|
||||
template <class Mutex>
|
||||
class scoped_lock
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
typedef scoped_lock<Mutex> this_type;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_lock)
|
||||
typedef bool this_type::*unspecified_bool_type;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
//!Effects: Default constructs a scoped_lock.
|
||||
//!Postconditions: owns() == false and mutex() == 0.
|
||||
scoped_lock()
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{}
|
||||
|
||||
//!Effects: m.lock().
|
||||
//!Postconditions: owns() == true and mutex() == &m.
|
||||
//!Notes: The constructor will take ownership of the mutex. If another thread
|
||||
//! already owns the mutex, this thread will block until the mutex is released.
|
||||
//! Whether or not this constructor handles recursive locking depends upon the mutex.
|
||||
explicit scoped_lock(mutex_type& m)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ mp_mutex->lock(); m_locked = true; }
|
||||
|
||||
//!Postconditions: owns() == false, and mutex() == &m.
|
||||
//!Notes: The constructor will not take ownership of the mutex. There is no effect
|
||||
//! required on the referenced mutex.
|
||||
scoped_lock(mutex_type& m, defer_lock_type)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{}
|
||||
|
||||
//!Postconditions: owns() == true, and mutex() == &m.
|
||||
//!Notes: The constructor will suppose that the mutex is already locked. There
|
||||
//! is no effect required on the referenced mutex.
|
||||
scoped_lock(mutex_type& m, accept_ownership_type)
|
||||
: mp_mutex(&m), m_locked(true)
|
||||
{}
|
||||
|
||||
//!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
|
||||
//! so without waiting. Whether or not this constructor handles recursive
|
||||
//! locking depends upon the mutex. If the mutex_type does not support try_lock,
|
||||
//! this constructor will fail at compile time if instantiated, but otherwise
|
||||
//! have no effect.
|
||||
scoped_lock(mutex_type& m, try_to_lock_type)
|
||||
: mp_mutex(&m), m_locked(mp_mutex->try_lock())
|
||||
{}
|
||||
|
||||
//!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
|
||||
//! it until abs_time is reached. Whether or not this constructor
|
||||
//! handles recursive locking depends upon the mutex. If the mutex_type
|
||||
//! does not support try_lock, this constructor will fail at compile
|
||||
//! time if instantiated, but otherwise have no effect.
|
||||
scoped_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
|
||||
: mp_mutex(&m), m_locked(mp_mutex->timed_lock(abs_time))
|
||||
{}
|
||||
|
||||
//!Postconditions: mutex() == the value scop.mutex() had before the
|
||||
//! constructor executes. s1.mutex() == 0. owns() == the value of
|
||||
//! scop.owns() before the constructor executes. scop.owns().
|
||||
//!Notes: If the scop scoped_lock owns the mutex, ownership is moved
|
||||
//! to thisscoped_lock with no blocking. If the scop scoped_lock does not
|
||||
//! own the mutex, then neither will this scoped_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);". This
|
||||
//! constructor does not alter the state of the mutex, only potentially
|
||||
//! who owns it.
|
||||
scoped_lock(BOOST_RV_REF(scoped_lock) scop)
|
||||
: mp_mutex(0), m_locked(scop.owns())
|
||||
{ mp_mutex = scop.release(); }
|
||||
|
||||
//!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the
|
||||
//! 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.
|
||||
//!Notes: If upgr is locked, this constructor will lock this scoped_lock while
|
||||
//! unlocking upgr. If upgr is unlocked, then this scoped_lock will be
|
||||
//! unlocked as well. Only a moved upgradable_lock's will match this
|
||||
//! signature. An non-moved upgradable_lock can be moved with
|
||||
//! the expression: "boost::move(lock);" This constructor may block if
|
||||
//! other threads hold a sharable_lock on this mutex (sharable_lock's can
|
||||
//! share ownership with an upgradable_lock).
|
||||
template<class T>
|
||||
explicit scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
upgradable_lock<mutex_type> &u_lock = upgr;
|
||||
if(u_lock.owns()){
|
||||
u_lock.mutex()->unlock_upgradable_and_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
mp_mutex = u_lock.release();
|
||||
}
|
||||
|
||||
//!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.
|
||||
//! 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.
|
||||
//! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release()
|
||||
//! 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 merely changes type to an unlocked "write lock".
|
||||
//! If the "read lock" is held, then mutex transfer occurs only if it can
|
||||
//! do so in a non-blocking manner.
|
||||
template<class T>
|
||||
scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, try_to_lock_type
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
upgradable_lock<mutex_type> &u_lock = upgr;
|
||||
if(u_lock.owns()){
|
||||
if((m_locked = u_lock.mutex()->try_unlock_upgradable_and_lock()) == true){
|
||||
mp_mutex = u_lock.release();
|
||||
}
|
||||
}
|
||||
else{
|
||||
u_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
//!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.
|
||||
//! 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
|
||||
//!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
|
||||
//! merely changes type to an unlocked "write lock". If the "read lock" is held,
|
||||
//! then mutex transfer occurs only if it can do so in a non-blocking manner.
|
||||
template<class T>
|
||||
scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, boost::posix_time::ptime &abs_time
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
upgradable_lock<mutex_type> &u_lock = upgr;
|
||||
if(u_lock.owns()){
|
||||
if((m_locked = u_lock.mutex()->timed_unlock_upgradable_and_lock(abs_time)) == true){
|
||||
mp_mutex = u_lock.release();
|
||||
}
|
||||
}
|
||||
else{
|
||||
u_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
//!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the
|
||||
//!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.
|
||||
//! 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.
|
||||
//! 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
|
||||
//! 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
|
||||
//! first place, the mutex merely changes type to an unlocked "write lock".
|
||||
//! If the "read lock" is held, then mutex transfer occurs only if it can
|
||||
//! do so in a non-blocking manner.
|
||||
template<class T>
|
||||
scoped_lock(BOOST_RV_REF(sharable_lock<T>) shar, try_to_lock_type
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
sharable_lock<mutex_type> &s_lock = shar;
|
||||
if(s_lock.owns()){
|
||||
if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock()) == true){
|
||||
mp_mutex = s_lock.release();
|
||||
}
|
||||
}
|
||||
else{
|
||||
s_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
//!Effects: if (owns()) mp_mutex->unlock().
|
||||
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
|
||||
~scoped_lock()
|
||||
{
|
||||
try{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
|
||||
catch(...){}
|
||||
}
|
||||
|
||||
//!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.
|
||||
//!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();
|
||||
mp_mutex = scop.release();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! exception. Calls lock() on the referenced mutex.
|
||||
//!Postconditions: owns() == true.
|
||||
//!Notes: The scoped_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();
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! 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
|
||||
//! mutex_type does not support try_lock(), 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();
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! exception. Calls timed_lock(abs_time) on the referenced mutex.
|
||||
//!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
|
||||
//!Notes: The scoped_lock changes from a state of not owning the mutex, to
|
||||
//! owning the mutex, but only if it can obtain ownership by the specified
|
||||
//! time. If the mutex_type does not support timed_lock (), 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(abs_time);
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
|
||||
//! exception. Calls unlock() on the referenced mutex.
|
||||
//!Postconditions: owns() == false.
|
||||
//!Notes: The scoped_lock changes from a state of owning the mutex, to not
|
||||
//! owning the mutex.*/
|
||||
void unlock()
|
||||
{
|
||||
if(!mp_mutex || !m_locked)
|
||||
throw lock_exception();
|
||||
mp_mutex->unlock();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
//!Effects: Returns true if this scoped_lock has acquired
|
||||
//!the referenced mutex.
|
||||
bool owns() const
|
||||
{ return m_locked && mp_mutex; }
|
||||
|
||||
//!Conversion to bool.
|
||||
//!Returns owns().
|
||||
operator unspecified_bool_type() const
|
||||
{ return m_locked? &this_type::m_locked : 0; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if
|
||||
//!there is no mutex to reference.
|
||||
mutex_type* mutex() const
|
||||
{ return mp_mutex; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
|
||||
//! mutex to reference.
|
||||
//!Postconditions: mutex() == 0 and owns() == false.
|
||||
mutex_type* release()
|
||||
{
|
||||
mutex_type *mut = mp_mutex;
|
||||
mp_mutex = 0;
|
||||
m_locked = false;
|
||||
return mut;
|
||||
}
|
||||
|
||||
//!Effects: Swaps state with moved lock.
|
||||
//!Throws: Nothing.
|
||||
void swap( scoped_lock<mutex_type> &other)
|
||||
{
|
||||
(simple_swap)(mp_mutex, other.mp_mutex);
|
||||
(simple_swap)(m_locked, other.m_locked);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
mutex_type *mp_mutex;
|
||||
bool m_locked;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_SCOPED_LOCK_HPP
|
||||
@@ -0,0 +1,310 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This interface is inspired by Howard Hinnant's lock proposal.
|
||||
// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
|
||||
#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/sync/lock_options.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/simple_swap.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes the upgradable_lock class that serves to acquire the upgradable
|
||||
//!lock of a mutex.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
//!sharable_lock is meant to carry out the tasks for sharable-locking
|
||||
//!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking
|
||||
//!(recursive or not) for the Mutex. The Mutex need not supply all of this
|
||||
//!functionality. If the client of sharable_lock<Mutex> does not use functionality which
|
||||
//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among
|
||||
//!sharable_locks, and a single upgradable_lock. sharable_lock does not support
|
||||
//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock,
|
||||
//!upgradable_lock and scoped_lock via transfer_lock syntax.*/
|
||||
template <class SharableMutex>
|
||||
class sharable_lock
|
||||
{
|
||||
public:
|
||||
typedef SharableMutex mutex_type;
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
typedef sharable_lock<SharableMutex> this_type;
|
||||
explicit sharable_lock(scoped_lock<mutex_type>&);
|
||||
typedef bool this_type::*unspecified_bool_type;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock)
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Effects: Default constructs a sharable_lock.
|
||||
//!Postconditions: owns() == false and mutex() == 0.
|
||||
sharable_lock()
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{}
|
||||
|
||||
//!Effects: m.lock_sharable().
|
||||
//!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.
|
||||
//! If another thread owns the mutex with sharable or upgradable ownership,
|
||||
//! then no blocking will occur. Whether or not this constructor handles
|
||||
//! recursive locking depends upon the mutex.
|
||||
explicit sharable_lock(mutex_type& m)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ mp_mutex->lock_sharable(); m_locked = true; }
|
||||
|
||||
//!Postconditions: owns() == false, and mutex() == &m.
|
||||
//!Notes: The constructor will not take ownership of the mutex. There is no effect
|
||||
//! required on the referenced mutex.
|
||||
sharable_lock(mutex_type& m, defer_lock_type)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{}
|
||||
|
||||
//!Postconditions: owns() == true, and mutex() == &m.
|
||||
//!Notes: The constructor will suppose that the mutex is already sharable
|
||||
//! locked. There is no effect required on the referenced mutex.
|
||||
sharable_lock(mutex_type& m, accept_ownership_type)
|
||||
: mp_mutex(&m), m_locked(true)
|
||||
{}
|
||||
|
||||
//!Effects: m.try_lock_sharable()
|
||||
//!Postconditions: mutex() == &m. owns() == the return value of the
|
||||
//! m.try_lock_sharable() executed within the constructor.
|
||||
//!Notes: The constructor will take sharable-ownership of the mutex if it
|
||||
//! can do so without waiting. Whether or not this constructor handles
|
||||
//! recursive locking depends upon the mutex. If the mutex_type does not
|
||||
//! support try_lock_sharable, this constructor will fail at compile
|
||||
//! time if instantiated, but otherwise have no effect.
|
||||
sharable_lock(mutex_type& m, try_to_lock_type)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ m_locked = mp_mutex->try_lock_sharable(); }
|
||||
|
||||
//!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
|
||||
//! can do so within the time specified. Whether or not this constructor
|
||||
//! handles recursive locking depends upon the mutex. If the mutex_type
|
||||
//! does not support timed_lock_sharable, this constructor will fail at
|
||||
//! compile time if instantiated, but otherwise have no effect.
|
||||
sharable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ m_locked = mp_mutex->timed_lock_sharable(abs_time); }
|
||||
|
||||
//!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns()
|
||||
//! before the construction. upgr.owns() == false after the construction.
|
||||
//!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this
|
||||
//! sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then
|
||||
//! neither will this sharable_lock. Only a moved sharable_lock's will match this
|
||||
//! signature. An non-moved sharable_lock can be moved with the expression:
|
||||
//! "boost::move(lock);". This constructor does not alter the state of the mutex,
|
||||
//! only potentially who owns it.
|
||||
sharable_lock(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
|
||||
: mp_mutex(0), m_locked(upgr.owns())
|
||||
{ mp_mutex = upgr.release(); }
|
||||
|
||||
//!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the
|
||||
//! 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.
|
||||
//!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:
|
||||
//! "boost::move(lock);".*/
|
||||
template<class T>
|
||||
sharable_lock(BOOST_RV_REF(upgradable_lock<T>) upgr
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
upgradable_lock<mutex_type> &u_lock = upgr;
|
||||
if(u_lock.owns()){
|
||||
u_lock.mutex()->unlock_upgradable_and_lock_sharable();
|
||||
m_locked = true;
|
||||
}
|
||||
mp_mutex = u_lock.release();
|
||||
}
|
||||
|
||||
//!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the
|
||||
//! referenced mutex.
|
||||
//!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.
|
||||
//!Notes: If scop is locked, this constructor will transfer the exclusive ownership
|
||||
//! 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);".
|
||||
template<class T>
|
||||
sharable_lock(BOOST_RV_REF(scoped_lock<T>) scop
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
scoped_lock<mutex_type> &e_lock = scop;
|
||||
if(e_lock.owns()){
|
||||
e_lock.mutex()->unlock_and_lock_sharable();
|
||||
m_locked = true;
|
||||
}
|
||||
mp_mutex = e_lock.release();
|
||||
}
|
||||
|
||||
//!Effects: if (owns()) mp_mutex->unlock_sharable().
|
||||
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.
|
||||
~sharable_lock()
|
||||
{
|
||||
try{
|
||||
if(m_locked && mp_mutex) mp_mutex->unlock_sharable();
|
||||
}
|
||||
catch(...){}
|
||||
}
|
||||
|
||||
//!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.
|
||||
//!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();
|
||||
mp_mutex = upgr.release();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
|
||||
//! exception. Calls lock_sharable() on the referenced mutex.
|
||||
//!Postconditions: owns() == true.
|
||||
//!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();
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
|
||||
//! exception. Calls try_lock_sharable() on the referenced mutex.
|
||||
//!Postconditions: owns() == the value returned from
|
||||
//! mutex()->try_lock_sharable().
|
||||
//!Notes: The sharable_lock changes from a state of not owning the mutex,
|
||||
//! to owning the mutex, but only if blocking was not required. If the
|
||||
//! 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();
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
|
||||
//! exception. Calls timed_lock_sharable(abs_time) on the referenced mutex.
|
||||
//!Postconditions: owns() == the value returned from
|
||||
//! mutex()->timed_lock_sharable(elps_time).
|
||||
//!Notes: The sharable_lock changes from a state of not owning the mutex,
|
||||
//! to owning the mutex, but only if it can obtain ownership within the
|
||||
//! specified time interval. If the mutex_type does not support
|
||||
//! 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);
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception.
|
||||
//! Calls unlock_sharable() on the referenced mutex.
|
||||
//!Postconditions: owns() == false.
|
||||
//!Notes: The sharable_lock changes from a state of owning the mutex, to
|
||||
//! not owning the mutex.
|
||||
void unlock()
|
||||
{
|
||||
if(!mp_mutex || !m_locked)
|
||||
throw lock_exception();
|
||||
mp_mutex->unlock_sharable();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
//!Effects: Returns true if this scoped_lock has
|
||||
//!acquired the referenced mutex.
|
||||
bool owns() const
|
||||
{ return m_locked && mp_mutex; }
|
||||
|
||||
//!Conversion to bool.
|
||||
//!Returns owns().
|
||||
operator unspecified_bool_type() const
|
||||
{ return m_locked? &this_type::m_locked : 0; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if
|
||||
//!there is no mutex to reference.
|
||||
mutex_type* mutex() const
|
||||
{ return mp_mutex; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
|
||||
//! mutex to reference.
|
||||
//!Postconditions: mutex() == 0 and owns() == false.
|
||||
mutex_type* release()
|
||||
{
|
||||
mutex_type *mut = mp_mutex;
|
||||
mp_mutex = 0;
|
||||
m_locked = false;
|
||||
return mut;
|
||||
}
|
||||
|
||||
//!Effects: Swaps state with moved lock.
|
||||
//!Throws: Nothing.
|
||||
void swap(sharable_lock<mutex_type> &other)
|
||||
{
|
||||
(simple_swap)(mp_mutex, other.mp_mutex);
|
||||
(simple_swap)(m_locked, other.m_locked);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
mutex_type *mp_mutex;
|
||||
bool m_locked;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
|
||||
@@ -0,0 +1,239 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHM_NAMED_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#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)
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
|
||||
#else
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes process-shared variables interprocess_condition class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
class interprocess_tester;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//! A global condition variable that can be created by name.
|
||||
//! This condition variable is designed to work with named_mutex and
|
||||
//! can't be placed in shared memory or memory mapped files.
|
||||
class shm_named_condition
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
shm_named_condition();
|
||||
shm_named_condition(const shm_named_condition &);
|
||||
shm_named_condition &operator=(const shm_named_condition &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Creates a global condition with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!shm_named_condition(open_only_t, ... )
|
||||
//!Does not throw
|
||||
shm_named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global condition with a name if that condition is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
shm_named_condition(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~shm_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);
|
||||
|
||||
//!Erases a named condition from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
|
||||
class internal_condition_members
|
||||
{
|
||||
public:
|
||||
typedef interprocess_mutex mutex_type;
|
||||
typedef interprocess_condition condvar_type;
|
||||
|
||||
condvar_type& get_condvar() { return m_cond; }
|
||||
mutex_type& get_mutex() { return m_mtx; }
|
||||
|
||||
private:
|
||||
mutex_type m_mtx;
|
||||
condvar_type m_cond;
|
||||
};
|
||||
|
||||
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
|
||||
#else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
|
||||
typedef interprocess_condition internal_condition;
|
||||
#endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
|
||||
|
||||
internal_condition &internal_cond()
|
||||
{ return *static_cast<internal_condition*>(m_shmem.get_user_address()); }
|
||||
|
||||
friend class boost::interprocess::ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
|
||||
template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor;
|
||||
typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline shm_named_condition::~shm_named_condition()
|
||||
{}
|
||||
|
||||
inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(internal_condition) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(internal_condition) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_condition::shm_named_condition(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpen))
|
||||
{}
|
||||
|
||||
inline void shm_named_condition::dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline void shm_named_condition::notify_one()
|
||||
{ this->internal_cond().notify_one(); }
|
||||
|
||||
inline void shm_named_condition::notify_all()
|
||||
{ this->internal_cond().notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
inline void shm_named_condition::wait(L& lock)
|
||||
{ this->internal_cond().wait(lock); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
inline void shm_named_condition::wait(L& lock, Pr pred)
|
||||
{ this->internal_cond().wait(lock, pred); }
|
||||
|
||||
template <typename L>
|
||||
inline bool shm_named_condition::timed_wait
|
||||
(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{ return this->internal_cond().timed_wait(lock, abs_time); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
inline bool shm_named_condition::timed_wait
|
||||
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
|
||||
|
||||
inline bool shm_named_condition::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHM_NAMED_CONDITION_ANY_HPP
|
||||
#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes process-shared variables interprocess_condition class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
class interprocess_tester;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//! A global condition variable that can be created by name.
|
||||
//! This condition variable is designed to work with named_mutex and
|
||||
//! can't be placed in shared memory or memory mapped files.
|
||||
class shm_named_condition_any
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
shm_named_condition_any();
|
||||
shm_named_condition_any(const shm_named_condition_any &);
|
||||
shm_named_condition_any &operator=(const shm_named_condition_any &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
//!Creates a global condition with a name.
|
||||
//!If the condition can't be created throws interprocess_exception
|
||||
shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions())
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(internal_condition) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
//!Opens or creates a global condition with a name.
|
||||
//!If the condition is created, this call is equivalent to
|
||||
//!shm_named_condition_any(create_only_t, ... )
|
||||
//!If the condition is already created, this call is equivalent
|
||||
//!shm_named_condition_any(open_only_t, ... )
|
||||
//!Does not throw
|
||||
shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions())
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(internal_condition) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
//!Opens a global condition with a name if that condition is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
shm_named_condition_any(open_only_t open_only, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpen))
|
||||
{}
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~shm_named_condition_any()
|
||||
{}
|
||||
|
||||
//!If there is a thread waiting on *this, change that
|
||||
//!thread's state to ready. Otherwise there is no effect.*/
|
||||
void notify_one()
|
||||
{ m_cond.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()
|
||||
{ m_cond.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)
|
||||
{ m_cond.wait(lock); }
|
||||
|
||||
//!The same as:
|
||||
//!while (!pred()) wait(lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{ m_cond.wait(lock, 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)
|
||||
{ return m_cond.timed_wait(lock, 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)
|
||||
{ return m_cond.timed_wait(lock, abs_time, pred); }
|
||||
|
||||
//!Erases a named condition from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
|
||||
class internal_condition_members
|
||||
{
|
||||
public:
|
||||
typedef interprocess_mutex mutex_type;
|
||||
typedef interprocess_condition condvar_type;
|
||||
|
||||
condvar_type& get_condvar() { return m_cond; }
|
||||
mutex_type& get_mutex() { return m_mtx; }
|
||||
|
||||
private:
|
||||
mutex_type m_mtx;
|
||||
condvar_type m_cond;
|
||||
};
|
||||
|
||||
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
|
||||
|
||||
internal_condition m_cond;
|
||||
|
||||
friend class boost::interprocess::ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
|
||||
template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor;
|
||||
typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-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_SYNC_NAMED_CREATION_FUNCTOR_HPP
|
||||
#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct named_creation_functor_no_arg{};
|
||||
|
||||
template <class T, class Arg = named_creation_functor_no_arg>
|
||||
class named_creation_functor
|
||||
{
|
||||
typedef named_creation_functor_no_arg no_arg_t;
|
||||
public:
|
||||
named_creation_functor(create_enum_t type, Arg arg = Arg())
|
||||
: m_creation_type(type), m_arg(arg){}
|
||||
|
||||
template<class ArgType>
|
||||
void construct(void *address, typename enable_if_c<is_same<ArgType, no_arg_t>::value>::type * = 0) const
|
||||
{ ::new(address, boost_container_new_t())T; }
|
||||
|
||||
template<class ArgType>
|
||||
void construct(void *address, typename enable_if_c<!is_same<ArgType, no_arg_t>::value>::type * = 0) const
|
||||
{ ::new(address, boost_container_new_t())T(m_arg); }
|
||||
|
||||
bool operator()(void *address, std::size_t, bool created) const
|
||||
{
|
||||
switch(m_creation_type){
|
||||
case DoOpen:
|
||||
return true;
|
||||
break;
|
||||
case DoCreate:
|
||||
case DoOpenOrCreate:
|
||||
if(created){
|
||||
construct<Arg>(address);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static std::size_t get_min_size()
|
||||
{ return sizeof(T); }
|
||||
|
||||
private:
|
||||
create_enum_t m_creation_type;
|
||||
Arg m_arg;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
|
||||
@@ -0,0 +1,181 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHM_NAMED_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
shm_named_mutex();
|
||||
shm_named_mutex(const shm_named_mutex &);
|
||||
shm_named_mutex &operator=(const shm_named_mutex &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Creates a global interprocess_mutex with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!shm_named_mutex(open_only_t, ... )
|
||||
//!Does not throw
|
||||
shm_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global mutex with a name if that mutex is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
shm_named_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~shm_named_mutex();
|
||||
|
||||
//!Unlocks a previously locked
|
||||
//!interprocess_mutex.
|
||||
void unlock();
|
||||
|
||||
//!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
void lock();
|
||||
|
||||
//!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();
|
||||
|
||||
//!Tries to lock the interprocess_mutex until time abs_time,
|
||||
//!Returns false when timeout expires, returns true when locks.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Erases a named mutex from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
typedef interprocess_mutex internal_mutex_type;
|
||||
interprocess_mutex &internal_mutex()
|
||||
{ return *static_cast<interprocess_mutex*>(m_shmem.get_user_address()); }
|
||||
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef ipcdetail::named_creation_functor<interprocess_mutex> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline void shm_named_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline shm_named_mutex::~shm_named_mutex()
|
||||
{}
|
||||
|
||||
inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
inline void shm_named_mutex::lock()
|
||||
{ this->internal_mutex().lock(); }
|
||||
|
||||
inline void shm_named_mutex::unlock()
|
||||
{ this->internal_mutex().unlock(); }
|
||||
|
||||
inline bool shm_named_mutex::try_lock()
|
||||
{ return this->internal_mutex().try_lock(); }
|
||||
|
||||
inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->internal_mutex().timed_lock(abs_time); }
|
||||
|
||||
inline bool shm_named_mutex::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHM_NAMED_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shm_named_recursive_mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
class interprocess_tester;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
class shm_named_recursive_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
shm_named_recursive_mutex();
|
||||
shm_named_recursive_mutex(const shm_named_recursive_mutex &);
|
||||
shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Creates a global recursive_mutex with a name.
|
||||
//!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.
|
||||
//!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
|
||||
//!shm_named_recursive_mutex(open_only_t, ... )
|
||||
//!Does not throw
|
||||
shm_named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
shm_named_recursive_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~shm_named_recursive_mutex();
|
||||
|
||||
//!Unlocks a previously locked
|
||||
//!shm_named_recursive_mutex.
|
||||
void unlock();
|
||||
|
||||
//!Locks shm_named_recursive_mutex, sleeps when shm_named_recursive_mutex is already locked.
|
||||
//!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
|
||||
//!is already locked, returns true when success.
|
||||
//!Throws interprocess_exception if a severe error is found.
|
||||
bool try_lock();
|
||||
|
||||
//!Tries to lock the shm_named_recursive_mutex until time abs_time,
|
||||
//!Returns false when timeout expires, returns true when locks.
|
||||
//!Throws interprocess_exception if a severe error is found
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Erases a named recursive mutex
|
||||
//!from the system
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
interprocess_recursive_mutex *mutex() const
|
||||
{ return static_cast<interprocess_recursive_mutex*>(m_shmem.get_user_address()); }
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef named_creation_functor<interprocess_recursive_mutex> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
inline shm_named_recursive_mutex::~shm_named_recursive_mutex()
|
||||
{}
|
||||
|
||||
inline void shm_named_recursive_mutex::dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_recursive_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_recursive_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpen))
|
||||
{}
|
||||
|
||||
inline void shm_named_recursive_mutex::lock()
|
||||
{ this->mutex()->lock(); }
|
||||
|
||||
inline void shm_named_recursive_mutex::unlock()
|
||||
{ this->mutex()->unlock(); }
|
||||
|
||||
inline bool shm_named_recursive_mutex::try_lock()
|
||||
{ return this->mutex()->try_lock(); }
|
||||
|
||||
inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock(abs_time); }
|
||||
|
||||
inline bool shm_named_recursive_mutex::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
|
||||
@@ -0,0 +1,138 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SHM_NAMED_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.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/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class shm_named_semaphore
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
shm_named_semaphore();
|
||||
shm_named_semaphore(const shm_named_semaphore &);
|
||||
shm_named_semaphore &operator=(const shm_named_semaphore &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
|
||||
|
||||
shm_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
|
||||
|
||||
shm_named_semaphore(open_only_t, const char *name);
|
||||
|
||||
~shm_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);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
interprocess_semaphore *semaphore() const
|
||||
{ return static_cast<interprocess_semaphore*>(m_shmem.get_user_address()); }
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef named_creation_functor<interprocess_semaphore, int> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
inline shm_named_semaphore::~shm_named_semaphore()
|
||||
{}
|
||||
|
||||
inline void shm_named_semaphore::dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline shm_named_semaphore::shm_named_semaphore
|
||||
(create_only_t, const char *name, unsigned int initialCount, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_semaphore) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoCreate, initialCount)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_semaphore::shm_named_semaphore
|
||||
(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_semaphore) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpenOrCreate, initialCount)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline shm_named_semaphore::shm_named_semaphore
|
||||
(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(DoOpen, 0))
|
||||
{}
|
||||
|
||||
inline void shm_named_semaphore::post()
|
||||
{ semaphore()->post(); }
|
||||
|
||||
inline void shm_named_semaphore::wait()
|
||||
{ semaphore()->wait(); }
|
||||
|
||||
inline bool shm_named_semaphore::try_wait()
|
||||
{ return semaphore()->try_wait(); }
|
||||
|
||||
inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return semaphore()->timed_wait(abs_time); }
|
||||
|
||||
inline bool shm_named_semaphore::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_UPGRADABLE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/exceptions.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named upgradable mutex class for inter-process synchronization
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
class named_condition;
|
||||
|
||||
//!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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
//Non-copyable
|
||||
named_upgradable_mutex();
|
||||
named_upgradable_mutex(const named_upgradable_mutex &);
|
||||
named_upgradable_mutex &operator=(const named_upgradable_mutex &);
|
||||
friend class named_condition;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!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.
|
||||
//!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
|
||||
//!named_upgradable_mutex(open_only_t, ... ).
|
||||
named_upgradable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
|
||||
|
||||
//!Opens a global upgradable mutex with a name if that upgradable mutex
|
||||
//!is previously.
|
||||
//!created. If it is not previously created this function throws
|
||||
//!interprocess_exception.
|
||||
named_upgradable_mutex(open_only_t open_only, const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~named_upgradable_mutex();
|
||||
|
||||
//Exclusive locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
|
||||
//! and if another thread has exclusive, sharable or upgradable ownership of
|
||||
//! the mutex, it waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock();
|
||||
|
||||
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
|
||||
//! without waiting. If no other thread has exclusive, sharable or upgradable
|
||||
//! ownership of the mutex this succeeds.
|
||||
//!Returns: If it can acquire exclusive ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
//Sharable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
|
||||
//! and if another thread has exclusive ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire sharable ownership immediately returns true. If it
|
||||
//! 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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_sharable();
|
||||
|
||||
//Upgradable locking
|
||||
|
||||
//!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
|
||||
//! and if another thread has exclusive or upgradable ownership of the mutex,
|
||||
//! waits until it can obtain the ownership.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Returns: If it can acquire upgradable ownership immediately returns true.
|
||||
//! If it has to wait, returns false.
|
||||
//!Throws: interprocess_exception on error.
|
||||
bool try_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_upgradable();
|
||||
|
||||
//Demotions
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_upgradable();
|
||||
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
void unlock_and_lock_sharable();
|
||||
|
||||
//!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.
|
||||
//!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.
|
||||
//!Effects: The thread atomically releases upgradable ownership and acquires
|
||||
//! exclusive ownership. This operation will block until all threads with
|
||||
//! 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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!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.
|
||||
//!Throws: An exception derived from interprocess_exception on error.
|
||||
bool try_unlock_sharable_and_lock();
|
||||
|
||||
bool try_unlock_sharable_and_lock_upgradable();
|
||||
|
||||
//!Erases a named upgradable mutex from the system.
|
||||
//!Returns false on error. Never throws.
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
|
||||
interprocess_upgradable_mutex *mutex() const
|
||||
{ return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
|
||||
|
||||
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
|
||||
open_create_impl_t m_shmem;
|
||||
typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
inline named_upgradable_mutex::~named_upgradable_mutex()
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(create_only_t, const char *name, const permissions &perm)
|
||||
: m_shmem (create_only
|
||||
,name
|
||||
,sizeof(interprocess_upgradable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_shmem (open_or_create
|
||||
,name
|
||||
,sizeof(interprocess_upgradable_mutex) +
|
||||
open_create_impl_t::ManagedOpenOrCreateUserOffset
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpenOrCreate)
|
||||
,perm)
|
||||
{}
|
||||
|
||||
inline named_upgradable_mutex::named_upgradable_mutex
|
||||
(open_only_t, const char *name)
|
||||
: m_shmem (open_only
|
||||
,name
|
||||
,read_write
|
||||
,0
|
||||
,construct_func_t(ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
inline void named_upgradable_mutex::dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
|
||||
|
||||
inline void named_upgradable_mutex::lock()
|
||||
{ this->mutex()->lock(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock()
|
||||
{ this->mutex()->unlock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock()
|
||||
{ return this->mutex()->try_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::lock_upgradable()
|
||||
{ this->mutex()->lock_upgradable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable()
|
||||
{ this->mutex()->unlock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock_upgradable()
|
||||
{ return this->mutex()->try_lock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock_upgradable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock_upgradable(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::lock_sharable()
|
||||
{ this->mutex()->lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_sharable()
|
||||
{ this->mutex()->unlock_sharable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_lock_sharable()
|
||||
{ return this->mutex()->try_lock_sharable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_lock_sharable
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_lock_sharable(abs_time); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
|
||||
{ this->mutex()->unlock_and_lock_upgradable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_and_lock_sharable()
|
||||
{ this->mutex()->unlock_and_lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable()
|
||||
{ this->mutex()->unlock_upgradable_and_lock_sharable(); }
|
||||
|
||||
inline void named_upgradable_mutex::unlock_upgradable_and_lock()
|
||||
{ this->mutex()->unlock_upgradable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
|
||||
{ return this->mutex()->try_unlock_upgradable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
|
||||
{ return this->mutex()->try_unlock_sharable_and_lock(); }
|
||||
|
||||
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
|
||||
{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); }
|
||||
|
||||
inline bool named_upgradable_mutex::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
|
||||
@@ -0,0 +1,304 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SPIN_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/spin/mutex.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class spin_condition
|
||||
{
|
||||
spin_condition(const spin_condition &);
|
||||
spin_condition &operator=(const spin_condition &);
|
||||
public:
|
||||
spin_condition();
|
||||
~spin_condition();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
//Handle infinity absolute time here to avoid complications in do_timed_wait
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->wait(lock);
|
||||
return true;
|
||||
}
|
||||
return this->do_timed_wait(abs_time, *lock.mutex());
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
//Handle infinity absolute time here to avoid complications in do_timed_wait
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->wait(lock, pred);
|
||||
return true;
|
||||
}
|
||||
while (!pred()){
|
||||
if (!this->do_timed_wait(abs_time, *lock.mutex()))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
do_wait(*lock.mutex());
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_exception();
|
||||
|
||||
while (!pred())
|
||||
do_wait(*lock.mutex());
|
||||
}
|
||||
|
||||
template<class InterprocessMutex>
|
||||
void do_wait(InterprocessMutex &mut);
|
||||
|
||||
template<class InterprocessMutex>
|
||||
bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
|
||||
|
||||
private:
|
||||
template<class InterprocessMutex>
|
||||
bool do_timed_wait(bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
|
||||
|
||||
enum { SLEEP = 0, NOTIFY_ONE, NOTIFY_ALL };
|
||||
spin_mutex m_enter_mut;
|
||||
volatile boost::uint32_t m_command;
|
||||
volatile boost::uint32_t m_num_waiters;
|
||||
void notify(boost::uint32_t command);
|
||||
};
|
||||
|
||||
inline spin_condition::spin_condition()
|
||||
{
|
||||
//Note that this class is initialized to zero.
|
||||
//So zeroed memory can be interpreted as an initialized
|
||||
//condition variable
|
||||
m_command = SLEEP;
|
||||
m_num_waiters = 0;
|
||||
}
|
||||
|
||||
inline spin_condition::~spin_condition()
|
||||
{
|
||||
//Notify all waiting threads
|
||||
//to allow POSIX semantics on condition destruction
|
||||
this->notify_all();
|
||||
}
|
||||
|
||||
inline void spin_condition::notify_one()
|
||||
{
|
||||
this->notify(NOTIFY_ONE);
|
||||
}
|
||||
|
||||
inline void spin_condition::notify_all()
|
||||
{
|
||||
this->notify(NOTIFY_ALL);
|
||||
}
|
||||
|
||||
inline void spin_condition::notify(boost::uint32_t command)
|
||||
{
|
||||
//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
|
||||
//on this spin_condition before this one ends
|
||||
m_enter_mut.lock();
|
||||
|
||||
//Return if there are no waiters
|
||||
if(!atomic_read32(&m_num_waiters)) {
|
||||
m_enter_mut.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
//Notify that all threads should execute wait logic
|
||||
spin_wait swait;
|
||||
while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
|
||||
swait.yield();
|
||||
}
|
||||
//The enter mutex will rest locked until the last waiting thread unlocks it
|
||||
}
|
||||
|
||||
template<class InterprocessMutex>
|
||||
inline void spin_condition::do_wait(InterprocessMutex &mut)
|
||||
{
|
||||
this->do_timed_wait(false, boost::posix_time::ptime(), mut);
|
||||
}
|
||||
|
||||
template<class InterprocessMutex>
|
||||
inline bool spin_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 spin_condition::do_timed_wait(bool tout_enabled,
|
||||
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.
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
InternalLock lock;
|
||||
if(tout_enabled){
|
||||
InternalLock dummy(m_enter_mut, abs_time);
|
||||
lock = boost::move(dummy);
|
||||
}
|
||||
else{
|
||||
InternalLock dummy(m_enter_mut);
|
||||
lock = boost::move(dummy);
|
||||
}
|
||||
|
||||
if(!lock)
|
||||
return false;
|
||||
//---------------------------------------------------------------
|
||||
//We increment the waiting thread count protected so that it will be
|
||||
//always constant when another thread enters the notification logic.
|
||||
//The increment marks this thread as "waiting on spin_condition"
|
||||
atomic_inc32(const_cast<boost::uint32_t*>(&m_num_waiters));
|
||||
|
||||
//We unlock the external mutex atomically with the increment
|
||||
mut.unlock();
|
||||
}
|
||||
|
||||
//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
|
||||
//exit or timeout occurs
|
||||
while(1){
|
||||
//The thread sleeps/spins until a spin_condition commands a notification
|
||||
//Notification occurred, we will lock the checking mutex so that
|
||||
spin_wait swait;
|
||||
while(atomic_read32(&m_command) == SLEEP){
|
||||
swait.yield();
|
||||
|
||||
//Check for timeout
|
||||
if(tout_enabled){
|
||||
now = microsec_clock::universal_time();
|
||||
|
||||
if(now >= abs_time){
|
||||
//If we can lock the mutex it means that no notification
|
||||
//is being executed in this spin_condition variable
|
||||
timed_out = m_enter_mut.try_lock();
|
||||
|
||||
//If locking fails, indicates that another thread is executing
|
||||
//notification, so we play the notification game
|
||||
if(!timed_out){
|
||||
//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,
|
||||
//release the enter mutex and return false.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If a timeout occurred, the mutex will not execute checking logic
|
||||
if(tout_enabled && timed_out){
|
||||
//Decrement wait count
|
||||
atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
|
||||
unlock_enter_mut = true;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
boost::uint32_t result = atomic_cas32
|
||||
(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ONE);
|
||||
if(result == SLEEP){
|
||||
//Other thread has been notified and since it was a NOTIFY one
|
||||
//command, this thread must sleep again
|
||||
continue;
|
||||
}
|
||||
else if(result == NOTIFY_ONE){
|
||||
//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.
|
||||
unlock_enter_mut = true;
|
||||
atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
|
||||
break;
|
||||
}
|
||||
else{
|
||||
//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
|
||||
if(unlock_enter_mut){
|
||||
atomic_cas32(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
//Lock external again before returning from the method
|
||||
mut.lock();
|
||||
return !timed_out;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include<boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
inline barrier::barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
inline barrier::~barrier(){}
|
||||
|
||||
inline bool barrier::wait()
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0){
|
||||
m_generation++;
|
||||
m_count = m_threshold;
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation){
|
||||
m_cond.wait(lock);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
@@ -0,0 +1,87 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SPIN_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class spin_mutex
|
||||
{
|
||||
spin_mutex(const spin_mutex &);
|
||||
spin_mutex &operator=(const spin_mutex &);
|
||||
public:
|
||||
|
||||
spin_mutex();
|
||||
~spin_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
void take_ownership(){};
|
||||
private:
|
||||
volatile boost::uint32_t m_s;
|
||||
};
|
||||
|
||||
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()
|
||||
{
|
||||
//Trivial destructor
|
||||
}
|
||||
|
||||
inline void spin_mutex::lock(void)
|
||||
{ return ipcdetail::try_based_lock(*this); }
|
||||
|
||||
inline bool spin_mutex::try_lock(void)
|
||||
{
|
||||
boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
|
||||
return m_s == 1 && prev_s == 0;
|
||||
}
|
||||
|
||||
inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
|
||||
|
||||
inline void spin_mutex::unlock(void)
|
||||
{ ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); }
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
|
||||
@@ -0,0 +1,176 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/spin/mutex.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class spin_recursive_mutex
|
||||
{
|
||||
spin_recursive_mutex(const spin_recursive_mutex &);
|
||||
spin_recursive_mutex &operator=(const spin_recursive_mutex &);
|
||||
public:
|
||||
|
||||
spin_recursive_mutex();
|
||||
~spin_recursive_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
void take_ownership();
|
||||
private:
|
||||
spin_mutex m_mutex;
|
||||
unsigned int m_nLockCount;
|
||||
volatile ipcdetail::OS_systemwide_thread_id_t m_nOwner;
|
||||
volatile boost::uint32_t m_s;
|
||||
};
|
||||
|
||||
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(){}
|
||||
|
||||
inline void spin_recursive_mutex::lock()
|
||||
{
|
||||
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
|
||||
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
|
||||
handle_t old_id;
|
||||
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
|
||||
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)){
|
||||
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{
|
||||
m_mutex.lock();
|
||||
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
|
||||
m_nLockCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool spin_recursive_mutex::try_lock()
|
||||
{
|
||||
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
|
||||
handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
|
||||
handle_t old_id;
|
||||
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
|
||||
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
|
||||
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;
|
||||
}
|
||||
if(m_mutex.try_lock()){
|
||||
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
|
||||
m_nLockCount = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
|
||||
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
|
||||
handle_t old_id;
|
||||
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
|
||||
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
|
||||
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;
|
||||
}
|
||||
//m_mutex supports abs_time so no need to check it
|
||||
if(m_mutex.timed_lock(abs_time)){
|
||||
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
|
||||
m_nLockCount = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void spin_recursive_mutex::unlock()
|
||||
{
|
||||
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
|
||||
handle_t old_id;
|
||||
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
|
||||
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
|
||||
(void)old_id;
|
||||
(void)thr_id;
|
||||
BOOST_ASSERT(ipcdetail::equal_systemwide_thread_id(thr_id, old_id));
|
||||
--m_nLockCount;
|
||||
if(!m_nLockCount){
|
||||
const handle_t new_id(ipcdetail::get_invalid_systemwide_thread_id());
|
||||
ipcdetail::systemwide_thread_id_copy(new_id, m_nOwner);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
inline void spin_recursive_mutex::take_ownership()
|
||||
{
|
||||
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
|
||||
this->m_nLockCount = 1;
|
||||
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
|
||||
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
|
||||
@@ -0,0 +1,94 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SPIN_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
|
||||
#include <boost/interprocess/sync/detail/locks.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class spin_semaphore
|
||||
{
|
||||
spin_semaphore(const spin_semaphore &);
|
||||
spin_semaphore &operator=(const spin_semaphore &);
|
||||
|
||||
public:
|
||||
spin_semaphore(unsigned int initialCount);
|
||||
~spin_semaphore();
|
||||
|
||||
void post();
|
||||
void wait();
|
||||
bool try_wait();
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
// int get_count() const;
|
||||
private:
|
||||
volatile boost::uint32_t m_count;
|
||||
};
|
||||
|
||||
|
||||
inline spin_semaphore::~spin_semaphore()
|
||||
{}
|
||||
|
||||
inline spin_semaphore::spin_semaphore(unsigned int initialCount)
|
||||
{ ipcdetail::atomic_write32(&this->m_count, boost::uint32_t(initialCount)); }
|
||||
|
||||
inline void spin_semaphore::post()
|
||||
{
|
||||
ipcdetail::atomic_inc32(&m_count);
|
||||
}
|
||||
|
||||
inline void spin_semaphore::wait()
|
||||
{
|
||||
ipcdetail::lock_to_wait<spin_semaphore> lw(*this);
|
||||
return ipcdetail::try_based_lock(lw);
|
||||
}
|
||||
|
||||
inline bool spin_semaphore::try_wait()
|
||||
{
|
||||
return ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0));
|
||||
}
|
||||
|
||||
inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
ipcdetail::lock_to_wait<spin_semaphore> lw(*this);
|
||||
return ipcdetail::try_based_timed_lock(lw, abs_time);
|
||||
}
|
||||
|
||||
//inline int spin_semaphore::get_count() const
|
||||
//{
|
||||
//return (int)ipcdetail::atomic_read32(&m_count);
|
||||
//}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
|
||||
@@ -0,0 +1,185 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Peter Dimov 2008.
|
||||
// (C) Copyright Ion Gaztanaga 2013-2013. 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parts of this file come from boost/smart_ptr/detail/yield_k.hpp
|
||||
//Many thanks to Peter Dimov.
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
#define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
|
||||
//#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
// BOOST_INTERPROCESS_SMT_PAUSE
|
||||
|
||||
#if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) )
|
||||
|
||||
extern "C" void _mm_pause();
|
||||
#pragma intrinsic( _mm_pause )
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
|
||||
|
||||
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC)
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail {
|
||||
|
||||
template<int Dummy = 0>
|
||||
class num_core_holder
|
||||
{
|
||||
public:
|
||||
static unsigned int get()
|
||||
{
|
||||
if(!num_cores){
|
||||
return ipcdetail::get_num_cores();
|
||||
}
|
||||
else{
|
||||
return num_cores;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static unsigned int num_cores;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
class spin_wait
|
||||
{
|
||||
public:
|
||||
|
||||
static const unsigned int nop_pause_limit = 32u;
|
||||
spin_wait()
|
||||
: m_count_start(), m_ul_yield_only_counts(), m_k()
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
~spin_wait()
|
||||
{
|
||||
if(m_k){
|
||||
std::cout << "final m_k: " << m_k
|
||||
<< " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int count() const
|
||||
{ return m_k; }
|
||||
|
||||
void yield()
|
||||
{
|
||||
//Lazy initialization of limits
|
||||
if( !m_k){
|
||||
this->init_limits();
|
||||
}
|
||||
//Nop tries
|
||||
if( m_k < (nop_pause_limit >> 2) ){
|
||||
|
||||
}
|
||||
//Pause tries if the processor supports it
|
||||
#if defined(BOOST_INTERPROCESS_SMT_PAUSE)
|
||||
else if( m_k < nop_pause_limit ){
|
||||
BOOST_INTERPROCESS_SMT_PAUSE
|
||||
}
|
||||
#endif
|
||||
//Yield/Sleep strategy
|
||||
else{
|
||||
//Lazy initialization of tick information
|
||||
if(m_k == nop_pause_limit){
|
||||
this->init_tick_info();
|
||||
}
|
||||
else if( this->yield_or_sleep() ){
|
||||
ipcdetail::thread_yield();
|
||||
}
|
||||
else{
|
||||
ipcdetail::thread_sleep_tick();
|
||||
}
|
||||
}
|
||||
++m_k;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_k = 0u;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init_limits()
|
||||
{
|
||||
unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
|
||||
m_k = num_cores > 1u ? 0u : nop_pause_limit;
|
||||
}
|
||||
|
||||
void init_tick_info()
|
||||
{
|
||||
m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
|
||||
m_count_start = ipcdetail::get_current_system_highres_count();
|
||||
}
|
||||
|
||||
//Returns true if yield must be called, false is sleep must be called
|
||||
bool yield_or_sleep()
|
||||
{
|
||||
if(!m_ul_yield_only_counts){ //If yield-only limit was reached then yield one in every two tries
|
||||
return (m_k & 1u) != 0;
|
||||
}
|
||||
else{ //Try to see if we've reched yield-only time limit
|
||||
const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
|
||||
const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
|
||||
if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
std::cout << "elapsed!\n"
|
||||
<< " m_ul_yield_only_counts: " << m_ul_yield_only_counts
|
||||
<< " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
|
||||
<< " m_k: " << m_k << " elapsed counts: ";
|
||||
ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
|
||||
#endif
|
||||
//Yield-only time reached, now it's time to sleep
|
||||
m_ul_yield_only_counts = 0ul;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true; //Otherwise yield
|
||||
}
|
||||
|
||||
ipcdetail::OS_highres_count_t m_count_start;
|
||||
unsigned long m_ul_yield_only_counts;
|
||||
unsigned int m_k;
|
||||
};
|
||||
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
@@ -0,0 +1,313 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This interface is inspired by Howard Hinnant's lock proposal.
|
||||
// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
|
||||
#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/sync/lock_options.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes the upgradable_lock class that serves to acquire the upgradable
|
||||
//!lock of a mutex.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking,
|
||||
//!try-read-locking and timed-read-locking (recursive or not) for the Mutex.
|
||||
//!Additionally the upgradable_lock can transfer ownership to a scoped_lock
|
||||
//!using transfer_lock syntax. The Mutex need not supply all of the functionality.
|
||||
//!If the client of upgradable_lock<Mutex> does not use functionality which the
|
||||
//!Mutex does not supply, no harm is done. Mutex ownership can be shared among
|
||||
//!read_locks, and a single upgradable_lock. upgradable_lock does not support
|
||||
//!copy semantics. However upgradable_lock supports ownership transfer from
|
||||
//!a upgradable_locks or scoped_locks via transfer_lock syntax.
|
||||
template <class UpgradableMutex>
|
||||
class upgradable_lock
|
||||
{
|
||||
public:
|
||||
typedef UpgradableMutex mutex_type;
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
typedef upgradable_lock<UpgradableMutex> this_type;
|
||||
explicit upgradable_lock(scoped_lock<mutex_type>&);
|
||||
typedef bool this_type::*unspecified_bool_type;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock)
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
|
||||
//!Effects: Default constructs a upgradable_lock.
|
||||
//!Postconditions: owns() == false and mutex() == 0.
|
||||
upgradable_lock()
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{}
|
||||
|
||||
explicit upgradable_lock(mutex_type& m)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ mp_mutex->lock_upgradable(); m_locked = true; }
|
||||
|
||||
//!Postconditions: owns() == false, and mutex() == &m.
|
||||
//!Notes: The constructor will not take ownership of the mutex. There is no effect
|
||||
//! required on the referenced mutex.
|
||||
upgradable_lock(mutex_type& m, defer_lock_type)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{}
|
||||
|
||||
//!Postconditions: owns() == true, and mutex() == &m.
|
||||
//!Notes: The constructor will suppose that the mutex is already upgradable
|
||||
//! locked. There is no effect required on the referenced mutex.
|
||||
upgradable_lock(mutex_type& m, accept_ownership_type)
|
||||
: mp_mutex(&m), m_locked(true)
|
||||
{}
|
||||
|
||||
//!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
|
||||
//! if it can do so without waiting. Whether or not this constructor
|
||||
//! handles recursive locking depends upon the mutex. If the mutex_type
|
||||
//! does not support try_lock_upgradable, this constructor will fail at
|
||||
//! compile time if instantiated, but otherwise have no effect.
|
||||
upgradable_lock(mutex_type& m, try_to_lock_type)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ m_locked = mp_mutex->try_lock_upgradable(); }
|
||||
|
||||
//!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
|
||||
//! can do so within the time specified. Whether or not this constructor
|
||||
//! handles recursive locking depends upon the mutex. If the mutex_type
|
||||
//! does not support timed_lock_upgradable, this constructor will fail
|
||||
//! at compile time if instantiated, but otherwise have no effect.
|
||||
upgradable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
|
||||
: mp_mutex(&m), m_locked(false)
|
||||
{ m_locked = mp_mutex->timed_lock_upgradable(abs_time); }
|
||||
|
||||
//!Effects: No effects on the underlying mutex.
|
||||
//!Postconditions: mutex() == the value upgr.mutex() had before the
|
||||
//! construction. upgr.mutex() == 0. owns() == upgr.owns() before the
|
||||
//! construction. upgr.owns() == false.
|
||||
//!Notes: If upgr is locked, this constructor will lock this upgradable_lock
|
||||
//! while unlocking upgr. If upgr is unlocked, then this upgradable_lock will
|
||||
//! be unlocked as well. Only a moved upgradable_lock's will match this
|
||||
//! signature. An non-moved upgradable_lock can be moved with the
|
||||
//! expression: "boost::move(lock);". This constructor does not alter the
|
||||
//! state of the mutex, only potentially who owns it.
|
||||
upgradable_lock(BOOST_RV_REF(upgradable_lock<mutex_type>) upgr)
|
||||
: mp_mutex(0), m_locked(upgr.owns())
|
||||
{ mp_mutex = upgr.release(); }
|
||||
|
||||
//!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.
|
||||
//!Notes: If scop is locked, this constructor will transfer the exclusive-ownership
|
||||
//! to an upgradable-ownership of this upgradable_lock.
|
||||
//! Only a moved sharable_lock's will match this
|
||||
//! signature. An non-moved sharable_lock can be moved with the
|
||||
//! expression: "boost::move(lock);".
|
||||
template<class T>
|
||||
upgradable_lock(BOOST_RV_REF(scoped_lock<T>) scop
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, UpgradableMutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
scoped_lock<mutex_type> &u_lock = scop;
|
||||
if(u_lock.owns()){
|
||||
u_lock.mutex()->unlock_and_lock_upgradable();
|
||||
m_locked = true;
|
||||
}
|
||||
mp_mutex = u_lock.release();
|
||||
}
|
||||
|
||||
//!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable()
|
||||
//! 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.
|
||||
//! 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.
|
||||
//! 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
|
||||
//! ownership from shar immediately, while changing the lock type from a
|
||||
//! "read lock" to an "upgradable lock". If the "read lock" isn't held
|
||||
//! in the first place, the mutex merely changes type to an unlocked
|
||||
//! "upgradable lock". If the "read lock" is held, then mutex transfer
|
||||
//! occurs only if it can do so in a non-blocking manner.
|
||||
template<class T>
|
||||
upgradable_lock( BOOST_RV_REF(sharable_lock<T>) shar, try_to_lock_type
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_same<T, UpgradableMutex> >::type * = 0)
|
||||
: mp_mutex(0), m_locked(false)
|
||||
{
|
||||
sharable_lock<mutex_type> &s_lock = shar;
|
||||
if(s_lock.owns()){
|
||||
if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){
|
||||
mp_mutex = s_lock.release();
|
||||
}
|
||||
}
|
||||
else{
|
||||
s_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
//!Effects: if (owns()) m_->unlock_upgradable().
|
||||
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.
|
||||
~upgradable_lock()
|
||||
{
|
||||
try{
|
||||
if(m_locked && mp_mutex) mp_mutex->unlock_upgradable();
|
||||
}
|
||||
catch(...){}
|
||||
}
|
||||
|
||||
//!Effects: If owns(), then unlock_upgradable() is called on mutex().
|
||||
//! *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 upgradable lock
|
||||
//! count will be decremented by one.
|
||||
upgradable_lock &operator=(BOOST_RV_REF(upgradable_lock) upgr)
|
||||
{
|
||||
if(this->owns())
|
||||
this->unlock();
|
||||
m_locked = upgr.owns();
|
||||
mp_mutex = upgr.release();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! exception. Calls lock_upgradable() on the referenced mutex.
|
||||
//!Postconditions: owns() == true.
|
||||
//!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();
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! exception. Calls try_lock_upgradable() on the referenced mutex.
|
||||
//!Postconditions: owns() == the value returned from
|
||||
//! mutex()->try_lock_upgradable().
|
||||
//!Notes: The upgradable_lock changes from a state of not owning the mutex,
|
||||
//! to owning the mutex, but only if blocking was not required. If the
|
||||
//! 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();
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
|
||||
//! exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex.
|
||||
//!Postconditions: owns() == the value returned from
|
||||
//! mutex()->timed_lock_upgradable(abs_time).
|
||||
//!Notes: The upgradable_lock changes from a state of not owning the mutex,
|
||||
//! to owning the mutex, but only if it can obtain ownership within the
|
||||
//! specified time. If the mutex_type does not support
|
||||
//! 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);
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
//!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
|
||||
//! exception. Calls unlock_upgradable() on the referenced mutex.
|
||||
//!Postconditions: owns() == false.
|
||||
//!Notes: The upgradable_lock changes from a state of owning the mutex,
|
||||
//! to not owning the mutex.
|
||||
void unlock()
|
||||
{
|
||||
if(!mp_mutex || !m_locked)
|
||||
throw lock_exception();
|
||||
mp_mutex->unlock_upgradable();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
//!Effects: Returns true if this scoped_lock has acquired the
|
||||
//!referenced mutex.
|
||||
bool owns() const
|
||||
{ return m_locked && mp_mutex; }
|
||||
|
||||
//!Conversion to bool.
|
||||
//!Returns owns().
|
||||
operator unspecified_bool_type() const
|
||||
{ return m_locked? &this_type::m_locked : 0; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if
|
||||
//!there is no mutex to reference.
|
||||
mutex_type* mutex() const
|
||||
{ return mp_mutex; }
|
||||
|
||||
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
|
||||
//! mutex to reference.
|
||||
//!Postconditions: mutex() == 0 and owns() == false.
|
||||
mutex_type* release()
|
||||
{
|
||||
mutex_type *mut = mp_mutex;
|
||||
mp_mutex = 0;
|
||||
m_locked = false;
|
||||
return mut;
|
||||
}
|
||||
|
||||
//!Effects: Swaps state with moved lock.
|
||||
//!Throws: Nothing.
|
||||
void swap(upgradable_lock<mutex_type> &other)
|
||||
{
|
||||
(simple_swap)(mp_mutex, other.mp_mutex);
|
||||
(simple_swap)(m_locked, other.m_locked);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
mutex_type *mp_mutex;
|
||||
bool m_locked;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
|
||||
@@ -0,0 +1,129 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_WINDOWS_CONDITION_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/sync/windows/semaphore.hpp>
|
||||
#include <boost/interprocess/sync/windows/mutex.hpp>
|
||||
#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class windows_condition
|
||||
{
|
||||
windows_condition(const windows_condition &);
|
||||
windows_condition &operator=(const windows_condition &);
|
||||
|
||||
public:
|
||||
windows_condition()
|
||||
: m_condition_data()
|
||||
{}
|
||||
|
||||
~windows_condition()
|
||||
{
|
||||
//Notify all waiting threads
|
||||
//to allow POSIX semantics on condition destruction
|
||||
this->notify_all();
|
||||
}
|
||||
|
||||
void notify_one()
|
||||
{ m_condition_data.notify_one(); }
|
||||
|
||||
void notify_all()
|
||||
{ m_condition_data.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{ return m_condition_data.timed_wait(lock, abs_time); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{ return m_condition_data.timed_wait(lock, abs_time, pred); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{ m_condition_data.wait(lock); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{ m_condition_data.wait(lock, pred); }
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
|
||||
@@ -0,0 +1,118 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_WINDOWS_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/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>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class windows_mutex
|
||||
{
|
||||
windows_mutex(const windows_mutex &);
|
||||
windows_mutex &operator=(const windows_mutex &);
|
||||
public:
|
||||
|
||||
windows_mutex();
|
||||
~windows_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
void take_ownership(){};
|
||||
|
||||
private:
|
||||
const sync_id id_;
|
||||
};
|
||||
|
||||
inline windows_mutex::windows_mutex()
|
||||
: id_(this)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//Create mutex with the initial count
|
||||
bool open_or_created;
|
||||
(void)handles.obtain_mutex(this->id_, &open_or_created);
|
||||
//The mutex must be created, never opened
|
||||
BOOST_ASSERT(open_or_created);
|
||||
BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
|
||||
(void)open_or_created;
|
||||
}
|
||||
|
||||
inline windows_mutex::~windows_mutex()
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
handles.destroy_handle(this->id_);
|
||||
}
|
||||
|
||||
inline void windows_mutex::lock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
mut.lock();
|
||||
}
|
||||
|
||||
inline bool windows_mutex::try_lock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
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)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
return mut.timed_lock(abs_time);
|
||||
}
|
||||
|
||||
inline void windows_mutex::unlock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
return mut.unlock();
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/windows/named_condition_any.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
typedef windows_named_condition_any windows_named_condition;
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_ANY_HPP
|
||||
#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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_any
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_condition_any();
|
||||
windows_named_condition_any(const windows_named_condition_any &);
|
||||
windows_named_condition_any &operator=(const windows_named_condition_any &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
windows_named_condition_any
|
||||
(create_only_t, const char *name, const permissions &perm)
|
||||
: m_condition_data()
|
||||
{
|
||||
named_cond_callbacks callbacks(m_condition_data.get_members());
|
||||
m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
|
||||
}
|
||||
|
||||
windows_named_condition_any
|
||||
(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_condition_data()
|
||||
{
|
||||
named_cond_callbacks callbacks(m_condition_data.get_members());
|
||||
m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
|
||||
}
|
||||
|
||||
windows_named_condition_any(open_only_t, const char *name)
|
||||
: m_condition_data()
|
||||
{
|
||||
named_cond_callbacks callbacks(m_condition_data.get_members());
|
||||
m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
|
||||
}
|
||||
|
||||
~windows_named_condition_any()
|
||||
{
|
||||
named_cond_callbacks callbacks(m_condition_data.get_members());
|
||||
m_named_sync.close(callbacks);
|
||||
}
|
||||
|
||||
void notify_one()
|
||||
{ m_condition_data.notify_one(); }
|
||||
|
||||
void notify_all()
|
||||
{ m_condition_data.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
|
||||
{ return m_condition_data.timed_wait(lock, abs_time); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
|
||||
{ return m_condition_data.timed_wait(lock, abs_time, pred); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{ m_condition_data.wait(lock); }
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{ m_condition_data.wait(lock, pred); }
|
||||
|
||||
static bool remove(const char *name)
|
||||
{ return windows_named_sync::remove(name); }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
|
||||
void dont_close_on_destruction()
|
||||
{}
|
||||
|
||||
friend class interprocess_tester;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
|
||||
@@ -0,0 +1,179 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_mutex();
|
||||
windows_named_mutex(const windows_named_mutex &);
|
||||
windows_named_mutex &operator=(const windows_named_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
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);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
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;
|
||||
};
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
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
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_recursive_mutex();
|
||||
windows_named_recursive_mutex(const windows_named_mutex &);
|
||||
windows_named_recursive_mutex &operator=(const windows_named_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
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
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_semaphore();
|
||||
windows_named_semaphore(const windows_named_semaphore &);
|
||||
windows_named_semaphore &operator=(const windows_named_semaphore &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
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);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
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;
|
||||
};
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
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
|
||||
@@ -0,0 +1,219 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/shared_dir_helpers.hpp>
|
||||
#include <boost/interprocess/sync/windows/sync_utils.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <string>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
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
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_sync(const windows_named_sync &);
|
||||
windows_named_sync &operator=(const windows_named_sync &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
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);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
void *m_file_hnd;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
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_shared_dir_cleaning_old_and_get_filepath(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);
|
||||
BOOST_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::shared_filepath(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
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_WINDOWS_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/windows/mutex.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
//Windows mutex is already recursive
|
||||
class windows_recursive_mutex
|
||||
: public windows_mutex
|
||||
{
|
||||
windows_recursive_mutex(const windows_recursive_mutex &);
|
||||
windows_recursive_mutex &operator=(const windows_recursive_mutex &);
|
||||
public:
|
||||
windows_recursive_mutex() : windows_mutex() {}
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
|
||||
@@ -0,0 +1,117 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_WINDOWS_SEMAPHORE_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/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>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class windows_semaphore
|
||||
{
|
||||
windows_semaphore(const windows_semaphore &);
|
||||
windows_semaphore &operator=(const windows_semaphore &);
|
||||
public:
|
||||
|
||||
windows_semaphore(unsigned int initialCount);
|
||||
~windows_semaphore();
|
||||
|
||||
void post(long release_count = 1);
|
||||
void wait();
|
||||
bool try_wait();
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
private:
|
||||
const sync_id id_;
|
||||
};
|
||||
|
||||
inline windows_semaphore::windows_semaphore(unsigned int initialCount)
|
||||
: id_(this)
|
||||
{
|
||||
sync_handles &handles =
|
||||
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);
|
||||
//The semaphore must be created, never opened
|
||||
BOOST_ASSERT(open_or_created);
|
||||
BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
|
||||
(void)open_or_created;
|
||||
}
|
||||
|
||||
inline windows_semaphore::~windows_semaphore()
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
handles.destroy_handle(this->id_);
|
||||
}
|
||||
|
||||
inline void windows_semaphore::wait(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
|
||||
sem.wait();
|
||||
}
|
||||
|
||||
inline bool windows_semaphore::try_wait(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
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)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
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 =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
|
||||
sem.post(release_count);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
|
||||
@@ -0,0 +1,240 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-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_SYNC_UTILS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/sync/spin/mutex.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
|
||||
|
||||
//Shield against external warnings
|
||||
#include <boost/interprocess/detail/config_external_begin.hpp>
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
#include <boost/interprocess/detail/config_external_end.hpp>
|
||||
|
||||
|
||||
#include <boost/container/map.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
|
||||
{
|
||||
const std::size_t need_mem = mem_length*2+1;
|
||||
if(out_length < need_mem){
|
||||
out_length = need_mem;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char Characters [] =
|
||||
{ '0', '1', '2', '3', '4', '5', '6', '7'
|
||||
, '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
std::size_t char_counter = 0;
|
||||
const char *buf = (const char *)mem;
|
||||
for(std::size_t i = 0; i != mem_length; ++i){
|
||||
out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
|
||||
out_str[char_counter++] = Characters[(buf[i]&0x0F)];
|
||||
}
|
||||
out_str[char_counter] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
class sync_id
|
||||
{
|
||||
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_; }
|
||||
|
||||
internal_type &internal_pod()
|
||||
{ return rand_; }
|
||||
|
||||
const void *map_address() const
|
||||
{ return map_addr_; }
|
||||
|
||||
friend std::size_t hash_value(const sync_id &m)
|
||||
{ return boost::hash_value(m.rand_); }
|
||||
|
||||
friend bool operator==(const sync_id &l, const sync_id &r)
|
||||
{ return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; }
|
||||
|
||||
private:
|
||||
internal_type rand_;
|
||||
const void * const map_addr_;
|
||||
};
|
||||
|
||||
class sync_handles
|
||||
{
|
||||
public:
|
||||
enum type { MUTEX, SEMAPHORE };
|
||||
|
||||
private:
|
||||
struct address_less
|
||||
{
|
||||
bool operator()(sync_id const * const l, sync_id const * const r) const
|
||||
{ return l->map_address() < r->map_address(); }
|
||||
};
|
||||
|
||||
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";
|
||||
std::size_t i = 0;
|
||||
do{
|
||||
name[i] = n[i];
|
||||
++i;
|
||||
} while(n[i]);
|
||||
std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
|
||||
bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
|
||||
}
|
||||
|
||||
void throw_if_error(void *hnd_val)
|
||||
{
|
||||
if(!hnd_val){
|
||||
error_info err(winapi::get_last_error());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
|
||||
{
|
||||
NameBuf name;
|
||||
fill_name(name, id);
|
||||
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);
|
||||
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_);
|
||||
umap_type::iterator it = umap_.insert(v).first;
|
||||
void *&hnd_val = it->second;
|
||||
if(!hnd_val){
|
||||
map_[&it->first] = it;
|
||||
hnd_val = open_or_create_mutex(id);
|
||||
if(popen_created) *popen_created = true;
|
||||
}
|
||||
else if(popen_created){
|
||||
*popen_created = false;
|
||||
}
|
||||
return hnd_val;
|
||||
}
|
||||
|
||||
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_);
|
||||
umap_type::iterator it = umap_.insert(v).first;
|
||||
void *&hnd_val = it->second;
|
||||
if(!hnd_val){
|
||||
map_[&it->first] = it;
|
||||
hnd_val = open_or_create_semaphore(id, initial_count);
|
||||
if(popen_created) *popen_created = true;
|
||||
}
|
||||
else if(popen_created){
|
||||
*popen_created = false;
|
||||
}
|
||||
return hnd_val;
|
||||
}
|
||||
|
||||
void destroy_handle(const sync_id &id)
|
||||
{
|
||||
scoped_lock<spin_mutex> lock(mtx_);
|
||||
umap_type::iterator it = umap_.find(id);
|
||||
umap_type::iterator itend = umap_.end();
|
||||
|
||||
if(it != itend){
|
||||
winapi::close_handle(it->second);
|
||||
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)
|
||||
{
|
||||
const sync_id low_id(addr);
|
||||
const 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 * const hnd = umap_[*itlow->first];
|
||||
winapi::close_handle(hnd);
|
||||
umap_.erase(*itlow->first);
|
||||
itlow = map_.erase(itlow);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
spin_mutex mtx_;
|
||||
umap_type umap_;
|
||||
map_type map_;
|
||||
};
|
||||
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/sync/windows/winapi_wrapper_common.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class winapi_mutex_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_mutex_functions(const winapi_mutex_functions &);
|
||||
winapi_mutex_functions &operator=(const winapi_mutex_functions &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
winapi_mutex_functions(void *mtx_hnd)
|
||||
: m_mtx_hnd(mtx_hnd)
|
||||
{}
|
||||
|
||||
void unlock()
|
||||
{ winapi::release_mutex(m_mtx_hnd); }
|
||||
|
||||
void lock()
|
||||
{ return winapi_wrapper_wait_for_single_object(m_mtx_hnd); }
|
||||
|
||||
bool try_lock()
|
||||
{ return winapi_wrapper_try_wait_for_single_object(m_mtx_hnd); }
|
||||
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return winapi_wrapper_timed_wait_for_single_object(m_mtx_hnd, abs_time); }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
protected:
|
||||
void *m_mtx_hnd;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
//Swappable mutex wrapper
|
||||
class winapi_mutex_wrapper
|
||||
: public winapi_mutex_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_mutex_wrapper(const winapi_mutex_wrapper &);
|
||||
winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//Note that Windows API does not return winapi::invalid_handle_value
|
||||
//when failing to create/open a mutex, but a nullptr
|
||||
|
||||
public:
|
||||
winapi_mutex_wrapper(void *mtx_hnd = 0)
|
||||
: winapi_mutex_functions(mtx_hnd)
|
||||
{}
|
||||
|
||||
~winapi_mutex_wrapper()
|
||||
{ this->close(); }
|
||||
|
||||
void *release()
|
||||
{
|
||||
void *hnd = m_mtx_hnd;
|
||||
m_mtx_hnd = 0;
|
||||
return hnd;
|
||||
}
|
||||
|
||||
void *handle() const
|
||||
{ return m_mtx_hnd; }
|
||||
|
||||
bool open_or_create(const char *name, const permissions &perm)
|
||||
{
|
||||
if(m_mtx_hnd == 0){
|
||||
m_mtx_hnd = winapi::open_or_create_mutex
|
||||
( name
|
||||
, false
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions()
|
||||
);
|
||||
return m_mtx_hnd != 0;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if(m_mtx_hnd != 0){
|
||||
winapi::close_handle(m_mtx_hnd);
|
||||
m_mtx_hnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/sync/windows/winapi_wrapper_common.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class winapi_semaphore_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_semaphore_functions(const winapi_semaphore_functions &);
|
||||
winapi_semaphore_functions &operator=(const winapi_semaphore_functions &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
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()
|
||||
{ return winapi_wrapper_wait_for_single_object(m_sem_hnd); }
|
||||
|
||||
bool try_wait()
|
||||
{ return winapi_wrapper_try_wait_for_single_object(m_sem_hnd); }
|
||||
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return winapi_wrapper_timed_wait_for_single_object(m_sem_hnd, abs_time); }
|
||||
|
||||
long value() const
|
||||
{
|
||||
long l_count, l_limit;
|
||||
if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
|
||||
return 0;
|
||||
return l_count;
|
||||
}
|
||||
|
||||
long limit() const
|
||||
{
|
||||
long l_count, l_limit;
|
||||
if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
|
||||
return 0;
|
||||
return l_limit;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
protected:
|
||||
void *m_sem_hnd;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
|
||||
//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
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_WRAPPER_COMMON_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
inline void winapi_wrapper_wait_for_single_object(void *handle)
|
||||
{
|
||||
unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time);
|
||||
if(ret != winapi::wait_object_0){
|
||||
if(ret != winapi::wait_abandoned){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
else{ //Special case for orphaned mutexes
|
||||
winapi::release_mutex(handle);
|
||||
throw interprocess_exception(owner_dead_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
|
||||
{
|
||||
unsigned long ret = winapi::wait_for_single_object(handle, 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);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Windows does not support infinity abs_time so check it
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
winapi_wrapper_wait_for_single_object(handle);
|
||||
return true;
|
||||
}
|
||||
const boost::posix_time::ptime cur_time = microsec_clock::universal_time();
|
||||
//Windows uses relative wait times so check for negative waits
|
||||
//and implement as 0 wait to allow try-semantics as POSIX mandates.
|
||||
unsigned long ret = winapi::wait_for_single_object
|
||||
( handle
|
||||
, (abs_time <= cur_time) ? 0u
|
||||
: (abs_time - cur_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);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
|
||||
Reference in New Issue
Block a user