|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r80146 - in trunk/boost/interprocess/sync: . detail shm windows
From: igaztanaga_at_[hidden]
Date: 2012-08-22 17:03:13
Author: igaztanaga
Date: 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
New Revision: 80146
URL: http://svn.boost.org/trac/boost/changeset/80146
Log:
[named_/interprocess]sharable_mutex & [named_/interprocess]condition_any implemented
Added:
trunk/boost/interprocess/sync/detail/condition_any_algorithm.hpp (contents, props changed)
trunk/boost/interprocess/sync/detail/locks.hpp (contents, props changed)
trunk/boost/interprocess/sync/interprocess_condition_any.hpp (contents, props changed)
trunk/boost/interprocess/sync/interprocess_sharable_mutex.hpp (contents, props changed)
trunk/boost/interprocess/sync/named_condition_any.hpp (contents, props changed)
trunk/boost/interprocess/sync/named_sharable_mutex.hpp (contents, props changed)
trunk/boost/interprocess/sync/shm/named_condition_any.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_condition_any.hpp (contents, props changed)
Text files modified:
trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp | 110 +++++++++++--
trunk/boost/interprocess/sync/interprocess_condition.hpp | 56 ++----
trunk/boost/interprocess/sync/interprocess_mutex.hpp | 56 ++++--
trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp | 4
trunk/boost/interprocess/sync/named_condition.hpp | 25 ++
trunk/boost/interprocess/sync/named_mutex.hpp | 19 +-
trunk/boost/interprocess/sync/named_upgradable_mutex.hpp | 32 +--
trunk/boost/interprocess/sync/shm/named_condition.hpp | 185 +++++-------------------
trunk/boost/interprocess/sync/shm/named_mutex.hpp | 13
trunk/boost/interprocess/sync/windows/condition.hpp | 85 ++--------
trunk/boost/interprocess/sync/windows/named_condition.hpp | 304 ---------------------------------------
11 files changed, 255 insertions(+), 634 deletions(-)
Modified: trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
==============================================================================
--- trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp (original)
+++ trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -14,6 +14,7 @@
#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 {
@@ -184,9 +185,9 @@
typedef typename ConditionMembers::integer_type integer_type;
public:
- template<class InterprocessMutex>
- static bool wait ( ConditionMembers &data, bool timeout_enabled
- , const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ 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);
};
@@ -238,12 +239,13 @@
}
template<class ConditionMembers>
-template<class InterprocessMutex>
+template<class Lock>
inline bool condition_algorithm_8a<ConditionMembers>::wait
( ConditionMembers &data
+ , Lock &lock
, bool tout_enabled
, const boost::posix_time::ptime &abs_time
- , InterprocessMutex &mtxExternal)
+ )
{
//Initialize to avoid warnings
integer_type nsignals_was_left = 0;
@@ -253,19 +255,13 @@
++data.get_nwaiters_blocked();
data.get_sem_block_lock().post();
- struct scoped_unlock
- {
- InterprocessMutex & mut;
- scoped_unlock(InterprocessMutex & m)
- : mut(m)
- { m.unlock(); }
-
- ~scoped_unlock()
- { mut.lock(); }
- } unlocker(mtxExternal);
-
-
- bool bTimedOut = tout_enabled ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false);
+ //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());
@@ -308,11 +304,87 @@
data.get_sem_block_lock().post(); // open the gate
}
- //mtxExternal.lock(); called from unlocker
+ //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(){}
+
+ ~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(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ 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(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ 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
Added: trunk/boost/interprocess/sync/detail/condition_any_algorithm.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/detail/condition_any_algorithm.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -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
+
+#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(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ 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(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ 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
Added: trunk/boost/interprocess/sync/detail/locks.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/detail/locks.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#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(); }
+};
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
Modified: trunk/boost/interprocess/sync/interprocess_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_condition.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_condition.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -22,6 +22,7 @@
#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>
@@ -54,6 +55,11 @@
//!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
{
/// @cond
@@ -62,13 +68,16 @@
interprocess_condition &operator=(const interprocess_condition &);
friend class named_condition;
/// @endcond
+
public:
//!Constructs a interprocess_condition. On error throws interprocess_exception.
- interprocess_condition(){}
+ interprocess_condition()
+ {}
//!Destroys *this
//!liberating system resources.
- ~interprocess_condition(){}
+ ~interprocess_condition()
+ {}
//!If there is a thread waiting on *this, change that
//!thread's state to ready. Otherwise there is no effect.
@@ -85,10 +94,9 @@
//!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());
+ {
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ m_condition.wait(internal_lock);
}
//!The same as:
@@ -96,11 +104,8 @@
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
- if (!lock)
- throw lock_exception();
-
- while (!pred())
- this->do_wait(*lock.mutex());
+ 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
@@ -111,13 +116,8 @@
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_condition.timed_wait(internal_lock, abs_time);
}
//!The same as: while (!pred()) {
@@ -126,28 +126,12 @@
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
- while (!pred()){
- if (!this->do_timed_wait(abs_time, *lock.mutex()))
- return pred();
- }
-
- return true;
+ ipcdetail::internal_mutex_lock<L> internal_lock(lock);
+ return m_condition.timed_wait(internal_lock, abs_time, pred);
}
/// @cond
- void do_wait(interprocess_mutex &mut)
- { m_condition.do_wait(mut.mutex); }
-
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut)
- { return m_condition.do_timed_wait(abs_time, mut.mutex); }
-
private:
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
Added: trunk/boost/interprocess/sync/interprocess_condition_any.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/interprocess_condition_any.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,129 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+/// @cond
+
+#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>
+
+/// @endcond
+
+//!\file
+//!Describes process-shared variables interprocess_condition_any class
+
+namespace boost {
+
+namespace posix_time
+{ class ptime; }
+
+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
+{
+ /// @cond
+ //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;
+
+ /// @endcond
+ 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
Modified: trunk/boost/interprocess/sync/interprocess_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -70,6 +70,25 @@
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
+
/// @endcond
public:
@@ -107,23 +126,16 @@
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: interprocess_exception on error.
void unlock();
+
/// @cond
- private:
+ internal_mutex_type &internal_mutex()
+ { return m_mutex; }
- #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
- #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
- friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
- void take_ownership(){ mutex.take_ownership(); }
- ipcdetail::spin_mutex mutex;
- #elif defined(BOOST_INTERPROCESS_USE_POSIX)
- #undef BOOST_INTERPROCESS_USE_POSIX
- ipcdetail::posix_mutex mutex;
- #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
- #undef BOOST_INTERPROCESS_USE_WINDOWS
- ipcdetail::windows_mutex mutex;
- #else
- #error "Unknown platform for interprocess_mutex"
- #endif
+ const internal_mutex_type &internal_mutex() const
+ { return m_mutex; }
+
+ private:
+ internal_mutex_type m_mutex;
/// @endcond
};
@@ -144,23 +156,25 @@
boost::posix_time::ptime wait_time
= boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
- if (!mutex.timed_lock(wait_time))
+ 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?");
+ throw interprocess_exception(timeout_when_locking_error
+ , "Interprocess mutex timeout when locking. Possible deadlock: "
+ "owner died without unlocking?");
}
#else
- mutex.lock();
+ m_mutex.lock();
#endif
}
inline bool interprocess_mutex::try_lock()
-{ return mutex.try_lock(); }
+{ return m_mutex.try_lock(); }
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{ return mutex.timed_lock(abs_time); }
+{ return m_mutex.timed_lock(abs_time); }
inline void interprocess_mutex::unlock()
-{ mutex.unlock(); }
+{ m_mutex.unlock(); }
} //namespace interprocess {
} //namespace boost {
Added: trunk/boost/interprocess/sync/interprocess_sharable_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/interprocess_sharable_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,337 @@
+//////////////////////////////////////////////////////////////////////////////
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/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();
+
+ /// @cond
+ 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_upr_shar : 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;
+ /// @endcond
+};
+
+/// @cond
+
+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_upr_shar = 0;
+}
+
+inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
+{}
+
+inline void interprocess_sharable_mutex::lock()
+{
+ scoped_lock_t lock(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(lock);
+ }
+
+ //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(lock);
+ }
+ rollback.release();
+}
+
+inline bool interprocess_sharable_mutex::try_lock()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+
+ //If we can't lock or any has there is any exclusive
+ //or sharable mark return false;
+ if(!lock.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_sharable_mutex::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ scoped_lock_t lock(m_mut, abs_time);
+ if(!lock.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){
+ if(!this->m_first_gate.timed_wait(lock, abs_time))
+ return !this->m_ctrl.exclusive_in;
+ }
+
+ //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(lock, abs_time)){
+ return !(this->m_ctrl.num_upr_shar);
+ }
+ }
+ rollback.release();
+ return true;
+}
+
+inline void interprocess_sharable_mutex::unlock()
+{
+ scoped_lock_t lock(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 lock(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(lock);
+ }
+
+ //Increment sharable count
+ ++this->m_ctrl.num_upr_shar;
+}
+
+inline bool interprocess_sharable_mutex::try_lock_sharable()
+{
+ scoped_lock_t lock(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(!lock.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_sharable_mutex::timed_lock_sharable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
+ scoped_lock_t lock(m_mut, abs_time);
+ if(!lock.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(lock, abs_time)){
+ return!(this->m_ctrl.exclusive_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers);
+ }
+ }
+
+ //Increment sharable count
+ ++this->m_ctrl.num_upr_shar;
+ return true;
+}
+
+inline void interprocess_sharable_mutex::unlock_sharable()
+{
+ scoped_lock_t lock(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();
+ }
+}
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
Modified: trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -594,6 +594,10 @@
inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->unlock_upgradable_and_lock();
+ return true;
+ }
scoped_lock_t lock(m_mut, abs_time);
if(!lock.owns()) return false;
Modified: trunk/boost/interprocess/sync/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/named_condition.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -22,6 +22,7 @@
#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
@@ -153,24 +154,38 @@
template <typename L>
inline void named_condition::wait(L& lock)
-{ m_cond.wait(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)
-{ m_cond.wait(lock, 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)
-{ return m_cond.timed_wait(lock, 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)
-{ return m_cond.timed_wait(lock, abs_time, 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); }
+{
+ return condition_type::remove(name);
+}
/// @endcond
Added: trunk/boost/interprocess/sync/named_condition_any.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/named_condition_any.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,151 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/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 {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+//! 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
+{
+ /// @cond
+ //Non-copyable
+ named_condition_any();
+ named_condition_any(const named_condition_any &);
+ named_condition_any &operator=(const named_condition_any &);
+ /// @endcond
+ 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); }
+
+ /// @cond
+ 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); }
+ /// @endcond
+};
+
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP
Modified: trunk/boost/interprocess/sync/named_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -108,21 +108,20 @@
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
+ public:
#if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES)
- typedef ipcdetail::posix_named_mutex impl_t;
- impl_t m_mut;
+ 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 impl_t;
- impl_t m_mut;
+ typedef ipcdetail::windows_named_mutex internal_mutex_type;
#undef BOOST_INTERPROCESS_USE_WINDOWS
#else
- typedef ipcdetail::shm_named_mutex impl_t;
- impl_t m_mut;
- public:
- interprocess_mutex *mutex() const
- { return m_mut.mutex(); }
+ typedef ipcdetail::shm_named_mutex internal_mutex_type;
#endif
+ internal_mutex_type &internal_mutex()
+ { return m_mut; }
+
+ internal_mutex_type m_mut;
/// @endcond
};
@@ -160,7 +159,7 @@
{ return m_mut.timed_lock(abs_time); }
inline bool named_mutex::remove(const char *name)
-{ return impl_t::remove(name); }
+{ return internal_mutex_type::remove(name); }
/// @endcond
Added: trunk/boost/interprocess/sync/named_sharable_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/named_sharable_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,231 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/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 {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+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
+{
+ /// @cond
+ //Non-copyable
+ named_sharable_mutex();
+ named_sharable_mutex(const named_sharable_mutex &);
+ named_sharable_mutex &operator=(const named_sharable_mutex &);
+ /// @endcond
+ 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);
+
+ /// @cond
+ 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()); }
+
+ ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::named_creation_functor<interprocess_sharable_mutex> construct_func_t;
+ /// @endcond
+};
+
+/// @cond
+
+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) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ 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) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ 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); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP
Modified: trunk/boost/interprocess/sync/named_upgradable_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_upgradable_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_upgradable_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -56,7 +56,7 @@
//!If the upgradable mutex can't be created throws interprocess_exception
named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
- //!Opens or creates a global upgradable mutex with a name, and an initial count.
+ //!Opens or creates a global upgradable mutex with a name.
//!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
@@ -215,6 +215,12 @@
//!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.
@@ -288,13 +294,7 @@
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- return this->mutex()->timed_lock(abs_time);
-}
+{ return this->mutex()->timed_lock(abs_time); }
inline void named_upgradable_mutex::lock_upgradable()
{ this->mutex()->lock_upgradable(); }
@@ -307,13 +307,7 @@
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_upgradable();
- return true;
- }
- return this->mutex()->timed_lock_upgradable(abs_time);
-}
+{ return this->mutex()->timed_lock_upgradable(abs_time); }
inline void named_upgradable_mutex::lock_sharable()
{ this->mutex()->lock_sharable(); }
@@ -326,13 +320,7 @@
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock_sharable();
- return true;
- }
- return this->mutex()->timed_lock_sharable(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(); }
Modified: trunk/boost/interprocess/sync/shm/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/shm/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/shm/named_condition.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -29,8 +29,11 @@
#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/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
@@ -122,106 +125,35 @@
/// @cond
private:
- struct condition_holder
- {
- interprocess_condition cond_;
- //If named_mutex is implemented using semaphores
- //we need to store an additional mutex
- #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- interprocess_mutex mutex_;
- #endif
- };
-
- interprocess_condition *condition() const
- { return &static_cast<condition_holder*>(m_shmem.get_user_address())->cond_; }
-
- template <class Lock>
- class lock_inverter
+ #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+ class internal_condition_members
{
- Lock &l_;
public:
- lock_inverter(Lock &l)
- : l_(l)
- {}
- void lock() { l_.unlock(); }
- void unlock() { l_.lock(); }
+ 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;
};
- //If named mutex uses POSIX semaphores, then the shm based condition variable
- //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t
- //instance needed by pthread_mutex_cond_t
- #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- interprocess_mutex *mutex() const
- { return &static_cast<condition_holder*>(m_shmem.get_user_address())->mutex_; }
-
- template <class Lock>
- void do_wait(Lock& lock)
- {
- //shm_named_condition only works with named_mutex
- BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true));
-
- //lock internal before unlocking external to avoid race with a notifier
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
-
- //unlock internal first to avoid deadlock with near simultaneous waits
- scoped_lock<interprocess_mutex> internal_unlock;
- internal_lock.swap(internal_unlock);
- this->condition()->wait(internal_unlock);
- }
-
- template <class Lock>
- bool do_timed_wait(Lock& lock, const boost::posix_time::ptime &abs_time)
- {
- //shm_named_condition only works with named_mutex
- BOOST_STATIC_ASSERT((is_convertible<typename Lock::mutex_type&, named_mutex&>::value == true));
- //lock internal before unlocking external to avoid race with a notifier
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time);
- if(!internal_lock) return false;
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
-
- //unlock internal first to avoid deadlock with near simultaneous waits
- scoped_lock<interprocess_mutex> internal_unlock;
- internal_lock.swap(internal_unlock);
- return this->condition()->timed_wait(internal_unlock, abs_time);
- }
- #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- template<class Lock>
- class lock_wrapper
- {
- typedef void (lock_wrapper::*unspecified_bool_type)();
- public:
-
- typedef interprocess_mutex mutex_type;
-
- lock_wrapper(Lock &l)
- : l_(l)
- {}
-
- mutex_type* mutex() const
- { return l_.mutex()->mutex(); }
-
- void lock() { l_.lock(); }
-
- void unlock() { l_.unlock(); }
-
- operator unspecified_bool_type() const
- { return l_ ? &lock_wrapper::lock : 0; }
-
- private:
- Lock &l_;
- };
+ 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 m_cond;
+
friend class boost::interprocess::ipcdetail::interprocess_tester;
void dont_close_on_destruction();
managed_open_or_create_impl<shared_memory_object> m_shmem;
template <class T, class Arg> friend class boost::interprocess::ipcdetail::named_creation_functor;
- typedef boost::interprocess::ipcdetail::named_creation_functor<condition_holder> construct_func_t;
+ typedef boost::interprocess::ipcdetail::named_creation_functor<internal_condition> construct_func_t;
/// @endcond
};
@@ -233,7 +165,7 @@
inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm)
: m_shmem (create_only
,name
- ,sizeof(condition_holder) +
+ ,sizeof(internal_condition) +
managed_open_or_create_impl<shared_memory_object>::
ManagedOpenOrCreateUserOffset
,read_write
@@ -245,7 +177,7 @@
inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm)
: m_shmem (open_or_create
,name
- ,sizeof(condition_holder) +
+ ,sizeof(internal_condition) +
managed_open_or_create_impl<shared_memory_object>::
ManagedOpenOrCreateUserOffset
,read_write
@@ -268,102 +200,65 @@
#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
inline void shm_named_condition::notify_one()
-{
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- this->condition()->notify_one();
-}
+{ m_cond.notify_one(); }
inline void shm_named_condition::notify_all()
-{
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
- this->condition()->notify_all();
-}
+{ m_cond.notify_all(); }
template <typename L>
inline void shm_named_condition::wait(L& lock)
-{
- if (!lock)
- throw lock_exception();
- this->do_wait(lock);
-}
+{ m_cond.wait(lock); }
template <typename L, typename Pr>
inline void shm_named_condition::wait(L& lock, Pr pred)
-{
- if (!lock)
- throw lock_exception();
- while (!pred())
- this->do_wait(lock);
-}
+{ m_cond.wait(lock, pred); }
template <typename L>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(lock, abs_time);
-}
+{ return m_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)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
-
- while (!pred()){
- if(!this->do_timed_wait(lock, abs_time)){
- return pred();
- }
- }
- return true;
-}
+{ return m_cond.timed_wait(lock, abs_time, pred); }
#else
inline void shm_named_condition::notify_one()
-{ this->condition()->notify_one(); }
+{ m_cond.notify_one(); }
inline void shm_named_condition::notify_all()
-{ this->condition()->notify_all(); }
+{ m_cond.notify_all(); }
template <typename L>
inline void shm_named_condition::wait(L& lock)
{
- lock_wrapper<L> newlock(lock);
- this->condition()->wait(newlock);
+ internal_mutex_lock<L> internal_lock(lock);
+ m_cond.wait(internal_lock);
}
template <typename L, typename Pr>
inline void shm_named_condition::wait(L& lock, Pr pred)
{
- lock_wrapper<L> newlock(lock);
- this->condition()->wait(newlock, pred);
+ internal_mutex_lock<L> internal_lock(lock);
+ m_cond.wait(internal_lock, pred);
}
template <typename L>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
{
- lock_wrapper<L> newlock(lock);
- return this->condition()->timed_wait(newlock, abs_time);
+ internal_mutex_lock<L> internal_lock(lock);
+ return m_cond.timed_wait(internal_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)
{
- lock_wrapper<L> newlock(lock);
- return this->condition()->timed_wait(newlock, abs_time, pred);
+ internal_mutex_lock<L> internal_lock(lock);
+ return m_cond.timed_wait(internal_lock, abs_time, pred);
}
#endif
Added: trunk/boost/interprocess/sync/shm/named_condition_any.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/shm/named_condition_any.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,192 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/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 {
+
+/// @cond
+class interprocess_tester;
+/// @endcond
+
+//! 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
+{
+ /// @cond
+ //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 &);
+ /// @endcond
+ 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) +
+ managed_open_or_create_impl<shared_memory_object>::
+ 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) +
+ managed_open_or_create_impl<shared_memory_object>::
+ 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); }
+
+ /// @cond
+ 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); }
+
+ managed_open_or_create_impl<shared_memory_object> 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;
+ /// @endcond
+};
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP
Modified: trunk/boost/interprocess/sync/shm/named_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/shm/named_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/shm/named_mutex.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -100,8 +100,9 @@
static bool remove(const char *name);
/// @cond
- interprocess_mutex *mutex() const
- { return static_cast<interprocess_mutex*>(m_shmem.get_user_address()); }
+ 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;
@@ -153,13 +154,13 @@
{}
inline void shm_named_mutex::lock()
-{ this->mutex()->lock(); }
+{ this->internal_mutex().lock(); }
inline void shm_named_mutex::unlock()
-{ this->mutex()->unlock(); }
+{ this->internal_mutex().unlock(); }
inline bool shm_named_mutex::try_lock()
-{ return this->mutex()->try_lock(); }
+{ return this->internal_mutex().try_lock(); }
inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
@@ -167,7 +168,7 @@
this->lock();
return true;
}
- return this->mutex()->timed_lock(abs_time);
+ return this->internal_mutex().timed_lock(abs_time);
}
inline bool shm_named_mutex::remove(const char *name)
Modified: trunk/boost/interprocess/sync/windows/condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/condition.hpp (original)
+++ trunk/boost/interprocess/sync/windows/condition.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -33,63 +33,34 @@
windows_condition &operator=(const windows_condition &);
public:
- windows_condition();
- ~windows_condition();
+ windows_condition()
+ : m_condition_data()
+ {}
- void notify_one();
- void notify_all();
+ ~windows_condition()
+ {}
+
+ 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)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
- }
+ { 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)
- {
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
- while (!pred()){
- if (!this->do_timed_wait(abs_time, *lock.mutex()))
- return pred();
- }
- return true;
- }
+ { return m_condition_data.timed_wait(lock, abs_time, pred); }
template <typename L>
void wait(L& lock)
- {
- if (!lock)
- throw lock_exception();
- do_wait(*lock.mutex());
- }
+ { m_condition_data.wait(lock); }
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);
+ { m_condition_data.wait(lock, pred); }
private:
@@ -132,33 +103,11 @@
windows_semaphore m_sem_block_queue;
windows_semaphore m_sem_block_lock;
windows_mutex m_mtx_unblock_lock;
- } m_condition_data;
+ };
- typedef condition_algorithm_8a<condition_data> algorithm_type;
+ ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
};
-inline windows_condition::windows_condition()
- : m_condition_data()
-{}
-
-inline windows_condition::~windows_condition()
-{}
-
-inline void windows_condition::notify_one()
-{ algorithm_type::signal(m_condition_data, false); }
-
-inline void windows_condition::notify_all()
-{ algorithm_type::signal(m_condition_data, true); }
-
-template<class InterprocessMutex>
-inline void windows_condition::do_wait(InterprocessMutex &mut)
-{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
-
-template<class InterprocessMutex>
-inline bool windows_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
-
} //namespace ipcdetail
} //namespace interprocess
} //namespace boost
Modified: trunk/boost/interprocess/sync/windows/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/windows/named_condition.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -17,313 +17,13 @@
#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>
+#include <boost/interprocess/sync/windows/named_condition_any.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
-class windows_named_condition
-{
- /// @cond
-
- //Non-copyable
- windows_named_condition();
- windows_named_condition(const windows_named_condition &);
- windows_named_condition &operator=(const windows_named_condition &);
- /// @endcond
-
- public:
- windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions());
-
- windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions());
-
- windows_named_condition(open_only_t, const char *name);
-
- ~windows_named_condition();
-
- //!If there is a thread waiting on *this, change that
- //!thread's state to ready. Otherwise there is no effect.*/
- void notify_one();
-
- //!Change the state of all threads waiting on *this to ready.
- //!If there are no waiting threads, notify_all() has no effect.
- void notify_all();
-
- //!Releases the lock on the named_mutex object associated with lock, blocks
- //!the current thread of execution until readied by a call to
- //!this->notify_one() or this->notify_all(), and then reacquires the lock.
- template <typename L>
- void wait(L& lock);
-
- //!The same as:
- //!while (!pred()) wait(lock)
- template <typename L, typename Pr>
- void wait(L& lock, Pr pred);
-
- //!Releases the lock on the named_mutex object associated with lock, blocks
- //!the current thread of execution until readied by a call to
- //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
- //!and then reacquires the lock.
- //!Returns: false if time abs_time is reached, otherwise true.
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
-
- //!The same as: while (!pred()) {
- //! if (!timed_wait(lock, abs_time)) return pred();
- //! } return true;
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
-
- static bool remove(const char *name);
-
- /// @cond
- private:
- friend class interprocess_tester;
- void dont_close_on_destruction();
-
- template <class InterprocessMutex>
- void do_wait(InterprocessMutex& lock);
-
- template <class InterprocessMutex>
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock);
-
- struct condition_data
- {
- typedef boost::int32_t integer_type;
- typedef winapi_semaphore_wrapper semaphore_type;
- typedef winapi_mutex_wrapper mutex_type;
-
- integer_type &get_nwaiters_blocked()
- { return m_nwaiters_blocked; }
-
- integer_type &get_nwaiters_gone()
- { return m_nwaiters_gone; }
-
- integer_type &get_nwaiters_to_unblock()
- { return m_nwaiters_to_unblock; }
-
- semaphore_type &get_sem_block_queue()
- { return m_sem_block_queue; }
-
- semaphore_type &get_sem_block_lock()
- { return m_sem_block_lock; }
-
- mutex_type &get_mtx_unblock_lock()
- { return m_mtx_unblock_lock; }
-
- integer_type m_nwaiters_blocked;
- integer_type m_nwaiters_gone;
- integer_type m_nwaiters_to_unblock;
- winapi_semaphore_wrapper m_sem_block_queue;
- winapi_semaphore_wrapper m_sem_block_lock;
- winapi_mutex_wrapper m_mtx_unblock_lock;
- } m_condition_data;
-
- typedef condition_algorithm_8a<condition_data> algorithm_type;
-
- class named_cond_callbacks : public windows_named_sync_interface
- {
- typedef __int64 sem_count_t;
- mutable sem_count_t sem_counts [2];
-
- public:
- named_cond_callbacks(condition_data &cond_data)
- : m_condition_data(cond_data)
- {}
-
- virtual std::size_t get_data_size() const
- { return sizeof(sem_counts); }
-
- virtual const void *buffer_with_final_data_to_file()
- {
- sem_counts[0] = m_condition_data.m_sem_block_queue.value();
- sem_counts[1] = m_condition_data.m_sem_block_lock.value();
- return &sem_counts;
- }
-
- virtual const void *buffer_with_init_data_to_file()
- {
- sem_counts[0] = 0;
- sem_counts[1] = 1;
- return &sem_counts;
- }
-
- virtual void *buffer_to_store_init_data_from_file()
- { return &sem_counts; }
-
- virtual bool open(create_enum_t, const char *id_name)
- {
- m_condition_data.m_nwaiters_blocked = 0;
- m_condition_data.m_nwaiters_gone = 0;
- m_condition_data.m_nwaiters_to_unblock = 0;
-
- //Now open semaphores and mutex.
- //Use local variables + swap to guarantee consistent
- //initialization and cleanup in case any opening fails
- permissions perm;
- perm.set_unrestricted();
- std::string aux_str = "Global\\bipc.cond.";
- aux_str += id_name;
- std::size_t pos = aux_str.size();
-
- //sem_block_queue
- aux_str += "_bq";
- winapi_semaphore_wrapper sem_block_queue;
- bool created;
- if(!sem_block_queue.open_or_create
- (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created))
- return false;
- aux_str.erase(pos);
-
- //sem_block_lock
- aux_str += "_bl";
- winapi_semaphore_wrapper sem_block_lock;
- if(!sem_block_lock.open_or_create
- (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created))
- return false;
- aux_str.erase(pos);
-
- //mtx_unblock_lock
- aux_str += "_ul";
- winapi_mutex_wrapper mtx_unblock_lock;
- if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm))
- return false;
-
- //All ok, commit data
- m_condition_data.m_sem_block_queue.swap(sem_block_queue);
- m_condition_data.m_sem_block_lock.swap(sem_block_lock);
- m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock);
- return true;
- }
-
- virtual void close()
- {
- m_condition_data.m_sem_block_queue.close();
- m_condition_data.m_sem_block_lock.close();
- m_condition_data.m_mtx_unblock_lock.close();
- m_condition_data.m_nwaiters_blocked = 0;
- m_condition_data.m_nwaiters_gone = 0;
- m_condition_data.m_nwaiters_to_unblock = 0;
- }
-
- virtual ~named_cond_callbacks()
- {}
-
- private:
- condition_data &m_condition_data;
- };
-
- windows_named_sync m_named_sync;
- /// @endcond
-};
-
-inline windows_named_condition::~windows_named_condition()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.close(callbacks);
-}
-
-inline void windows_named_condition::dont_close_on_destruction()
-{}
-
-inline windows_named_condition::windows_named_condition
- (create_only_t, const char *name, const permissions &perm)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
-}
-
-inline windows_named_condition::windows_named_condition
- (open_or_create_t, const char *name, const permissions &perm)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
-}
-
-inline windows_named_condition::windows_named_condition(open_only_t, const char *name)
- : m_condition_data()
-{
- named_cond_callbacks callbacks(m_condition_data);
- m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
-}
-
-inline void windows_named_condition::notify_one()
-{ algorithm_type::signal(m_condition_data, false); }
-
-inline void windows_named_condition::notify_all()
-{ algorithm_type::signal(m_condition_data, true); }
-
-template<class InterprocessMutex>
-inline void windows_named_condition::do_wait(InterprocessMutex &mut)
-{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
-
-template<class InterprocessMutex>
-inline bool windows_named_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
-
-template <typename L>
-inline void windows_named_condition::wait(L& lock)
-{
- if (!lock)
- throw lock_exception();
- this->do_wait(*lock.mutex());
-}
-
-template <typename L, typename Pr>
-inline void windows_named_condition::wait(L& lock, Pr pred)
-{
- if (!lock)
- throw lock_exception();
- while (!pred())
- this->do_wait(*lock.mutex());
-}
-
-template <typename L>
-inline bool windows_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock);
- return true;
- }
- if (!lock)
- throw lock_exception();
- return this->do_timed_wait(abs_time, *lock.mutex());
-}
-
-template <typename L, typename Pr>
-inline bool windows_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait(lock, pred);
- return true;
- }
- if (!lock)
- throw lock_exception();
-
- while (!pred()){
- if(!this->do_timed_wait(abs_time, *lock.mutex())){
- return pred();
- }
- }
- return true;
-}
-
-inline bool windows_named_condition::remove(const char *name)
-{
- return windows_named_sync::remove(name);
-}
+typedef windows_named_condition_any windows_named_condition;
} //namespace ipcdetail {
} //namespace interprocess {
Added: trunk/boost/interprocess/sync/windows/named_condition_any.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_condition_any.hpp 2012-08-22 17:03:11 EDT (Wed, 22 Aug 2012)
@@ -0,0 +1,241 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/named_sync.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_named_condition_any
+{
+ /// @cond
+
+ //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 &);
+ /// @endcond
+
+ 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); }
+
+ /// @cond
+ private:
+
+ void windows_named_condition_any::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;
+ };
+
+ ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
+
+ class named_cond_callbacks : public windows_named_sync_interface
+ {
+ typedef __int64 sem_count_t;
+ mutable sem_count_t sem_counts [2];
+
+ public:
+ named_cond_callbacks(condition_data &cond_data)
+ : m_condition_data(cond_data)
+ {}
+
+ virtual std::size_t get_data_size() const
+ { return sizeof(sem_counts); }
+
+ virtual const void *buffer_with_final_data_to_file()
+ {
+ sem_counts[0] = m_condition_data.m_sem_block_queue.value();
+ sem_counts[1] = m_condition_data.m_sem_block_lock.value();
+ return &sem_counts;
+ }
+
+ virtual const void *buffer_with_init_data_to_file()
+ {
+ sem_counts[0] = 0;
+ sem_counts[1] = 1;
+ return &sem_counts;
+ }
+
+ virtual void *buffer_to_store_init_data_from_file()
+ { return &sem_counts; }
+
+ virtual bool open(create_enum_t, const char *id_name)
+ {
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+
+ //Now open semaphores and mutex.
+ //Use local variables + swap to guarantee consistent
+ //initialization and cleanup in case any opening fails
+ permissions perm;
+ perm.set_unrestricted();
+ std::string aux_str = "Global\\bipc.cond.";
+ aux_str += id_name;
+ std::size_t pos = aux_str.size();
+
+ //sem_block_queue
+ aux_str += "_bq";
+ winapi_semaphore_wrapper sem_block_queue;
+ bool created;
+ if(!sem_block_queue.open_or_create
+ (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created))
+ return false;
+ aux_str.erase(pos);
+
+ //sem_block_lock
+ aux_str += "_bl";
+ winapi_semaphore_wrapper sem_block_lock;
+ if(!sem_block_lock.open_or_create
+ (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created))
+ return false;
+ aux_str.erase(pos);
+
+ //mtx_unblock_lock
+ aux_str += "_ul";
+ winapi_mutex_wrapper mtx_unblock_lock;
+ if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm))
+ return false;
+
+ //All ok, commit data
+ m_condition_data.m_sem_block_queue.swap(sem_block_queue);
+ m_condition_data.m_sem_block_lock.swap(sem_block_lock);
+ m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock);
+ return true;
+ }
+
+ virtual void close()
+ {
+ m_condition_data.m_sem_block_queue.close();
+ m_condition_data.m_sem_block_lock.close();
+ m_condition_data.m_mtx_unblock_lock.close();
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+ }
+
+ virtual ~named_cond_callbacks()
+ {}
+
+ private:
+ condition_data &m_condition_data;
+ };
+
+ windows_named_sync m_named_sync;
+ /// @endcond
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk