summaryrefslogtreecommitdiff
path: root/boost/interprocess/sync
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/interprocess/sync
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/interprocess/sync')
-rw-r--r--boost/interprocess/sync/file_lock.hpp305
-rw-r--r--boost/interprocess/sync/interprocess_condition.hpp172
-rw-r--r--boost/interprocess/sync/interprocess_mutex.hpp170
-rw-r--r--boost/interprocess/sync/interprocess_recursive_mutex.hpp177
-rw-r--r--boost/interprocess/sync/interprocess_semaphore.hpp145
-rw-r--r--boost/interprocess/sync/interprocess_upgradable_mutex.hpp659
-rw-r--r--boost/interprocess/sync/lock_options.hpp55
-rw-r--r--boost/interprocess/sync/mutex_family.hpp56
-rw-r--r--boost/interprocess/sync/named_condition.hpp172
-rw-r--r--boost/interprocess/sync/named_mutex.hpp163
-rw-r--r--boost/interprocess/sync/named_recursive_mutex.hpp154
-rw-r--r--boost/interprocess/sync/named_semaphore.hpp168
-rw-r--r--boost/interprocess/sync/named_upgradable_mutex.hpp372
-rw-r--r--boost/interprocess/sync/null_mutex.hpp147
-rw-r--r--boost/interprocess/sync/posix/condition.hpp191
-rw-r--r--boost/interprocess/sync/posix/mutex.hpp152
-rw-r--r--boost/interprocess/sync/posix/named_mutex.hpp116
-rw-r--r--boost/interprocess/sync/posix/named_semaphore.hpp84
-rw-r--r--boost/interprocess/sync/posix/pthread_helpers.hpp168
-rw-r--r--boost/interprocess/sync/posix/ptime_to_timespec.hpp38
-rw-r--r--boost/interprocess/sync/posix/recursive_mutex.hpp142
-rw-r--r--boost/interprocess/sync/posix/semaphore.hpp63
-rw-r--r--boost/interprocess/sync/posix/semaphore_wrapper.hpp211
-rw-r--r--boost/interprocess/sync/scoped_lock.hpp372
-rw-r--r--boost/interprocess/sync/sharable_lock.hpp305
-rw-r--r--boost/interprocess/sync/shm/named_condition.hpp379
-rw-r--r--boost/interprocess/sync/shm/named_creation_functor.hpp68
-rw-r--r--boost/interprocess/sync/shm/named_mutex.hpp184
-rw-r--r--boost/interprocess/sync/shm/named_recursive_mutex.hpp175
-rw-r--r--boost/interprocess/sync/shm/named_semaphore.hpp141
-rw-r--r--boost/interprocess/sync/shm/named_upgradable_mutex.hpp372
-rw-r--r--boost/interprocess/sync/spin/condition.hpp295
-rw-r--r--boost/interprocess/sync/spin/interprocess_barrier.hpp46
-rw-r--r--boost/interprocess/sync/spin/mutex.hpp114
-rw-r--r--boost/interprocess/sync/spin/recursive_mutex.hpp175
-rw-r--r--boost/interprocess/sync/spin/semaphore.hpp110
-rw-r--r--boost/interprocess/sync/upgradable_lock.hpp309
-rw-r--r--boost/interprocess/sync/windows/condition.hpp383
-rw-r--r--boost/interprocess/sync/windows/mutex.hpp137
-rw-r--r--boost/interprocess/sync/windows/recursive_mutex.hpp43
-rw-r--r--boost/interprocess/sync/windows/semaphore.hpp137
-rw-r--r--boost/interprocess/sync/windows/sync_utils.hpp173
-rw-r--r--boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp193
-rw-r--r--boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp116
-rw-r--r--boost/interprocess/sync/xsi/xsi_named_mutex.hpp228
45 files changed, 8535 insertions, 0 deletions
diff --git a/boost/interprocess/sync/file_lock.hpp b/boost/interprocess/sync/file_lock.hpp
new file mode 100644
index 0000000000..a60b814a4f
--- /dev/null
+++ b/boost/interprocess/sync/file_lock.hpp
@@ -0,0 +1,305 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_FILE_LOCK_HPP
+#define BOOST_INTERPROCESS_FILE_LOCK_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/exceptions.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/move/move.hpp>
+
+//!\file
+//!Describes a class that wraps file locking capabilities.
+
+namespace boost {
+namespace interprocess {
+
+
+//!A file lock, is a mutual exclusion utility similar to a mutex using a
+//!file. A file lock has sharable and exclusive locking capabilities and
+//!can be used with scoped_lock and sharable_lock classes.
+//!A file lock can't guarantee synchronization between threads of the same
+//!process so just use file locks to synchronize threads from different processes.
+class file_lock
+{
+ /// @cond
+ //Non-copyable
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock)
+ /// @endcond
+
+ public:
+ //!Constructs an empty file mapping.
+ //!Does not throw
+ file_lock()
+ : m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
+ {}
+
+ //!Opens a file lock. Throws interprocess_exception if the file does not
+ //!exist or there are no operating system resources.
+ file_lock(const char *name);
+
+ //!Moves the ownership of "moved"'s file mapping object to *this.
+ //!After the call, "moved" does not represent any file mapping object.
+ //!Does not throw
+ file_lock(BOOST_RV_REF(file_lock) moved)
+ : m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
+ { this->swap(moved); }
+
+ //!Moves the ownership of "moved"'s file mapping to *this.
+ //!After the call, "moved" does not represent any file mapping.
+ //!Does not throw
+ file_lock &operator=(BOOST_RV_REF(file_lock) moved)
+ {
+ file_lock tmp(boost::move(moved));
+ this->swap(tmp);
+ return *this;
+ }
+
+ //!Closes a file lock. Does not throw.
+ ~file_lock();
+
+ //!Swaps two file_locks.
+ //!Does not throw.
+ void swap(file_lock &other)
+ {
+ file_handle_t tmp = m_file_hnd;
+ m_file_hnd = other.m_file_hnd;
+ other.m_file_hnd = tmp;
+ }
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive, or sharable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive, or sharable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive, or sharable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex, waits until
+ //! it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership of the
+ //! mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive ownership of
+ //! the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+ /// @cond
+ private:
+ file_handle_t m_file_hnd;
+
+ bool timed_acquire_file_lock
+ (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
+ {
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+ using namespace boost::detail;
+
+ if(now >= abs_time) return false;
+
+ do{
+ if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
+ return false;
+
+ if(acquired)
+ return true;
+ else{
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ acquired = false;
+ return true;
+ }
+ // relinquish current time slice
+ ipcdetail::thread_yield();
+ }
+ }while (true);
+ }
+
+ bool timed_acquire_file_lock_sharable
+ (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
+ {
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+ using namespace boost::detail;
+
+ if(now >= abs_time) return false;
+
+ do{
+ if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
+ return false;
+
+ if(acquired)
+ return true;
+ else{
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ acquired = false;
+ return true;
+ }
+ // relinquish current time slice
+ ipcdetail::thread_yield();
+ }
+ }while (true);
+ }
+ /// @endcond
+};
+
+inline file_lock::file_lock(const char *name)
+{
+ m_file_hnd = ipcdetail::open_existing_file(name, read_write);
+
+ if(m_file_hnd == ipcdetail::invalid_file()){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+}
+
+inline file_lock::~file_lock()
+{
+ if(m_file_hnd != ipcdetail::invalid_file()){
+ ipcdetail::close_file(m_file_hnd);
+ m_file_hnd = ipcdetail::invalid_file();
+ }
+}
+
+inline void file_lock::lock()
+{
+ if(!ipcdetail::acquire_file_lock(m_file_hnd)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool file_lock::try_lock()
+{
+ bool result;
+ if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+ return result;
+}
+
+inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ bool result;
+ if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+ return result;
+}
+
+inline void file_lock::unlock()
+{
+ if(!ipcdetail::release_file_lock(m_file_hnd)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+}
+
+inline void file_lock::lock_sharable()
+{
+ if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool file_lock::try_lock_sharable()
+{
+ bool result;
+ if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+ return result;
+}
+
+inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
+ bool result;
+ if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+ return result;
+}
+
+inline void file_lock::unlock_sharable()
+{
+ if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){
+ error_info err(system_error_code());
+ throw interprocess_exception(err);
+ }
+}
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_FILE_LOCK_HPP
diff --git a/boost/interprocess/sync/interprocess_condition.hpp b/boost/interprocess/sync/interprocess_condition.hpp
new file mode 100644
index 0000000000..b0e74fc342
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_condition.hpp
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONDITION_HPP
+#define BOOST_INTERPROCESS_CONDITION_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/exceptions.hpp>
+#include <boost/limits.hpp>
+#include <boost/assert.hpp>
+
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
+ #include <boost/interprocess/sync/posix/condition.hpp>
+ #define BOOST_INTERPROCESS_USE_POSIX
+//Experimental...
+//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+// #include <boost/interprocess/sync/windows/condition.hpp>
+// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ #include <boost/interprocess/sync/spin/condition.hpp>
+ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+#endif
+
+/// @endcond
+
+//!\file
+//!Describes process-shared variables interprocess_condition class
+
+namespace boost {
+
+namespace posix_time
+{ class ptime; }
+
+namespace interprocess {
+
+class named_condition;
+
+//!This class is a condition variable that can be placed in shared memory or
+//!memory mapped files.
+class interprocess_condition
+{
+ /// @cond
+ //Non-copyable
+ interprocess_condition(const interprocess_condition &);
+ interprocess_condition &operator=(const interprocess_condition &);
+ friend class named_condition;
+ /// @endcond
+ public:
+ //!Constructs a interprocess_condition. On error throws interprocess_exception.
+ interprocess_condition(){}
+
+ //!Destroys *this
+ //!liberating system resources.
+ ~interprocess_condition(){}
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.
+ void notify_one()
+ { m_condition.notify_one(); }
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all()
+ { m_condition.notify_all(); }
+
+ //!Releases the lock on the interprocess_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ this->do_wait(*lock.mutex());
+ }
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ this->do_wait(*lock.mutex());
+ }
+
+ //!Releases the lock on the 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)
+ {
+ 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());
+ }
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if(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;
+ }
+
+ /// @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
+ ipcdetail::spin_condition m_condition;
+ #elif defined(BOOST_INTERPROCESS_USE_POSIX)
+ #undef BOOST_INTERPROCESS_USE_POSIX
+ ipcdetail::posix_condition m_condition;
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ ipcdetail::windows_condition m_condition;
+ #else
+ #error "Unknown platform for interprocess_mutex"
+ #endif
+ /// @endcond
+};
+
+} //namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_CONDITION_HPP
diff --git a/boost/interprocess/sync/interprocess_mutex.hpp b/boost/interprocess/sync/interprocess_mutex.hpp
new file mode 100644
index 0000000000..478cf78cc3
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_mutex.hpp
@@ -0,0 +1,170 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Parts of the pthread code come from Boost Threads code.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MUTEX_HPP
+#define BOOST_INTERPROCESS_MUTEX_HPP
+
+/// @cond
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/assert.hpp>
+
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
+ #include <boost/interprocess/sync/posix/mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_POSIX
+//Experimental...
+//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+// #include <boost/interprocess/sync/windows/mutex.hpp>
+// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ #include <boost/interprocess/sync/spin/mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+namespace robust_emulation_helpers {
+
+template<class T>
+class mutex_traits;
+
+}}}}
+
+#endif
+
+/// @endcond
+
+//!\file
+//!Describes a mutex class that can be placed in memory shared by
+//!several processes.
+
+namespace boost {
+namespace interprocess {
+
+class interprocess_condition;
+
+//!Wraps a interprocess_mutex that can be placed in shared memory and can be
+//!shared between processes. Allows timed lock tries
+class interprocess_mutex
+{
+ /// @cond
+ //Non-copyable
+ interprocess_mutex(const interprocess_mutex &);
+ interprocess_mutex &operator=(const interprocess_mutex &);
+ friend class interprocess_condition;
+ /// @endcond
+ public:
+
+ //!Constructor.
+ //!Throws interprocess_exception on error.
+ interprocess_mutex();
+
+ //!Destructor. If any process uses the mutex after the destructor is called
+ //!the result is undefined. Does not throw.
+ ~interprocess_mutex();
+
+ //!Effects: The calling thread tries to obtain ownership of the mutex, and
+ //! if another thread has ownership of the mutex, it waits until it can
+ //! obtain the ownership. If a thread takes ownership of the mutex the
+ //! mutex must be unlocked by the same mutex.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to obtain ownership of the mutex, and
+ //! if another thread has ownership of the mutex returns immediately.
+ //!Returns: If the thread acquires ownership of the mutex, returns true, if
+ //! the another thread has ownership of the mutex, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread will try to obtain exclusive ownership of the
+ //! mutex if it can do so in until the specified time is reached. If the
+ //! mutex supports recursive locking, the mutex must be unlocked the same
+ //! number of times it is locked.
+ //!Returns: If the thread acquires ownership of the mutex, returns true, if
+ //! the timeout expires returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: interprocess_exception on error.
+ void unlock();
+ /// @cond
+ private:
+
+ #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
+ /// @endcond
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+
+namespace boost {
+namespace interprocess {
+
+inline interprocess_mutex::interprocess_mutex(){}
+
+inline interprocess_mutex::~interprocess_mutex(){}
+
+inline void interprocess_mutex::lock()
+{
+ #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
+ boost::posix_time::ptime wait_time
+ = boost::posix_time::microsec_clock::universal_time()
+ + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
+ if (!mutex.timed_lock(wait_time))
+ {
+ throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?");
+ }
+ #else
+ mutex.lock();
+ #endif
+}
+
+inline bool interprocess_mutex::try_lock()
+{ return mutex.try_lock(); }
+
+inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{ return mutex.timed_lock(abs_time); }
+
+inline void interprocess_mutex::unlock()
+{ mutex.unlock(); }
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_MUTEX_HPP
diff --git a/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/boost/interprocess/sync/interprocess_recursive_mutex.hpp
new file mode 100644
index 0000000000..308819ff27
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_recursive_mutex.hpp
@@ -0,0 +1,177 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Parts of the pthread code come from Boost Threads code:
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. William E. Kempf makes no representations
+// about the suitability of this software for any purpose.
+// It is provided "as is" without express or implied warranty.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
+
+/// @cond
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/assert.hpp>
+
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
+ (defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES))
+ #include <boost/interprocess/sync/posix/recursive_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_POSIX
+//Experimental...
+//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+// #include <boost/interprocess/sync/windows/recursive_mutex.hpp>
+// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ #include <boost/interprocess/sync/spin/recursive_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+#endif
+
+#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+namespace robust_emulation_helpers {
+
+template<class T>
+class mutex_traits;
+
+}}}}
+
+#endif
+
+/// @endcond
+
+//!\file
+//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes
+
+namespace boost {
+namespace interprocess {
+
+//!Wraps a interprocess_mutex that can be placed in shared memory and can be
+//!shared between processes. Allows several locking calls by the same
+//!process. Allows timed lock tries
+class interprocess_recursive_mutex
+{
+ /// @cond
+ //Non-copyable
+ interprocess_recursive_mutex(const interprocess_recursive_mutex &);
+ interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &);
+ /// @endcond
+ public:
+ //!Constructor.
+ //!Throws interprocess_exception on error.
+ interprocess_recursive_mutex();
+
+ //!Destructor. If any process uses the mutex after the destructor is called
+ //!the result is undefined. Does not throw.
+ ~interprocess_recursive_mutex();
+
+ //!Effects: The calling thread tries to obtain ownership of the mutex, and
+ //! if another thread has ownership of the mutex, it waits until it can
+ //! obtain the ownership. If a thread takes ownership of the mutex the
+ //! mutex must be unlocked by the same mutex. The mutex must be unlocked
+ //! the same number of times it is locked.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
+ //!is already locked, returns true when success. The mutex must be unlocked
+ //!the same number of times it is locked.
+ //!Throws: interprocess_exception if a severe error is found
+ bool try_lock();
+
+ //!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before
+ //!abs_time time, returns false. The mutex must be unlocked
+ //! the same number of times it is locked.
+ //!Throws: interprocess_exception if a severe error is found
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //! If the mutex supports recursive locking, the mutex must be unlocked the
+ //! same number of times it is locked.
+ //!Throws: interprocess_exception on error.
+ void unlock();
+ /// @cond
+ private:
+
+ #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
+ #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+ void take_ownership(){ mutex.take_ownership(); }
+ friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_recursive_mutex>;
+ ipcdetail::spin_recursive_mutex mutex;
+ #elif defined(BOOST_INTERPROCESS_USE_POSIX)
+ #undef BOOST_INTERPROCESS_USE_POSIX
+ ipcdetail::posix_recursive_mutex mutex;
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ ipcdetail::windows_recursive_mutex mutex;
+ #else
+ #error "Unknown platform for interprocess_mutex"
+ #endif
+ /// @endcond
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+namespace boost {
+namespace interprocess {
+
+inline interprocess_recursive_mutex::interprocess_recursive_mutex(){}
+
+inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
+
+inline void interprocess_recursive_mutex::lock()
+{
+ #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
+ boost::posix_time::ptime wait_time
+ = boost::posix_time::microsec_clock::universal_time()
+ + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
+ if (!mutex.timed_lock(wait_time)){
+ throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?");
+ }
+ #else
+ mutex.lock();
+ #endif
+}
+
+inline bool interprocess_recursive_mutex::try_lock()
+{ return mutex.try_lock(); }
+
+inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{ return mutex.timed_lock(abs_time); }
+
+inline void interprocess_recursive_mutex::unlock()
+{ mutex.unlock(); }
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/interprocess_semaphore.hpp b/boost/interprocess/sync/interprocess_semaphore.hpp
new file mode 100644
index 0000000000..4ffcdcf691
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_semaphore.hpp
@@ -0,0 +1,145 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_SEMAPHORE_HPP
+
+/// @cond
+
+#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/posix_time_types_wrk.hpp>
+
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
+ (defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES))
+ #include <boost/interprocess/sync/posix/semaphore.hpp>
+ #define BOOST_INTERPROCESS_USE_POSIX
+//Experimental...
+//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+// #include <boost/interprocess/sync/windows/semaphore.hpp>
+// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ #include <boost/interprocess/sync/spin/semaphore.hpp>
+ #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+#endif
+
+/// @endcond
+
+//!\file
+//!Describes a interprocess_semaphore class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+//!Wraps a interprocess_semaphore that can be placed in shared memory and can be
+//!shared between processes. Allows timed lock tries
+class interprocess_semaphore
+{
+ /// @cond
+ //Non-copyable
+ interprocess_semaphore(const interprocess_semaphore &);
+ interprocess_semaphore &operator=(const interprocess_semaphore &);
+ /// @endcond
+ public:
+ //!Creates a interprocess_semaphore with the given initial count.
+ //!interprocess_exception if there is an error.*/
+ interprocess_semaphore(unsigned int initialCount);
+
+ //!Destroys the interprocess_semaphore.
+ //!Does not throw
+ ~interprocess_semaphore();
+
+ //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting
+ //!for the interprocess_semaphore, then one of these processes will return successfully from
+ //!its wait function. If there is an error an interprocess_exception exception is thrown.
+ void post();
+
+ //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero,
+ //!then the calling process/thread blocks until it can decrement the counter.
+ //!If there is an error an interprocess_exception exception is thrown.
+ void wait();
+
+ //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero
+ //!and returns true. If the value is not greater than zero returns false.
+ //!If there is an error an interprocess_exception exception is thrown.
+ bool try_wait();
+
+ //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater
+ //!than zero and returns true. Otherwise, waits for the interprocess_semaphore
+ //!to the posted or the timeout expires. If the timeout expires, the
+ //!function returns false. If the interprocess_semaphore is posted the function
+ //!returns true. If there is an error throws sem_exception
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ //!Returns the interprocess_semaphore count
+// int get_count() const;
+ /// @cond
+ private:
+ #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
+ #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+ ipcdetail::spin_semaphore m_sem;
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ ipcdetail::windows_semaphore m_sem;
+ #else
+ #undef BOOST_INTERPROCESS_USE_POSIX
+ ipcdetail::posix_semaphore m_sem;
+ #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
+ /// @endcond
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+namespace boost {
+namespace interprocess {
+
+inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount)
+ : m_sem(initialCount)
+{}
+
+inline interprocess_semaphore::~interprocess_semaphore(){}
+
+inline void interprocess_semaphore::wait()
+{
+ #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
+ boost::posix_time::ptime wait_time
+ = boost::posix_time::microsec_clock::universal_time()
+ + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
+ if (!m_sem.timed_wait(wait_time))
+ {
+ throw interprocess_exception(timeout_when_waiting_error, "Interprocess semaphore timeout when waiting. Possible deadlock: owner died without posting?");
+ }
+ #else
+ m_sem.wait();
+ #endif
+}
+inline bool interprocess_semaphore::try_wait()
+{ return m_sem.try_wait(); }
+
+inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{ return m_sem.timed_wait(abs_time); }
+
+inline void interprocess_semaphore::post()
+{ m_sem.post(); }
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
new file mode 100644
index 0000000000..048407f4b3
--- /dev/null
+++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
@@ -0,0 +1,659 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
+#define BOOST_INTERPROCESS_UPGRADABLE_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_upgradable_mutex class
+
+namespace boost {
+namespace interprocess {
+
+//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be
+//!shared between processes. Allows timed lock tries
+class interprocess_upgradable_mutex
+{
+ //Non-copyable
+ interprocess_upgradable_mutex(const interprocess_upgradable_mutex &);
+ interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &);
+
+ friend class interprocess_condition;
+ public:
+
+ //!Constructs the upgradable lock.
+ //!Throws interprocess_exception on error.
+ interprocess_upgradable_mutex();
+
+ //!Destroys the upgradable lock.
+ //!Does not throw.
+ ~interprocess_upgradable_mutex();
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive, sharable or upgradable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive, sharable or upgradable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive, sharable or
+ //! upgradable ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+
+ //Upgradable locking
+
+ //!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
+ //! and if another thread has exclusive or upgradable ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! without waiting. If no other thread has exclusive or upgradable ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire upgradable ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive or upgradable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The calling thread releases the upgradable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable();
+
+ //Demotions
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! upgradable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_upgradable();
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_sharable();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock_sharable();
+
+ //Promotions
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! exclusive ownership. This operation will block until all threads with
+ //! sharable ownership release their sharable lock.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to
+ //! acquire exclusive ownership. This operation will fail if there are threads
+ //! with sharable ownership, but it will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to acquire
+ //! exclusive ownership, waiting if necessary until abs_time. This operation will
+ //! fail if there are threads with sharable ownership or timeout reaches, but it
+ //! will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error. */
+ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The thread atomically releases sharable ownership and tries to acquire
+ //! exclusive ownership. This operation will fail if there are threads with sharable
+ //! or upgradable ownership, but it will maintain sharable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_sharable_and_lock();
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The thread atomically releases sharable ownership and tries to acquire
+ //! upgradable ownership. This operation will fail if there are threads with sharable
+ //! or upgradable ownership, but it will maintain sharable ownership.
+ //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_sharable_and_lock_upgradable();
+
+ /// @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 upgradable_in : 1;
+ unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2;
+ } m_ctrl;
+
+ interprocess_mutex m_mut;
+ interprocess_condition m_first_gate;
+ interprocess_condition m_second_gate;
+
+ private:
+ //Rollback structures for exceptions or failure return values
+ struct exclusive_rollback
+ {
+ exclusive_rollback(control_word_t &ctrl
+ ,interprocess_condition &first_gate)
+ : mp_ctrl(&ctrl), m_first_gate(first_gate)
+ {}
+
+ void release()
+ { mp_ctrl = 0; }
+
+ ~exclusive_rollback()
+ {
+ if(mp_ctrl){
+ mp_ctrl->exclusive_in = 0;
+ m_first_gate.notify_all();
+ }
+ }
+ control_word_t *mp_ctrl;
+ interprocess_condition &m_first_gate;
+ };
+
+ struct upgradable_to_exclusive_rollback
+ {
+ upgradable_to_exclusive_rollback(control_word_t &ctrl)
+ : mp_ctrl(&ctrl)
+ {}
+
+ void release()
+ { mp_ctrl = 0; }
+
+ ~upgradable_to_exclusive_rollback()
+ {
+ if(mp_ctrl){
+ //Recover upgradable lock
+ mp_ctrl->upgradable_in = 1;
+ ++mp_ctrl->num_upr_shar;
+ //Execute the second half of exclusive locking
+ mp_ctrl->exclusive_in = 0;
+ }
+ }
+ control_word_t *mp_ctrl;
+ };
+
+ template<int Dummy>
+ struct base_constants_t
+ {
+ static const unsigned max_readers
+ = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
+ };
+ typedef base_constants_t<0> constants;
+ /// @endcond
+};
+
+/// @cond
+
+template <int Dummy>
+const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
+
+inline interprocess_upgradable_mutex::interprocess_upgradable_mutex()
+{
+ this->m_ctrl.exclusive_in = 0;
+ this->m_ctrl.upgradable_in = 0;
+ this->m_ctrl.num_upr_shar = 0;
+}
+
+inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
+{}
+
+inline void interprocess_upgradable_mutex::lock()
+{
+ scoped_lock_t lock(m_mut);
+
+ //The exclusive lock must block in the first gate
+ //if an exclusive or upgradable lock has been acquired
+ while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
+ this->m_first_gate.wait(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_upgradable_mutex::try_lock()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+
+ //If we can't lock or any has there is any exclusive, upgradable
+ //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_upgradable_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 or upgradable lock has been acquired
+ while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
+ if(!this->m_first_gate.timed_wait(lock, abs_time))
+ return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_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_upgradable_mutex::unlock()
+{
+ scoped_lock_t lock(m_mut);
+ this->m_ctrl.exclusive_in = 0;
+ this->m_first_gate.notify_all();
+}
+
+//Upgradable locking
+
+inline void interprocess_upgradable_mutex::lock_upgradable()
+{
+ scoped_lock_t lock(m_mut);
+
+ //The upgradable lock must block in the first gate
+ //if an exclusive or upgradable lock has been acquired
+ //or there are too many sharable locks
+ while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers){
+ this->m_first_gate.wait(lock);
+ }
+
+ //Mark that upgradable lock has been acquired
+ //And add upgradable to the sharable count
+ this->m_ctrl.upgradable_in = 1;
+ ++this->m_ctrl.num_upr_shar;
+}
+
+inline bool interprocess_upgradable_mutex::try_lock_upgradable()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+
+ //The upgradable lock must fail
+ //if an exclusive or upgradable lock has been acquired
+ //or there are too many sharable locks
+ if(!lock.owns()
+ || this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers){
+ return false;
+ }
+
+ //Mark that upgradable lock has been acquired
+ //And add upgradable to the sharable count
+ this->m_ctrl.upgradable_in = 1;
+ ++this->m_ctrl.num_upr_shar;
+ return true;
+}
+
+inline bool interprocess_upgradable_mutex::timed_lock_upgradable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_upgradable();
+ return true;
+ }
+ scoped_lock_t lock(m_mut, abs_time);
+ if(!lock.owns()) return false;
+
+ //The upgradable lock must block in the first gate
+ //if an exclusive or upgradable lock has been acquired
+ //or there are too many sharable locks
+ while(this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers){
+ if(!this->m_first_gate.timed_wait(lock, abs_time)){
+ return!(this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar == constants::max_readers);
+ }
+ }
+
+ //Mark that upgradable lock has been acquired
+ //And add upgradable to the sharable count
+ this->m_ctrl.upgradable_in = 1;
+ ++this->m_ctrl.num_upr_shar;
+ return true;
+}
+
+inline void interprocess_upgradable_mutex::unlock_upgradable()
+{
+ scoped_lock_t lock(m_mut);
+ //Mark that upgradable lock has been acquired
+ //And add upgradable to the sharable count
+ this->m_ctrl.upgradable_in = 0;
+ --this->m_ctrl.num_upr_shar;
+ this->m_first_gate.notify_all();
+}
+
+//Sharable locking
+
+inline void interprocess_upgradable_mutex::lock_sharable()
+{
+ scoped_lock_t 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_upgradable_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_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;
+ }
+ 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_upgradable_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();
+ }
+}
+
+//Downgrading
+
+inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
+{
+ scoped_lock_t lock(m_mut);
+ //Unmark it as exclusive
+ this->m_ctrl.exclusive_in = 0;
+ //Mark it as upgradable
+ this->m_ctrl.upgradable_in = 1;
+ //The sharable count should be 0 so increment it
+ this->m_ctrl.num_upr_shar = 1;
+ //Notify readers that they can enter
+ m_first_gate.notify_all();
+}
+
+inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
+{
+ scoped_lock_t lock(m_mut);
+ //Unmark it as exclusive
+ this->m_ctrl.exclusive_in = 0;
+ //The sharable count should be 0 so increment it
+ this->m_ctrl.num_upr_shar = 1;
+ //Notify readers that they can enter
+ m_first_gate.notify_all();
+}
+
+inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
+{
+ scoped_lock_t lock(m_mut);
+ //Unmark it as upgradable (we don't have to decrement count)
+ this->m_ctrl.upgradable_in = 0;
+ //Notify readers/upgradable that they can enter
+ m_first_gate.notify_all();
+}
+
+//Upgrading
+
+inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
+{
+ scoped_lock_t lock(m_mut);
+ //Simulate unlock_upgradable() without
+ //notifying sharables.
+ this->m_ctrl.upgradable_in = 0;
+ --this->m_ctrl.num_upr_shar;
+ //Execute the second half of exclusive locking
+ this->m_ctrl.exclusive_in = 1;
+
+ //Prepare rollback
+ upgradable_to_exclusive_rollback rollback(m_ctrl);
+
+ while (this->m_ctrl.num_upr_shar){
+ this->m_second_gate.wait(lock);
+ }
+ rollback.release();
+}
+
+inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+ //Check if there are no readers
+ if(!lock.owns()
+ || this->m_ctrl.num_upr_shar != 1){
+ return false;
+ }
+ //Now unlock upgradable and mark exclusive
+ this->m_ctrl.upgradable_in = 0;
+ --this->m_ctrl.num_upr_shar;
+ this->m_ctrl.exclusive_in = 1;
+ return true;
+}
+
+inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ scoped_lock_t lock(m_mut, abs_time);
+ if(!lock.owns()) return false;
+
+ //Simulate unlock_upgradable() without
+ //notifying sharables.
+ this->m_ctrl.upgradable_in = 0;
+ --this->m_ctrl.num_upr_shar;
+ //Execute the second half of exclusive locking
+ this->m_ctrl.exclusive_in = 1;
+
+ //Prepare rollback
+ upgradable_to_exclusive_rollback rollback(m_ctrl);
+
+ while (this->m_ctrl.num_upr_shar){
+ if(!this->m_second_gate.timed_wait(lock, abs_time)){
+ return !(this->m_ctrl.num_upr_shar);
+ }
+ }
+ rollback.release();
+ return true;
+}
+
+inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+
+ //If we can't lock or any has there is any exclusive, upgradable
+ //or sharable mark return false;
+ if(!lock.owns()
+ || this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in
+ || this->m_ctrl.num_upr_shar != 1){
+ return false;
+ }
+ this->m_ctrl.exclusive_in = 1;
+ this->m_ctrl.num_upr_shar = 0;
+ return true;
+}
+
+inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
+{
+ scoped_lock_t lock(m_mut, try_to_lock);
+
+ //The upgradable lock must fail
+ //if an exclusive or upgradable lock has been acquired
+ if(!lock.owns()
+ || this->m_ctrl.exclusive_in
+ || this->m_ctrl.upgradable_in){
+ return false;
+ }
+
+ //Mark that upgradable lock has been acquired
+ this->m_ctrl.upgradable_in = 1;
+ return true;
+}
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
diff --git a/boost/interprocess/sync/lock_options.hpp b/boost/interprocess/sync/lock_options.hpp
new file mode 100644
index 0000000000..74f3399a4c
--- /dev/null
+++ b/boost/interprocess/sync/lock_options.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
+#define BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+//!\file
+//!Describes the lock options with associated with interprocess_mutex lock constructors.
+
+namespace boost {
+
+namespace posix_time
+{ class ptime; }
+
+namespace interprocess {
+
+//!Type to indicate to a mutex lock constructor that must not lock the mutex.
+struct defer_lock_type{};
+//!Type to indicate to a mutex lock constructor that must try to lock the mutex.
+struct try_to_lock_type {};
+//!Type to indicate to a mutex lock constructor that the mutex is already locked.
+struct accept_ownership_type{};
+
+//!An object indicating that the locking
+//!must be deferred.
+static const defer_lock_type defer_lock = defer_lock_type();
+
+//!An object indicating that a try_lock()
+//!operation must be executed.
+static const try_to_lock_type try_to_lock = try_to_lock_type();
+
+//!An object indicating that the ownership of lockable
+//!object must be accepted by the new owner.
+static const accept_ownership_type accept_ownership = accept_ownership_type();
+
+} // namespace interprocess {
+} // namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_LOCK_OPTIONS_HPP
diff --git a/boost/interprocess/sync/mutex_family.hpp b/boost/interprocess/sync/mutex_family.hpp
new file mode 100644
index 0000000000..a9215e24fe
--- /dev/null
+++ b/boost/interprocess/sync/mutex_family.hpp
@@ -0,0 +1,56 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
+#define BOOST_INTERPROCESS_MUTEX_FAMILY_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/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/null_mutex.hpp>
+
+//!\file
+//!Describes a shared interprocess_mutex family fit algorithm used to allocate objects in shared memory.
+
+namespace boost {
+
+namespace interprocess {
+
+//!Describes interprocess_mutex family to use with Interprocess framework
+//!based on boost::interprocess synchronization objects.
+struct mutex_family
+{
+ typedef boost::interprocess::interprocess_mutex mutex_type;
+ typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type;
+};
+
+//!Describes interprocess_mutex family to use with Interprocess frameworks
+//!based on null operation synchronization objects.
+struct null_mutex_family
+{
+ typedef boost::interprocess::null_mutex mutex_type;
+ typedef boost::interprocess::null_mutex recursive_mutex_type;
+};
+
+} //namespace interprocess {
+
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP
+
+
diff --git a/boost/interprocess/sync/named_condition.hpp b/boost/interprocess/sync/named_condition.hpp
new file mode 100644
index 0000000000..c5529eda6c
--- /dev/null
+++ b/boost/interprocess/sync/named_condition.hpp
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_CONDITION_HPP
+#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/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/shm/named_condition.hpp>
+
+//!\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
+{
+ /// @cond
+ //Non-copyable
+ named_condition();
+ named_condition(const named_condition &);
+ named_condition &operator=(const named_condition &);
+ /// @endcond
+ public:
+ //!Creates a global condition with a name.
+ //!If the condition can't be created throws interprocess_exception
+ named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global condition with a name.
+ //!If the condition is created, this call is equivalent to
+ //!named_condition(create_only_t, ... )
+ //!If the condition is already created, this call is equivalent
+ //!named_condition(open_only_t, ... )
+ //!Does not throw
+ named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global condition with a name if that condition is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_condition(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_condition();
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.*/
+ void notify_one();
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all();
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock);
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred);
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
+
+ //!Erases a named condition from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ ipcdetail::shm_named_condition m_cond;
+
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction()
+ { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); }
+ /// @endcond
+};
+
+/// @cond
+
+inline named_condition::~named_condition()
+{}
+
+inline named_condition::named_condition(create_only_t, const char *name, const permissions &perm)
+ : m_cond(create_only_t(), name, perm)
+{}
+
+inline named_condition::named_condition(open_or_create_t, const char *name, const permissions &perm)
+ : m_cond(open_or_create_t(), name, perm)
+{}
+
+inline named_condition::named_condition(open_only_t, const char *name)
+ : m_cond(open_only_t(), name)
+{}
+
+inline void named_condition::notify_one()
+{ m_cond.notify_one(); }
+
+inline void named_condition::notify_all()
+{ m_cond.notify_all(); }
+
+template <typename L>
+inline void named_condition::wait(L& lock)
+{ m_cond.wait(lock); }
+
+template <typename L, typename Pr>
+inline void named_condition::wait(L& lock, Pr pred)
+{ m_cond.wait(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); }
+
+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); }
+
+inline bool named_condition::remove(const char *name)
+{ return ipcdetail::shm_named_condition::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_NAMED_CONDITION_HPP
diff --git a/boost/interprocess/sync/named_mutex.hpp b/boost/interprocess/sync/named_mutex.hpp
new file mode 100644
index 0000000000..3e56b81794
--- /dev/null
+++ b/boost/interprocess/sync/named_mutex.hpp
@@ -0,0 +1,163 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+#include <boost/interprocess/sync/posix/named_mutex.hpp>
+#else
+#include <boost/interprocess/sync/shm/named_mutex.hpp>
+#endif
+
+//!\file
+//!Describes a named mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+class named_condition;
+
+//!A mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named_mutex.
+class named_mutex
+{
+ /// @cond
+
+ //Non-copyable
+ named_mutex();
+ named_mutex(const named_mutex &);
+ named_mutex &operator=(const named_mutex &);
+ friend class named_condition;
+ /// @endcond
+
+ public:
+ //!Creates a global interprocess_mutex with a name.
+ //!Throws interprocess_exception on error.
+ named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global mutex with a name.
+ //!If the mutex is created, this call is equivalent to
+ //!named_mutex(create_only_t, ... )
+ //!If the mutex is already created, this call is equivalent
+ //!named_mutex(open_only_t, ... )
+ //!Does not throw
+ named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global mutex with a name if that mutex is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_mutex();
+
+ //!Unlocks a previously locked
+ //!interprocess_mutex.
+ void unlock();
+
+ //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked.
+ //!Throws interprocess_exception if a severe error is found
+ void lock();
+
+ //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
+ //!is already locked, returns true when success.
+ //!Throws interprocess_exception if a severe error is found
+ bool try_lock();
+
+ //!Tries to lock the interprocess_mutex until time abs_time,
+ //!Returns false when timeout expires, returns true when locks.
+ //!Throws interprocess_exception if a severe error is found
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Erases a named mutex from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
+ typedef ipcdetail::posix_named_mutex impl_t;
+ impl_t m_mut;
+ #else
+ typedef ipcdetail::shm_named_mutex impl_t;
+ impl_t m_mut;
+ public:
+ interprocess_mutex *mutex() const
+ { return m_mut.mutex(); }
+ #endif
+
+ /// @endcond
+};
+
+/// @cond
+
+inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm)
+ : m_mut(create_only_t(), name, perm)
+{}
+
+inline named_mutex::named_mutex(open_or_create_t, const char *name, const permissions &perm)
+ : m_mut(open_or_create_t(), name, perm)
+{}
+
+inline named_mutex::named_mutex(open_only_t, const char *name)
+ : m_mut(open_only_t(), name)
+{}
+
+inline void named_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); }
+
+inline named_mutex::~named_mutex()
+{}
+
+inline void named_mutex::lock()
+{ m_mut.lock(); }
+
+inline void named_mutex::unlock()
+{ m_mut.unlock(); }
+
+inline bool named_mutex::try_lock()
+{ return m_mut.try_lock(); }
+
+inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{ return m_mut.timed_lock(abs_time); }
+
+inline bool named_mutex::remove(const char *name)
+{ return impl_t::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_MUTEX_HPP
diff --git a/boost/interprocess/sync/named_recursive_mutex.hpp b/boost/interprocess/sync/named_recursive_mutex.hpp
new file mode 100644
index 0000000000..28768cea6f
--- /dev/null
+++ b/boost/interprocess/sync/named_recursive_mutex.hpp
@@ -0,0 +1,154 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/sync/shm/named_recursive_mutex.hpp>
+
+//!\file
+//!Describes a named named_recursive_mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+//!A recursive mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named_recursive_mutex.
+class named_recursive_mutex
+{
+ /// @cond
+ //Non-copyable
+ named_recursive_mutex();
+ named_recursive_mutex(const named_recursive_mutex &);
+ named_recursive_mutex &operator=(const named_recursive_mutex &);
+ /// @endcond
+ public:
+
+ //!Creates a global recursive_mutex with a name.
+ //!If the recursive_mutex can't be created throws interprocess_exception
+ named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global recursive_mutex with a name.
+ //!If the recursive_mutex is created, this call is equivalent to
+ //!named_recursive_mutex(create_only_t, ... )
+ //!If the recursive_mutex is already created, this call is equivalent
+ //!named_recursive_mutex(open_only_t, ... )
+ //!Does not throw
+ named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global recursive_mutex with a name if that recursive_mutex is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_recursive_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_recursive_mutex();
+
+ //!Unlocks a previously locked
+ //!named_recursive_mutex.
+ void unlock();
+
+ //!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked.
+ //!Throws interprocess_exception if a severe error is found.
+ void lock();
+
+ //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex
+ //!is already locked, returns true when success.
+ //!Throws interprocess_exception if a severe error is found.
+ bool try_lock();
+
+ //!Tries to lock the named_recursive_mutex until time abs_time,
+ //!Returns false when timeout expires, returns true when locks.
+ //!Throws interprocess_exception if a severe error is found
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Erases a named recursive mutex
+ //!from the system
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ typedef ipcdetail::shm_named_recursive_mutex impl_t;
+ impl_t m_mut;
+
+ /// @endcond
+};
+
+/// @cond
+
+inline named_recursive_mutex::~named_recursive_mutex()
+{}
+
+inline void named_recursive_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); }
+
+inline named_recursive_mutex::named_recursive_mutex(create_only_t, const char *name, const permissions &perm)
+ : m_mut (create_only, name, perm)
+{}
+
+inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm)
+ : m_mut (open_or_create, name, perm)
+{}
+
+inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *name)
+ : m_mut (open_only, name)
+{}
+
+inline void named_recursive_mutex::lock()
+{ m_mut.lock(); }
+
+inline void named_recursive_mutex::unlock()
+{ m_mut.unlock(); }
+
+inline bool named_recursive_mutex::try_lock()
+{ return m_mut.try_lock(); }
+
+inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return m_mut.timed_lock(abs_time);
+}
+
+inline bool named_recursive_mutex::remove(const char *name)
+{ return impl_t::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/named_semaphore.hpp b/boost/interprocess/sync/named_semaphore.hpp
new file mode 100644
index 0000000000..33e06964f9
--- /dev/null
+++ b/boost/interprocess/sync/named_semaphore.hpp
@@ -0,0 +1,168 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
+#include <boost/interprocess/sync/posix/named_semaphore.hpp>
+#else
+#include <boost/interprocess/sync/shm/named_semaphore.hpp>
+#endif
+
+//!\file
+//!Describes a named semaphore class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+//!A semaphore with a global name, so it can be found from different
+//!processes. Allows several resource sharing patterns and efficient
+//!acknowledgment mechanisms.
+class named_semaphore
+{
+ /// @cond
+
+ //Non-copyable
+ named_semaphore();
+ named_semaphore(const named_semaphore &);
+ named_semaphore &operator=(const named_semaphore &);
+ /// @endcond
+
+ public:
+ //!Creates a global semaphore with a name, and an initial count.
+ //!If the semaphore can't be created throws interprocess_exception
+ named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ //!Opens or creates a global semaphore with a name, and an initial count.
+ //!If the semaphore is created, this call is equivalent to
+ //!named_semaphore(create_only_t, ...)
+ //!If the semaphore is already created, this call is equivalent to
+ //!named_semaphore(open_only_t, ... )
+ //!and initialCount is ignored.
+ named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ //!Opens a global semaphore with a name if that semaphore is previously.
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_semaphore(open_only_t, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_semaphore();
+
+ //!Increments the semaphore count. If there are processes/threads blocked waiting
+ //!for the semaphore, then one of these processes will return successfully from
+ //!its wait function. If there is an error an interprocess_exception exception is thrown.
+ void post();
+
+ //!Decrements the semaphore. If the semaphore value is not greater than zero,
+ //!then the calling process/thread blocks until it can decrement the counter.
+ //!If there is an error an interprocess_exception exception is thrown.
+ void wait();
+
+ //!Decrements the semaphore if the semaphore's value is greater than zero
+ //!and returns true. If the value is not greater than zero returns false.
+ //!If there is an error an interprocess_exception exception is thrown.
+ bool try_wait();
+
+ //!Decrements the semaphore if the semaphore's value is greater
+ //!than zero and returns true. Otherwise, waits for the semaphore
+ //!to the posted or the timeout expires. If the timeout expires, the
+ //!function returns false. If the semaphore is posted the function
+ //!returns true. If there is an error throws sem_exception
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ //!Erases a named semaphore from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
+ typedef ipcdetail::posix_named_semaphore impl_t;
+ #else
+ typedef ipcdetail::shm_named_semaphore impl_t;
+ #endif
+ impl_t m_sem;
+ /// @endcond
+};
+
+/// @cond
+
+inline named_semaphore::named_semaphore
+ (create_only_t, const char *name, unsigned int initialCount, const permissions &perm)
+ : m_sem(create_only, name, initialCount, perm)
+{}
+
+inline named_semaphore::named_semaphore
+ (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm)
+ : m_sem(open_or_create, name, initialCount, perm)
+{}
+
+inline named_semaphore::named_semaphore(open_only_t, const char *name)
+ : m_sem(open_only, name)
+{}
+
+inline named_semaphore::~named_semaphore()
+{}
+
+inline void named_semaphore::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_sem); }
+
+inline void named_semaphore::wait()
+{ m_sem.wait(); }
+
+inline void named_semaphore::post()
+{ m_sem.post(); }
+
+inline bool named_semaphore::try_wait()
+{ return m_sem.try_wait(); }
+
+inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ return m_sem.timed_wait(abs_time);
+}
+
+inline bool named_semaphore::remove(const char *name)
+{ return impl_t::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/named_upgradable_mutex.hpp b/boost/interprocess/sync/named_upgradable_mutex.hpp
new file mode 100644
index 0000000000..61c6bb4086
--- /dev/null
+++ b/boost/interprocess/sync/named_upgradable_mutex.hpp
@@ -0,0 +1,372 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_named_upgradable_mutex_HPP
+#define BOOST_INTERPROCESS_named_upgradable_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_upgradable_mutex.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+//!\file
+//!Describes a named upgradable mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+class named_condition;
+
+//!A upgradable mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named upgradable mutex.
+class named_upgradable_mutex
+{
+ /// @cond
+ //Non-copyable
+ named_upgradable_mutex();
+ named_upgradable_mutex(const named_upgradable_mutex &);
+ named_upgradable_mutex &operator=(const named_upgradable_mutex &);
+ friend class named_condition;
+ /// @endcond
+ public:
+
+ //!Creates a global upgradable mutex with a name.
+ //!If the upgradable mutex can't be created throws interprocess_exception
+ named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global upgradable mutex with a name, and an initial count.
+ //!If the upgradable mutex is created, this call is equivalent to
+ //!named_upgradable_mutex(create_only_t, ...)
+ //!If the upgradable mutex is already created, this call is equivalent to
+ //!named_upgradable_mutex(open_only_t, ... ).
+ named_upgradable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global upgradable mutex with a name if that upgradable mutex
+ //!is previously.
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_upgradable_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_upgradable_mutex();
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive, sharable or upgradable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive, sharable or upgradable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive, sharable or
+ //! upgradable ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+
+ //Upgradable locking
+
+ //!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
+ //! and if another thread has exclusive or upgradable ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! without waiting. If no other thread has exclusive or upgradable ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire upgradable ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive or upgradable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The calling thread releases the upgradable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable();
+
+ //Demotions
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! upgradable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_upgradable();
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_sharable();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock_sharable();
+
+ //Promotions
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! exclusive ownership. This operation will block until all threads with
+ //! sharable ownership release it.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to
+ //! acquire exclusive ownership. This operation will fail if there are threads
+ //! with sharable ownership, but it will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to acquire
+ //! exclusive ownership, waiting if necessary until abs_time. This operation will
+ //! fail if there are threads with sharable ownership or timeout reaches, but it
+ //! will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The thread atomically releases sharable ownership and tries to acquire
+ //! exclusive ownership. This operation will fail if there are threads with sharable
+ //! or upgradable ownership, but it will maintain sharable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_sharable_and_lock();
+
+ bool try_unlock_sharable_and_lock_upgradable();
+
+ //!Erases a named upgradable mutex from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ interprocess_upgradable_mutex *mutex() const
+ { return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
+
+ ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
+ /// @endcond
+};
+
+/// @cond
+
+inline named_upgradable_mutex::~named_upgradable_mutex()
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_upgradable_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoCreate)
+ ,perm)
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_upgradable_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpenOrCreate)
+ ,perm)
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpen))
+{}
+
+inline void named_upgradable_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline void named_upgradable_mutex::lock()
+{ this->mutex()->lock(); }
+
+inline void named_upgradable_mutex::unlock()
+{ this->mutex()->unlock(); }
+
+inline bool named_upgradable_mutex::try_lock()
+{ return this->mutex()->try_lock(); }
+
+inline bool named_upgradable_mutex::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
+
+inline void named_upgradable_mutex::lock_upgradable()
+{ this->mutex()->lock_upgradable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable()
+{ this->mutex()->unlock_upgradable(); }
+
+inline bool named_upgradable_mutex::try_lock_upgradable()
+{ return this->mutex()->try_lock_upgradable(); }
+
+inline bool named_upgradable_mutex::timed_lock_upgradable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_upgradable();
+ return true;
+ }
+ return this->mutex()->timed_lock_upgradable(abs_time);
+}
+
+inline void named_upgradable_mutex::lock_sharable()
+{ this->mutex()->lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_sharable()
+{ this->mutex()->unlock_sharable(); }
+
+inline bool named_upgradable_mutex::try_lock_sharable()
+{ return this->mutex()->try_lock_sharable(); }
+
+inline bool named_upgradable_mutex::timed_lock_sharable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
+ return this->mutex()->timed_lock_sharable(abs_time);
+}
+
+inline void named_upgradable_mutex::unlock_and_lock_upgradable()
+{ this->mutex()->unlock_and_lock_upgradable(); }
+
+inline void named_upgradable_mutex::unlock_and_lock_sharable()
+{ this->mutex()->unlock_and_lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable()
+{ this->mutex()->unlock_upgradable_and_lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable_and_lock()
+{ this->mutex()->unlock_upgradable_and_lock(); }
+
+inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
+{ return this->mutex()->try_unlock_upgradable_and_lock(); }
+
+inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
+ (const boost::posix_time::ptime &abs_time)
+{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
+
+inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
+{ return this->mutex()->try_unlock_sharable_and_lock(); }
+
+inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
+{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); }
+
+inline bool named_upgradable_mutex::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP
diff --git a/boost/interprocess/sync/null_mutex.hpp b/boost/interprocess/sync/null_mutex.hpp
new file mode 100644
index 0000000000..afe444ed3f
--- /dev/null
+++ b/boost/interprocess/sync/null_mutex.hpp
@@ -0,0 +1,147 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NULL_MUTEX_HPP
+#define BOOST_INTERPROCESS_NULL_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>
+
+
+//!\file
+//!Describes null_mutex classes
+
+namespace boost {
+
+namespace posix_time
+{ class ptime; }
+
+namespace interprocess {
+
+//!Implements a mutex that simulates a mutex without doing any operation and
+//!simulates a successful operation.
+class null_mutex
+{
+ /// @cond
+ null_mutex(const null_mutex&);
+ null_mutex &operator= (const null_mutex&);
+ /// @endcond
+ public:
+
+ //!Constructor.
+ //!Empty.
+ null_mutex(){}
+
+ //!Destructor.
+ //!Empty.
+ ~null_mutex(){}
+
+ //!Simulates a mutex lock() operation. Empty function.
+ void lock(){}
+
+ //!Simulates a mutex try_lock() operation.
+ //!Equivalent to "return true;"
+ bool try_lock()
+ { return true; }
+
+ //!Simulates a mutex timed_lock() operation.
+ //!Equivalent to "return true;"
+ bool timed_lock(const boost::posix_time::ptime &)
+ { return true; }
+
+ //!Simulates a mutex unlock() operation.
+ //!Empty function.
+ void unlock(){}
+
+ //!Simulates a mutex lock_sharable() operation.
+ //!Empty function.
+ void lock_sharable(){}
+
+ //!Simulates a mutex try_lock_sharable() operation.
+ //!Equivalent to "return true;"
+ bool try_lock_sharable()
+ { return true; }
+
+ //!Simulates a mutex timed_lock_sharable() operation.
+ //!Equivalent to "return true;"
+ bool timed_lock_sharable(const boost::posix_time::ptime &)
+ { return true; }
+
+ //!Simulates a mutex unlock_sharable() operation.
+ //!Empty function.
+ void unlock_sharable(){}
+
+ //!Simulates a mutex lock_upgradable() operation.
+ //!Empty function.
+ void lock_upgradable(){}
+
+ //!Simulates a mutex try_lock_upgradable() operation.
+ //!Equivalent to "return true;"
+ bool try_lock_upgradable()
+ { return true; }
+
+ //!Simulates a mutex timed_lock_upgradable() operation.
+ //!Equivalent to "return true;"
+ bool timed_lock_upgradable(const boost::posix_time::ptime &)
+ { return true; }
+
+ //!Simulates a mutex unlock_upgradable() operation.
+ //!Empty function.
+ void unlock_upgradable(){}
+
+ //!Simulates unlock_and_lock_upgradable().
+ //!Empty function.
+ void unlock_and_lock_upgradable(){}
+
+ //!Simulates unlock_and_lock_sharable().
+ //!Empty function.
+ void unlock_and_lock_sharable(){}
+
+ //!Simulates unlock_upgradable_and_lock_sharable().
+ //!Empty function.
+ void unlock_upgradable_and_lock_sharable(){}
+
+ //Promotions
+
+ //!Simulates unlock_upgradable_and_lock().
+ //!Empty function.
+ void unlock_upgradable_and_lock(){}
+
+ //!Simulates try_unlock_upgradable_and_lock().
+ //!Equivalent to "return true;"
+ bool try_unlock_upgradable_and_lock()
+ { return true; }
+
+ //!Simulates timed_unlock_upgradable_and_lock().
+ //!Equivalent to "return true;"
+ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &)
+ { return true; }
+
+ //!Simulates try_unlock_sharable_and_lock().
+ //!Equivalent to "return true;"
+ bool try_unlock_sharable_and_lock()
+ { return true; }
+
+ //!Simulates try_unlock_sharable_and_lock_upgradable().
+ //!Equivalent to "return true;"
+ bool try_unlock_sharable_and_lock_upgradable()
+ { return true; }
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NULL_MUTEX_HPP
diff --git a/boost/interprocess/sync/posix/condition.hpp b/boost/interprocess/sync/posix/condition.hpp
new file mode 100644
index 0000000000..213e4ce8b5
--- /dev/null
+++ b/boost/interprocess/sync/posix/condition.hpp
@@ -0,0 +1,191 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP
+#define BOOST_INTERPROCESS_POSIX_CONDITION_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <pthread.h>
+#include <errno.h>
+#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
+#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/posix/mutex.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class posix_condition
+{
+ //Non-copyable
+ posix_condition(const posix_condition &);
+ posix_condition &operator=(const posix_condition &);
+
+ public:
+ //!Constructs a posix_condition. On error throws interprocess_exception.
+ posix_condition();
+
+ //!Destroys *this
+ //!liberating system resources.
+ ~posix_condition();
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.
+ void notify_one();
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all();
+
+ //!Releases the lock on the posix_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ this->do_wait(*lock.mutex());
+ }
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ this->do_wait(*lock.mutex());
+ }
+
+ //!Releases the lock on the posix_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if(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());
+ }
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if(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;
+ }
+
+
+ void do_wait(posix_mutex &mut);
+
+ bool do_timed_wait(const boost::posix_time::ptime &abs_time, posix_mutex &mut);
+
+ private:
+ pthread_cond_t m_condition;
+};
+
+inline posix_condition::posix_condition()
+{
+ int res;
+ pthread_condattr_t cond_attr;
+ res = pthread_condattr_init(&cond_attr);
+ if(res != 0){
+ throw interprocess_exception("pthread_condattr_init failed");
+ }
+ res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
+ if(res != 0){
+ pthread_condattr_destroy(&cond_attr);
+ throw interprocess_exception(res);
+ }
+ res = pthread_cond_init(&m_condition, &cond_attr);
+ pthread_condattr_destroy(&cond_attr);
+ if(res != 0){
+ throw interprocess_exception(res);
+ }
+}
+
+inline posix_condition::~posix_condition()
+{
+ int res = 0;
+ res = pthread_cond_destroy(&m_condition);
+ BOOST_ASSERT(res == 0);
+}
+
+inline void posix_condition::notify_one()
+{
+ int res = 0;
+ res = pthread_cond_signal(&m_condition);
+ BOOST_ASSERT(res == 0);
+}
+
+inline void posix_condition::notify_all()
+{
+ int res = 0;
+ res = pthread_cond_broadcast(&m_condition);
+ BOOST_ASSERT(res == 0);
+}
+
+inline void posix_condition::do_wait(posix_mutex &mut)
+{
+ pthread_mutex_t* pmutex = &mut.m_mut;
+ int res = 0;
+ res = pthread_cond_wait(&m_condition, pmutex);
+ BOOST_ASSERT(res == 0);
+}
+
+inline bool posix_condition::do_timed_wait
+ (const boost::posix_time::ptime &abs_time, posix_mutex &mut)
+{
+ timespec ts = ptime_to_timespec(abs_time);
+ pthread_mutex_t* pmutex = &mut.m_mut;
+ int res = 0;
+ res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
+ BOOST_ASSERT(res == 0 || res == ETIMEDOUT);
+
+ return res != ETIMEDOUT;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP
diff --git a/boost/interprocess/sync/posix/mutex.hpp b/boost/interprocess/sync/posix/mutex.hpp
new file mode 100644
index 0000000000..22e2ec04b9
--- /dev/null
+++ b/boost/interprocess/sync/posix/mutex.hpp
@@ -0,0 +1,152 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Parts of the pthread code come from Boost Threads code:
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. William E. Kempf makes no representations
+// about the suitability of this software for any purpose.
+// It is provided "as is" without express or implied warranty.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <pthread.h>
+#include <errno.h>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
+
+#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+# include <boost/interprocess/detail/os_thread_functions.hpp>
+#endif
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class posix_condition;
+
+class posix_mutex
+{
+ posix_mutex(const posix_mutex &);
+ posix_mutex &operator=(const posix_mutex &);
+ public:
+
+ posix_mutex();
+ ~posix_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+
+ friend class posix_condition;
+
+ private:
+ pthread_mutex_t m_mut;
+};
+
+inline posix_mutex::posix_mutex()
+{
+ mutexattr_wrapper mut_attr;
+ mutex_initializer mut(m_mut, mut_attr);
+ mut.release();
+}
+
+inline posix_mutex::~posix_mutex()
+{
+ int res = pthread_mutex_destroy(&m_mut);
+ BOOST_ASSERT(res == 0);(void)res;
+}
+
+inline void posix_mutex::lock()
+{
+ if (pthread_mutex_lock(&m_mut) != 0)
+ throw lock_exception();
+}
+
+inline bool posix_mutex::try_lock()
+{
+ int res = pthread_mutex_trylock(&m_mut);
+ if (!(res == 0 || res == EBUSY))
+ throw lock_exception();
+ return res == 0;
+}
+
+inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
+ timespec ts = ptime_to_timespec(abs_time);
+ int res = pthread_mutex_timedlock(&m_mut, &ts);
+ if (res != 0 && res != ETIMEDOUT)
+ throw lock_exception();
+ return res == 0;
+
+ #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ do{
+ if(this->try_lock()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return false;
+ }
+ // relinquish current time slice
+ thread_yield();
+ }while (true);
+ return true;
+
+ #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
+}
+
+inline void posix_mutex::unlock()
+{
+ int res = 0;
+ res = pthread_mutex_unlock(&m_mut);
+ BOOST_ASSERT(res == 0);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP
diff --git a/boost/interprocess/sync/posix/named_mutex.hpp b/boost/interprocess/sync/posix/named_mutex.hpp
new file mode 100644
index 0000000000..931c731eff
--- /dev/null
+++ b/boost/interprocess/sync/posix/named_mutex.hpp
@@ -0,0 +1,116 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+#include <boost/interprocess/sync/posix/named_semaphore.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class named_condition;
+
+class posix_named_mutex
+{
+ /// @cond
+
+ posix_named_mutex();
+ posix_named_mutex(const posix_named_mutex &);
+ posix_named_mutex &operator=(const posix_named_mutex &);
+ friend class named_condition;
+ /// @endcond
+
+ public:
+ posix_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ posix_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ posix_named_mutex(open_only_t open_only, const char *name);
+
+ ~posix_named_mutex();
+
+ void unlock();
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+
+ posix_named_semaphore m_sem;
+ /// @endcond
+};
+
+/// @cond
+
+inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm)
+ : m_sem(create_only, name, 1, perm)
+{}
+
+inline posix_named_mutex::posix_named_mutex(open_or_create_t, const char *name, const permissions &perm)
+ : m_sem(open_or_create, name, 1, perm)
+{}
+
+inline posix_named_mutex::posix_named_mutex(open_only_t, const char *name)
+ : m_sem(open_only, name)
+{}
+
+inline void posix_named_mutex::dont_close_on_destruction()
+{ interprocess_tester::dont_close_on_destruction(m_sem); }
+
+inline posix_named_mutex::~posix_named_mutex()
+{}
+
+inline void posix_named_mutex::lock()
+{ m_sem.wait(); }
+
+inline void posix_named_mutex::unlock()
+{ m_sem.post(); }
+
+inline bool posix_named_mutex::try_lock()
+{ return m_sem.try_wait(); }
+
+inline bool posix_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return m_sem.timed_wait(abs_time);
+}
+
+inline bool posix_named_mutex::remove(const char *name)
+{ return posix_named_semaphore::remove(name); }
+
+/// @endcond
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP
diff --git a/boost/interprocess/sync/posix/named_semaphore.hpp b/boost/interprocess/sync/posix/named_semaphore.hpp
new file mode 100644
index 0000000000..f0327a4618
--- /dev/null
+++ b/boost/interprocess/sync/posix/named_semaphore.hpp
@@ -0,0 +1,84 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
+#define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+namespace ipcdetail {
+
+class posix_named_semaphore
+{
+ posix_named_semaphore();
+ posix_named_semaphore(const posix_named_semaphore&);
+ posix_named_semaphore &operator= (const posix_named_semaphore &);
+
+ public:
+ posix_named_semaphore
+ (create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions())
+ { semaphore_open(mp_sem, DoCreate, name, initialCount, perm); }
+
+ posix_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions())
+ { semaphore_open(mp_sem, DoOpenOrCreate, name, initialCount, perm); }
+
+ posix_named_semaphore(open_only_t, const char *name)
+ { semaphore_open(mp_sem, DoOpen, name); }
+
+ ~posix_named_semaphore()
+ {
+ if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED)
+ semaphore_close(mp_sem);
+ }
+
+ void post()
+ { semaphore_post(mp_sem); }
+
+ void wait()
+ { semaphore_wait(mp_sem); }
+
+ bool try_wait()
+ { return semaphore_try_wait(mp_sem); }
+
+ bool timed_wait(const boost::posix_time::ptime &abs_time)
+ { return semaphore_timed_wait(mp_sem, abs_time); }
+
+ static bool remove(const char *name)
+ { return semaphore_unlink(name); }
+
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction()
+ { mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; }
+
+ sem_t *mp_sem;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP
diff --git a/boost/interprocess/sync/posix/pthread_helpers.hpp b/boost/interprocess/sync/posix/pthread_helpers.hpp
new file mode 100644
index 0000000000..c09ce200cf
--- /dev/null
+++ b/boost/interprocess/sync/posix/pthread_helpers.hpp
@@ -0,0 +1,168 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
+#define BOOST_INTERPROCESS_PTHREAD_HELPERS_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 <pthread.h>
+#include <errno.h>
+#include <boost/interprocess/exceptions.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+ #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+
+ //!Makes pthread_mutexattr_t cleanup easy when using exceptions
+ struct mutexattr_wrapper
+ {
+ //!Constructor
+ mutexattr_wrapper(bool recursive = false)
+ {
+ if(pthread_mutexattr_init(&m_attr)!=0 ||
+ pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 ||
+ (recursive &&
+ pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 ))
+ throw interprocess_exception("pthread_mutexattr_xxxx failed");
+ }
+
+ //!Destructor
+ ~mutexattr_wrapper() { pthread_mutexattr_destroy(&m_attr); }
+
+ //!This allows using mutexattr_wrapper as pthread_mutexattr_t
+ operator pthread_mutexattr_t&() { return m_attr; }
+
+ pthread_mutexattr_t m_attr;
+ };
+
+ //!Makes pthread_condattr_t cleanup easy when using exceptions
+ struct condattr_wrapper
+ {
+ //!Constructor
+ condattr_wrapper()
+ {
+ if(pthread_condattr_init(&m_attr)!=0 ||
+ pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
+ throw interprocess_exception("pthread_condattr_xxxx failed");
+ }
+
+ //!Destructor
+ ~condattr_wrapper() { pthread_condattr_destroy(&m_attr); }
+
+ //!This allows using condattr_wrapper as pthread_condattr_t
+ operator pthread_condattr_t&(){ return m_attr; }
+
+ pthread_condattr_t m_attr;
+ };
+
+ //!Makes initialized pthread_mutex_t cleanup easy when using exceptions
+ class mutex_initializer
+ {
+ public:
+ //!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex
+ mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr)
+ : mp_mut(&mut)
+ {
+ if(pthread_mutex_init(mp_mut, &mut_attr) != 0)
+ throw interprocess_exception("pthread_mutex_init failed");
+ }
+
+ ~mutex_initializer() { if(mp_mut) pthread_mutex_destroy(mp_mut); }
+
+ void release() {mp_mut = 0; }
+
+ private:
+ pthread_mutex_t *mp_mut;
+ };
+
+ //!Makes initialized pthread_cond_t cleanup easy when using exceptions
+ class condition_initializer
+ {
+ public:
+ condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr)
+ : mp_cond(&cond)
+ {
+ if(pthread_cond_init(mp_cond, &cond_attr)!= 0)
+ throw interprocess_exception("pthread_cond_init failed");
+ }
+
+ ~condition_initializer() { if(mp_cond) pthread_cond_destroy(mp_cond); }
+
+ void release() { mp_cond = 0; }
+
+ private:
+ pthread_cond_t *mp_cond;
+ };
+
+ #endif // #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+
+ #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
+
+ //!Makes pthread_barrierattr_t cleanup easy when using exceptions
+ struct barrierattr_wrapper
+ {
+ //!Constructor
+ barrierattr_wrapper()
+ {
+ if(pthread_barrierattr_init(&m_attr)!=0 ||
+ pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
+ throw interprocess_exception("pthread_barrierattr_xxx failed");
+ }
+
+ //!Destructor
+ ~barrierattr_wrapper() { pthread_barrierattr_destroy(&m_attr); }
+
+ //!This allows using mutexattr_wrapper as pthread_barrierattr_t
+ operator pthread_barrierattr_t&() { return m_attr; }
+
+ pthread_barrierattr_t m_attr;
+ };
+
+ //!Makes initialized pthread_barrier_t cleanup easy when using exceptions
+ class barrier_initializer
+ {
+ public:
+ //!Constructor. Takes barrier attributes to initialize the barrier
+ barrier_initializer(pthread_barrier_t &mut,
+ pthread_barrierattr_t &mut_attr,
+ int count)
+ : mp_barrier(&mut)
+ {
+ if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0)
+ throw interprocess_exception("pthread_barrier_init failed");
+ }
+
+ ~barrier_initializer() { if(mp_barrier) pthread_barrier_destroy(mp_barrier); }
+
+ void release() {mp_barrier = 0; }
+
+ private:
+ pthread_barrier_t *mp_barrier;
+ };
+
+ #endif //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
+
+}//namespace ipcdetail
+
+}//namespace interprocess
+
+}//namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
diff --git a/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/boost/interprocess/sync/posix/ptime_to_timespec.hpp
new file mode 100644
index 0000000000..7d787353bd
--- /dev/null
+++ b/boost/interprocess/sync/posix/ptime_to_timespec.hpp
@@ -0,0 +1,38 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
+#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
+
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+namespace boost {
+
+namespace interprocess {
+
+namespace ipcdetail {
+
+inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm)
+{
+ const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
+ boost::posix_time::time_duration duration (tm - epoch);
+ timespec ts;
+ ts.tv_sec = duration.total_seconds();
+ ts.tv_nsec = duration.total_nanoseconds() % 1000000000;
+ return ts;
+}
+
+} //namespace ipcdetail {
+
+} //namespace interprocess {
+
+} //namespace boost {
+
+#endif //ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
diff --git a/boost/interprocess/sync/posix/recursive_mutex.hpp b/boost/interprocess/sync/posix/recursive_mutex.hpp
new file mode 100644
index 0000000000..baa670fa9a
--- /dev/null
+++ b/boost/interprocess/sync/posix/recursive_mutex.hpp
@@ -0,0 +1,142 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Parts of the pthread code come from Boost Threads code:
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. William E. Kempf makes no representations
+// about the suitability of this software for any purpose.
+// It is provided "as is" without express or implied warranty.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <pthread.h>
+#include <errno.h>
+#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
+#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+# include <boost/interprocess/detail/os_thread_functions.hpp>
+#endif
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class posix_recursive_mutex
+{
+ posix_recursive_mutex(const posix_recursive_mutex &);
+ posix_recursive_mutex &operator=(const posix_recursive_mutex &);
+ public:
+
+ posix_recursive_mutex();
+ ~posix_recursive_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+
+ private:
+ pthread_mutex_t m_mut;
+};
+
+inline posix_recursive_mutex::posix_recursive_mutex()
+{
+ mutexattr_wrapper mut_attr(true);
+ mutex_initializer mut(m_mut, mut_attr);
+ mut.release();
+}
+
+inline posix_recursive_mutex::~posix_recursive_mutex()
+{
+ int res = pthread_mutex_destroy(&m_mut);
+ BOOST_ASSERT(res == 0);(void)res;
+}
+
+inline void posix_recursive_mutex::lock()
+{
+ if (pthread_mutex_lock(&m_mut) != 0)
+ throw lock_exception();
+}
+
+inline bool posix_recursive_mutex::try_lock()
+{
+ int res = pthread_mutex_trylock(&m_mut);
+ if (!(res == 0 || res == EBUSY))
+ throw lock_exception();
+ return res == 0;
+}
+
+inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
+ timespec ts = ptime_to_timespec(abs_time);
+ int res = pthread_mutex_timedlock(&m_mut, &ts);
+ if (res != 0 && res != ETIMEDOUT)
+ throw lock_exception();
+ return res == 0;
+
+ #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS
+
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ do{
+ if(this->try_lock()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return false;
+ }
+ // relinquish current time slice
+ thread_yield();
+ }while (true);
+ return true;
+
+ #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS
+}
+
+inline void posix_recursive_mutex::unlock()
+{
+ int res = 0;
+ res = pthread_mutex_unlock(&m_mut);
+ BOOST_ASSERT(res == 0);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/posix/semaphore.hpp b/boost/interprocess/sync/posix/semaphore.hpp
new file mode 100644
index 0000000000..b7f62cc42d
--- /dev/null
+++ b/boost/interprocess/sync/posix/semaphore.hpp
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class posix_semaphore
+{
+ posix_semaphore();
+ posix_semaphore(const posix_semaphore&);
+ posix_semaphore &operator= (const posix_semaphore &);
+
+ public:
+ posix_semaphore(unsigned int initialCount)
+ { semaphore_init(&m_sem, initialCount); }
+
+ ~posix_semaphore()
+ { semaphore_destroy(&m_sem); }
+
+ void post()
+ { semaphore_post(&m_sem); }
+
+ void wait()
+ { semaphore_wait(&m_sem); }
+
+ bool try_wait()
+ { return semaphore_try_wait(&m_sem); }
+
+ bool timed_wait(const boost::posix_time::ptime &abs_time)
+ { return semaphore_timed_wait(&m_sem, abs_time); }
+
+ private:
+ sem_t m_sem;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/boost/interprocess/sync/posix/semaphore_wrapper.hpp
new file mode 100644
index 0000000000..1aeef47662
--- /dev/null
+++ b/boost/interprocess/sync/posix/semaphore_wrapper.hpp
@@ -0,0 +1,211 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
+#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
+
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+#include <fcntl.h> //O_CREAT, O_*...
+#include <unistd.h> //close
+#include <string> //std::string
+#include <semaphore.h> //sem_* family, SEM_VALUE_MAX
+#include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
+#include <boost/assert.hpp>
+
+#ifdef SEM_FAILED
+#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
+#else
+#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
+#endif
+
+#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
+#else
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+inline bool semaphore_open
+ (sem_t *&handle, create_enum_t type, const char *origname,
+ unsigned int count = 0, const permissions &perm = permissions())
+{
+ std::string name;
+ #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
+ add_leading_slash(origname, name);
+ #else
+ create_tmp_and_clean_old_and_get_filename(origname, name);
+ #endif
+
+ //Create new mapping
+ int oflag = 0;
+ switch(type){
+ case DoOpen:
+ {
+ //No addition
+ handle = ::sem_open(name.c_str(), oflag);
+ }
+ break;
+ case DoOpenOrCreate:
+ case DoCreate:
+ {
+ while(1){
+ oflag = (O_CREAT | O_EXCL);
+ handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count);
+ if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
+ //We can't change semaphore permissions!
+ //::fchmod(handle, perm.get_permissions());
+ break;
+ }
+ else if(errno == EEXIST && type == DoOpenOrCreate){
+ oflag = 0;
+ if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
+ || (errno != ENOENT) ){
+ break;
+ }
+ }
+ else{
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ error_info err(other_error);
+ throw interprocess_exception(err);
+ }
+ }
+
+ //Check for error
+ if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
+ throw interprocess_exception(error_info(errno));
+ }
+
+ return true;
+}
+
+inline void semaphore_close(sem_t *handle)
+{
+ int ret = sem_close(handle);
+ if(ret != 0){
+ BOOST_ASSERT(0);
+ }
+}
+
+inline bool semaphore_unlink(const char *semname)
+{
+ try{
+ std::string sem_str;
+ #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
+ add_leading_slash(semname, sem_str);
+ #else
+ tmp_filename(semname, sem_str);
+ #endif
+ return 0 == sem_unlink(sem_str.c_str());
+ }
+ catch(...){
+ return false;
+ }
+}
+
+inline void semaphore_init(sem_t *handle, unsigned int initialCount)
+{
+ int ret = sem_init(handle, 1, initialCount);
+ //According to SUSV3 version 2003 edition, the return value of a successful
+ //sem_init call is not defined, but -1 is returned on failure.
+ //In the future, a successful call might be required to return 0.
+ if(ret == -1){
+ throw interprocess_exception(system_error_code());
+ }
+}
+
+inline void semaphore_destroy(sem_t *handle)
+{
+ int ret = sem_destroy(handle);
+ if(ret != 0){
+ BOOST_ASSERT(0);
+ }
+}
+
+inline void semaphore_post(sem_t *handle)
+{
+ int ret = sem_post(handle);
+ if(ret != 0){
+ throw interprocess_exception(system_error_code());
+ }
+}
+
+inline void semaphore_wait(sem_t *handle)
+{
+ int ret = sem_wait(handle);
+ if(ret != 0){
+ throw interprocess_exception(system_error_code());
+ }
+}
+
+inline bool semaphore_try_wait(sem_t *handle)
+{
+ int res = sem_trywait(handle);
+ if(res == 0)
+ return true;
+ if(system_error_code() == EAGAIN){
+ return false;
+ }
+ throw interprocess_exception(system_error_code());
+ return false;
+}
+
+inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ semaphore_wait(handle);
+ return true;
+ }
+ #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ timespec tspec = ptime_to_timespec(abs_time);
+ for (;;){
+ int res = sem_timedwait(handle, &tspec);
+ if(res == 0)
+ return true;
+ if (res > 0){
+ //buggy glibc, copy the returned error code to errno
+ errno = res;
+ }
+ if(system_error_code() == ETIMEDOUT){
+ return false;
+ }
+ throw interprocess_exception(system_error_code());
+ }
+ return false;
+ #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ boost::posix_time::ptime now;
+ do{
+ if(semaphore_try_wait(handle))
+ return true;
+ thread_yield();
+ }while((now = microsec_clock::universal_time()) < abs_time);
+ return false;
+ #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
diff --git a/boost/interprocess/sync/scoped_lock.hpp b/boost/interprocess/sync/scoped_lock.hpp
new file mode 100644
index 0000000000..bfef63a30a
--- /dev/null
+++ b/boost/interprocess/sync/scoped_lock.hpp
@@ -0,0 +1,372 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This interface is inspired by Howard Hinnant's lock proposal.
+// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SCOPED_LOCK_HPP
+#define BOOST_INTERPROCESS_SCOPED_LOCK_HPP
+
+#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/interprocess_fwd.hpp>
+#include <boost/interprocess/sync/lock_options.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+//!\file
+//!Describes the scoped_lock class.
+
+namespace boost {
+namespace interprocess {
+
+
+//!scoped_lock is meant to carry out the tasks for locking, unlocking, try-locking
+//!and timed-locking (recursive or not) for the Mutex. The Mutex need not supply all
+//!of this functionality. If the client of scoped_lock<Mutex> does not use
+//!functionality which the Mutex does not supply, no harm is done. Mutex ownership
+//!transfer is supported through the syntax of move semantics. Ownership transfer
+//!is allowed both by construction and assignment. The scoped_lock does not support
+//!copy semantics. A compile time error results if copy construction or copy
+//!assignment is attempted. Mutex ownership can also be moved from an
+//!upgradable_lock and sharable_lock via constructor. In this role, scoped_lock
+//!shares the same functionality as a write_lock.
+template <class Mutex>
+class scoped_lock
+{
+ /// @cond
+ private:
+ typedef scoped_lock<Mutex> this_type;
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_lock)
+ typedef bool this_type::*unspecified_bool_type;
+ /// @endcond
+ public:
+
+ typedef Mutex mutex_type;
+
+ //!Effects: Default constructs a scoped_lock.
+ //!Postconditions: owns() == false and mutex() == 0.
+ scoped_lock()
+ : mp_mutex(0), m_locked(false)
+ {}
+
+ //!Effects: m.lock().
+ //!Postconditions: owns() == true and mutex() == &m.
+ //!Notes: The constructor will take ownership of the mutex. If another thread
+ //! already owns the mutex, this thread will block until the mutex is released.
+ //! Whether or not this constructor handles recursive locking depends upon the mutex.
+ explicit scoped_lock(mutex_type& m)
+ : mp_mutex(&m), m_locked(false)
+ { mp_mutex->lock(); m_locked = true; }
+
+ //!Postconditions: owns() == false, and mutex() == &m.
+ //!Notes: The constructor will not take ownership of the mutex. There is no effect
+ //! required on the referenced mutex.
+ scoped_lock(mutex_type& m, defer_lock_type)
+ : mp_mutex(&m), m_locked(false)
+ {}
+
+ //!Postconditions: owns() == true, and mutex() == &m.
+ //!Notes: The constructor will suppose that the mutex is already locked. There
+ //! is no effect required on the referenced mutex.
+ scoped_lock(mutex_type& m, accept_ownership_type)
+ : mp_mutex(&m), m_locked(true)
+ {}
+
+ //!Effects: m.try_lock().
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.try_lock() executed within the constructor.
+ //!Notes: The constructor will take ownership of the mutex if it can do
+ //! so without waiting. Whether or not this constructor handles recursive
+ //! locking depends upon the mutex. If the mutex_type does not support try_lock,
+ //! this constructor will fail at compile time if instantiated, but otherwise
+ //! have no effect.
+ scoped_lock(mutex_type& m, try_to_lock_type)
+ : mp_mutex(&m), m_locked(mp_mutex->try_lock())
+ {}
+
+ //!Effects: m.timed_lock(abs_time).
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.timed_lock(abs_time) executed within the constructor.
+ //!Notes: The constructor will take ownership of the mutex if it can do
+ //! it until abs_time is reached. Whether or not this constructor
+ //! handles recursive locking depends upon the mutex. If the mutex_type
+ //! does not support try_lock, this constructor will fail at compile
+ //! time if instantiated, but otherwise have no effect.
+ scoped_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
+ : mp_mutex(&m), m_locked(mp_mutex->timed_lock(abs_time))
+ {}
+
+ //!Postconditions: mutex() == the value scop.mutex() had before the
+ //! constructor executes. s1.mutex() == 0. owns() == the value of
+ //! scop.owns() before the constructor executes. scop.owns().
+ //!Notes: If the scop scoped_lock owns the mutex, ownership is moved
+ //! to thisscoped_lock with no blocking. If the scop scoped_lock does not
+ //! own the mutex, then neither will this scoped_lock. Only a moved
+ //! scoped_lock's will match this signature. An non-moved scoped_lock
+ //! can be moved with the expression: "boost::move(lock);". This
+ //! constructor does not alter the state of the mutex, only potentially
+ //! who owns it.
+ scoped_lock(BOOST_RV_REF(scoped_lock) scop)
+ : mp_mutex(0), m_locked(scop.owns())
+ { mp_mutex = scop.release(); }
+
+ //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the
+ //! referenced mutex. upgr.release() is called.
+ //!Postconditions: mutex() == the value upgr.mutex() had before the construction.
+ //! upgr.mutex() == 0. owns() == upgr.owns() before the construction.
+ //! upgr.owns() == false after the construction.
+ //!Notes: If upgr is locked, this constructor will lock this scoped_lock while
+ //! unlocking upgr. If upgr is unlocked, then this scoped_lock will be
+ //! unlocked as well. Only a moved upgradable_lock's will match this
+ //! signature. An non-moved upgradable_lock can be moved with
+ //! the expression: "boost::move(lock);" This constructor may block if
+ //! other threads hold a sharable_lock on this mutex (sharable_lock's can
+ //! share ownership with an upgradable_lock).
+ template<class T>
+ explicit scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ upgradable_lock<mutex_type> &u_lock = upgr;
+ if(u_lock.owns()){
+ u_lock.mutex()->unlock_upgradable_and_lock();
+ m_locked = true;
+ }
+ mp_mutex = u_lock.release();
+ }
+
+ //!Effects: If upgr.owns() then calls try_unlock_upgradable_and_lock() on the
+ //!referenced mutex:
+ //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains
+ //! the value from upgr.release() and owns() is set to true.
+ //! b)if try_unlock_upgradable_and_lock() returns false then upgr is
+ //! unaffected and this scoped_lock construction as the same effects as
+ //! a default construction.
+ //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release()
+ //! and owns() is set to false
+ //!Notes: This construction will not block. It will try to obtain mutex
+ //! ownership from upgr immediately, while changing the lock type from a
+ //! "read lock" to a "write lock". If the "read lock" isn't held in the
+ //! first place, the mutex merely changes type to an unlocked "write lock".
+ //! If the "read lock" is held, then mutex transfer occurs only if it can
+ //! do so in a non-blocking manner.
+ template<class T>
+ scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, try_to_lock_type
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ upgradable_lock<mutex_type> &u_lock = upgr;
+ if(u_lock.owns()){
+ if((m_locked = u_lock.mutex()->try_unlock_upgradable_and_lock()) == true){
+ mp_mutex = u_lock.release();
+ }
+ }
+ else{
+ u_lock.release();
+ }
+ }
+
+ //!Effects: If upgr.owns() then calls timed_unlock_upgradable_and_lock(abs_time)
+ //! on the referenced mutex:
+ //! a)if timed_unlock_upgradable_and_lock(abs_time) returns true then mutex()
+ //! obtains the value from upgr.release() and owns() is set to true.
+ //! b)if timed_unlock_upgradable_and_lock(abs_time) returns false then upgr
+ //! is unaffected and this scoped_lock construction as the same effects
+ //! as a default construction.
+ //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release()
+ //! and owns() is set to false
+ //!Notes: This construction will not block. It will try to obtain mutex ownership
+ //! from upgr immediately, while changing the lock type from a "read lock" to a
+ //! "write lock". If the "read lock" isn't held in the first place, the mutex
+ //! merely changes type to an unlocked "write lock". If the "read lock" is held,
+ //! then mutex transfer occurs only if it can do so in a non-blocking manner.
+ template<class T>
+ scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, boost::posix_time::ptime &abs_time
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ upgradable_lock<mutex_type> &u_lock = upgr;
+ if(u_lock.owns()){
+ if((m_locked = u_lock.mutex()->timed_unlock_upgradable_and_lock(abs_time)) == true){
+ mp_mutex = u_lock.release();
+ }
+ }
+ else{
+ u_lock.release();
+ }
+ }
+
+ //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the
+ //!referenced mutex.
+ //! a)if try_unlock_sharable_and_lock() returns true then mutex() obtains
+ //! the value from shar.release() and owns() is set to true.
+ //! b)if try_unlock_sharable_and_lock() returns false then shar is
+ //! unaffected and this scoped_lock construction has the same
+ //! effects as a default construction.
+ //! c)Else shar.owns() is false. mutex() obtains the value from
+ //! shar.release() and owns() is set to false
+ //!Notes: This construction will not block. It will try to obtain mutex
+ //! ownership from shar immediately, while changing the lock type from a
+ //! "read lock" to a "write lock". If the "read lock" isn't held in the
+ //! first place, the mutex merely changes type to an unlocked "write lock".
+ //! If the "read lock" is held, then mutex transfer occurs only if it can
+ //! do so in a non-blocking manner.
+ template<class T>
+ scoped_lock(BOOST_RV_REF(sharable_lock<T>) shar, try_to_lock_type
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ sharable_lock<mutex_type> &s_lock = shar;
+ if(s_lock.owns()){
+ if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock()) == true){
+ mp_mutex = s_lock.release();
+ }
+ }
+ else{
+ s_lock.release();
+ }
+ }
+
+ //!Effects: if (owns()) mp_mutex->unlock().
+ //!Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
+ ~scoped_lock()
+ {
+ try{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
+ catch(...){}
+ }
+
+ //!Effects: If owns() before the call, then unlock() is called on mutex().
+ //! *this gets the state of scop and scop gets set to a default constructed state.
+ //!Notes: With a recursive mutex it is possible that both this and scop own
+ //! the same mutex before the assignment. In this case, this will own the
+ //! mutex after the assignment (and scop will not), but the mutex's lock
+ //! count will be decremented by one.
+ scoped_lock &operator=(BOOST_RV_REF(scoped_lock) scop)
+ {
+ if(this->owns())
+ this->unlock();
+ m_locked = scop.owns();
+ mp_mutex = scop.release();
+ return *this;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls lock() on the referenced mutex.
+ //!Postconditions: owns() == true.
+ //!Notes: The scoped_lock changes from a state of not owning the mutex, to
+ //! owning the mutex, blocking if necessary.
+ void lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ mp_mutex->lock();
+ m_locked = true;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls try_lock() on the referenced mutex.
+ //!Postconditions: owns() == the value returned from mutex()->try_lock().
+ //!Notes: The scoped_lock changes from a state of not owning the mutex, to
+ //! owning the mutex, but only if blocking was not required. If the
+ //! mutex_type does not support try_lock(), this function will fail at
+ //! compile time if instantiated, but otherwise have no effect.*/
+ bool try_lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->try_lock();
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls timed_lock(abs_time) on the referenced mutex.
+ //!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
+ //!Notes: The scoped_lock changes from a state of not owning the mutex, to
+ //! owning the mutex, but only if it can obtain ownership by the specified
+ //! time. If the mutex_type does not support timed_lock (), this function
+ //! will fail at compile time if instantiated, but otherwise have no effect.*/
+ bool timed_lock(const boost::posix_time::ptime& abs_time)
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->timed_lock(abs_time);
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
+ //! exception. Calls unlock() on the referenced mutex.
+ //!Postconditions: owns() == false.
+ //!Notes: The scoped_lock changes from a state of owning the mutex, to not
+ //! owning the mutex.*/
+ void unlock()
+ {
+ if(!mp_mutex || !m_locked)
+ throw lock_exception();
+ mp_mutex->unlock();
+ m_locked = false;
+ }
+
+ //!Effects: Returns true if this scoped_lock has acquired
+ //!the referenced mutex.
+ bool owns() const
+ { return m_locked && mp_mutex; }
+
+ //!Conversion to bool.
+ //!Returns owns().
+ operator unspecified_bool_type() const
+ { return m_locked? &this_type::m_locked : 0; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if
+ //!there is no mutex to reference.
+ mutex_type* mutex() const
+ { return mp_mutex; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
+ //! mutex to reference.
+ //!Postconditions: mutex() == 0 and owns() == false.
+ mutex_type* release()
+ {
+ mutex_type *mut = mp_mutex;
+ mp_mutex = 0;
+ m_locked = false;
+ return mut;
+ }
+
+ //!Effects: Swaps state with moved lock.
+ //!Throws: Nothing.
+ void swap( scoped_lock<mutex_type> &other)
+ {
+ std::swap(mp_mutex, other.mp_mutex);
+ std::swap(m_locked, other.m_locked);
+ }
+
+ /// @cond
+ private:
+ mutex_type *mp_mutex;
+ bool m_locked;
+ /// @endcond
+};
+
+} // namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_SCOPED_LOCK_HPP
diff --git a/boost/interprocess/sync/sharable_lock.hpp b/boost/interprocess/sync/sharable_lock.hpp
new file mode 100644
index 0000000000..c8b7c1d26e
--- /dev/null
+++ b/boost/interprocess/sync/sharable_lock.hpp
@@ -0,0 +1,305 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This interface is inspired by Howard Hinnant's lock proposal.
+// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
+#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
+
+#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/interprocess_fwd.hpp>
+#include <boost/interprocess/sync/lock_options.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+//!\file
+//!Describes the upgradable_lock class that serves to acquire the upgradable
+//!lock of a mutex.
+
+namespace boost {
+namespace interprocess {
+
+
+//!sharable_lock is meant to carry out the tasks for sharable-locking
+//!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking
+//!(recursive or not) for the Mutex. The Mutex need not supply all of this
+//!functionality. If the client of sharable_lock<Mutex> does not use functionality which
+//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among
+//!sharable_locks, and a single upgradable_lock. sharable_lock does not support
+//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock,
+//!upgradable_lock and scoped_lock via transfer_lock syntax.*/
+template <class SharableMutex>
+class sharable_lock
+{
+ public:
+ typedef SharableMutex mutex_type;
+ /// @cond
+ private:
+ typedef sharable_lock<SharableMutex> this_type;
+ explicit sharable_lock(scoped_lock<mutex_type>&);
+ typedef bool this_type::*unspecified_bool_type;
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock)
+ /// @endcond
+ public:
+
+ //!Effects: Default constructs a sharable_lock.
+ //!Postconditions: owns() == false and mutex() == 0.
+ sharable_lock()
+ : mp_mutex(0), m_locked(false)
+ {}
+
+ //!Effects: m.lock_sharable().
+ //!Postconditions: owns() == true and mutex() == &m.
+ //!Notes: The constructor will take sharable-ownership of the mutex. If
+ //! another thread already owns the mutex with exclusive ownership
+ //! (scoped_lock), this thread will block until the mutex is released.
+ //! If another thread owns the mutex with sharable or upgradable ownership,
+ //! then no blocking will occur. Whether or not this constructor handles
+ //! recursive locking depends upon the mutex.
+ explicit sharable_lock(mutex_type& m)
+ : mp_mutex(&m), m_locked(false)
+ { mp_mutex->lock_sharable(); m_locked = true; }
+
+ //!Postconditions: owns() == false, and mutex() == &m.
+ //!Notes: The constructor will not take ownership of the mutex. There is no effect
+ //! required on the referenced mutex.
+ sharable_lock(mutex_type& m, defer_lock_type)
+ : mp_mutex(&m), m_locked(false)
+ {}
+
+ //!Postconditions: owns() == true, and mutex() == &m.
+ //!Notes: The constructor will suppose that the mutex is already sharable
+ //! locked. There is no effect required on the referenced mutex.
+ sharable_lock(mutex_type& m, accept_ownership_type)
+ : mp_mutex(&m), m_locked(true)
+ {}
+
+ //!Effects: m.try_lock_sharable()
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.try_lock_sharable() executed within the constructor.
+ //!Notes: The constructor will take sharable-ownership of the mutex if it
+ //! can do so without waiting. Whether or not this constructor handles
+ //! recursive locking depends upon the mutex. If the mutex_type does not
+ //! support try_lock_sharable, this constructor will fail at compile
+ //! time if instantiated, but otherwise have no effect.
+ sharable_lock(mutex_type& m, try_to_lock_type)
+ : mp_mutex(&m), m_locked(false)
+ { m_locked = mp_mutex->try_lock_sharable(); }
+
+ //!Effects: m.timed_lock_sharable(abs_time)
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.timed_lock_sharable() executed within the constructor.
+ //!Notes: The constructor will take sharable-ownership of the mutex if it
+ //! can do so within the time specified. Whether or not this constructor
+ //! handles recursive locking depends upon the mutex. If the mutex_type
+ //! does not support timed_lock_sharable, this constructor will fail at
+ //! compile time if instantiated, but otherwise have no effect.
+ sharable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
+ : mp_mutex(&m), m_locked(false)
+ { m_locked = mp_mutex->timed_lock_sharable(abs_time); }
+
+ //!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns()
+ //! before the construction. upgr.owns() == false after the construction.
+ //!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this
+ //! sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then
+ //! neither will this sharable_lock. Only a moved sharable_lock's will match this
+ //! signature. An non-moved sharable_lock can be moved with the expression:
+ //! "boost::move(lock);". This constructor does not alter the state of the mutex,
+ //! only potentially who owns it.
+ sharable_lock(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
+ : mp_mutex(0), m_locked(upgr.owns())
+ { mp_mutex = upgr.release(); }
+
+ //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the
+ //! referenced mutex.
+ //!Postconditions: mutex() == the value upgr.mutex() had before the construction.
+ //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction.
+ //! upgr.owns() == false after the construction.
+ //!Notes: If upgr is locked, this constructor will lock this sharable_lock while
+ //! unlocking upgr. Only a moved sharable_lock's will match this
+ //! signature. An non-moved upgradable_lock can be moved with the expression:
+ //! "boost::move(lock);".*/
+ template<class T>
+ sharable_lock(BOOST_RV_REF(upgradable_lock<T>) upgr
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ upgradable_lock<mutex_type> &u_lock = upgr;
+ if(u_lock.owns()){
+ u_lock.mutex()->unlock_upgradable_and_lock_sharable();
+ m_locked = true;
+ }
+ mp_mutex = u_lock.release();
+ }
+
+ //!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the
+ //! referenced mutex.
+ //!Postconditions: mutex() == the value scop.mutex() had before the construction.
+ //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the
+ //! construction, scop.owns() == false.
+ //!Notes: If scop is locked, this constructor will transfer the exclusive ownership
+ //! to a sharable-ownership of this sharable_lock.
+ //! Only a moved scoped_lock's will match this
+ //! signature. An non-moved scoped_lock can be moved with the expression:
+ //! "boost::move(lock);".
+ template<class T>
+ sharable_lock(BOOST_RV_REF(scoped_lock<T>) scop
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ scoped_lock<mutex_type> &e_lock = scop;
+ if(e_lock.owns()){
+ e_lock.mutex()->unlock_and_lock_sharable();
+ m_locked = true;
+ }
+ mp_mutex = e_lock.release();
+ }
+
+ //!Effects: if (owns()) mp_mutex->unlock_sharable().
+ //!Notes: The destructor behavior ensures that the mutex lock is not leaked.
+ ~sharable_lock()
+ {
+ try{
+ if(m_locked && mp_mutex) mp_mutex->unlock_sharable();
+ }
+ catch(...){}
+ }
+
+ //!Effects: If owns() before the call, then unlock_sharable() is called on mutex().
+ //! *this gets the state of upgr and upgr gets set to a default constructed state.
+ //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex
+ //! before the assignment. In this case, this will own the mutex after the assignment
+ //! (and upgr will not), but the mutex's lock count will be decremented by one.
+ sharable_lock &operator=(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
+ {
+ if(this->owns())
+ this->unlock();
+ m_locked = upgr.owns();
+ mp_mutex = upgr.release();
+ return *this;
+ }
+
+ //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
+ //! exception. Calls lock_sharable() on the referenced mutex.
+ //!Postconditions: owns() == true.
+ //!Notes: The sharable_lock changes from a state of not owning the
+ //! mutex, to owning the mutex, blocking if necessary.
+ void lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ mp_mutex->lock_sharable();
+ m_locked = true;
+ }
+
+ //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
+ //! exception. Calls try_lock_sharable() on the referenced mutex.
+ //!Postconditions: owns() == the value returned from
+ //! mutex()->try_lock_sharable().
+ //!Notes: The sharable_lock changes from a state of not owning the mutex,
+ //! to owning the mutex, but only if blocking was not required. If the
+ //! mutex_type does not support try_lock_sharable(), this function will
+ //! fail at compile time if instantiated, but otherwise have no effect.
+ bool try_lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->try_lock_sharable();
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
+ //! exception. Calls timed_lock_sharable(abs_time) on the referenced mutex.
+ //!Postconditions: owns() == the value returned from
+ //! mutex()->timed_lock_sharable(elps_time).
+ //!Notes: The sharable_lock changes from a state of not owning the mutex,
+ //! to owning the mutex, but only if it can obtain ownership within the
+ //! specified time interval. If the mutex_type does not support
+ //! timed_lock_sharable(), this function will fail at compile time if
+ //! instantiated, but otherwise have no effect.
+ bool timed_lock(const boost::posix_time::ptime& abs_time)
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->timed_lock_sharable(abs_time);
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception.
+ //! Calls unlock_sharable() on the referenced mutex.
+ //!Postconditions: owns() == false.
+ //!Notes: The sharable_lock changes from a state of owning the mutex, to
+ //! not owning the mutex.
+ void unlock()
+ {
+ if(!mp_mutex || !m_locked)
+ throw lock_exception();
+ mp_mutex->unlock_sharable();
+ m_locked = false;
+ }
+
+ //!Effects: Returns true if this scoped_lock has
+ //!acquired the referenced mutex.
+ bool owns() const
+ { return m_locked && mp_mutex; }
+
+ //!Conversion to bool.
+ //!Returns owns().
+ operator unspecified_bool_type() const
+ { return m_locked? &this_type::m_locked : 0; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if
+ //!there is no mutex to reference.
+ mutex_type* mutex() const
+ { return mp_mutex; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
+ //! mutex to reference.
+ //!Postconditions: mutex() == 0 and owns() == false.
+ mutex_type* release()
+ {
+ mutex_type *mut = mp_mutex;
+ mp_mutex = 0;
+ m_locked = false;
+ return mut;
+ }
+
+ //!Effects: Swaps state with moved lock.
+ //!Throws: Nothing.
+ void swap(sharable_lock<mutex_type> &other)
+ {
+ std::swap(mp_mutex, other.mp_mutex);
+ std::swap(m_locked, other.m_locked);
+ }
+
+ /// @cond
+ private:
+ mutex_type *mp_mutex;
+ bool m_locked;
+ /// @endcond
+};
+
+} // namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
diff --git a/boost/interprocess/sync/shm/named_condition.hpp b/boost/interprocess/sync/shm/named_condition.hpp
new file mode 100644
index 0000000000..0d67c25757
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_condition.hpp
@@ -0,0 +1,379 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
+#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/sync/named_mutex.hpp>
+#include <boost/interprocess/permissions.hpp>
+#if defined BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#endif
+
+
+//!\file
+//!Describes process-shared variables interprocess_condition class
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+/// @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 shm_named_condition
+{
+ /// @cond
+ //Non-copyable
+ shm_named_condition();
+ shm_named_condition(const shm_named_condition &);
+ shm_named_condition &operator=(const shm_named_condition &);
+ /// @endcond
+ public:
+ //!Creates a global condition with a name.
+ //!If the condition can't be created throws interprocess_exception
+ shm_named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global condition with a name.
+ //!If the condition is created, this call is equivalent to
+ //!shm_named_condition(create_only_t, ... )
+ //!If the condition is already created, this call is equivalent
+ //!shm_named_condition(open_only_t, ... )
+ //!Does not throw
+ shm_named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global condition with a name if that condition is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ shm_named_condition(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~shm_named_condition();
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.*/
+ void notify_one();
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all();
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock);
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred);
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
+
+ //!Erases a named condition from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @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
+ {
+ Lock &l_;
+ public:
+ lock_inverter(Lock &l)
+ : l_(l)
+ {}
+ void lock() { l_.unlock(); }
+ void unlock() { l_.lock(); }
+ };
+
+ #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
+ 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_;
+ };
+ #endif
+
+ 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;
+ /// @endcond
+};
+
+/// @cond
+
+inline shm_named_condition::~shm_named_condition()
+{}
+
+inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(condition_holder) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoCreate)
+ ,perm)
+{}
+
+inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(condition_holder) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpenOrCreate)
+ ,perm)
+{}
+
+inline shm_named_condition::shm_named_condition(open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpen))
+{}
+
+inline void shm_named_condition::dont_close_on_destruction()
+{ interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+#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();
+}
+
+inline void shm_named_condition::notify_all()
+{
+ scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
+ this->condition()->notify_all();
+}
+
+template <typename L>
+inline void shm_named_condition::wait(L& lock)
+{
+ if (!lock)
+ throw lock_exception();
+ this->do_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);
+}
+
+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);
+}
+
+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;
+}
+
+#else
+
+inline void shm_named_condition::notify_one()
+{ this->condition()->notify_one(); }
+
+inline void shm_named_condition::notify_all()
+{ this->condition()->notify_all(); }
+
+template <typename L>
+inline void shm_named_condition::wait(L& lock)
+{
+ lock_wrapper<L> newlock(lock);
+ this->condition()->wait(newlock);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+#endif
+
+inline bool shm_named_condition::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+/// @endcond
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP
diff --git a/boost/interprocess/sync/shm/named_creation_functor.hpp b/boost/interprocess/sync/shm/named_creation_functor.hpp
new file mode 100644
index 0000000000..11a1db1d6f
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_creation_functor.hpp
@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
+#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
+
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct named_creation_functor_no_arg{};
+
+template <class T, class Arg = named_creation_functor_no_arg>
+class named_creation_functor
+{
+ typedef named_creation_functor_no_arg no_arg_t;
+ public:
+ named_creation_functor(create_enum_t type, Arg arg = Arg())
+ : m_creation_type(type), m_arg(arg){}
+
+ template<class ArgType>
+ void construct(void *address, typename enable_if_c<is_same<ArgType, no_arg_t>::value>::type * = 0) const
+ { new(address)T; }
+
+ template<class ArgType>
+ void construct(void *address, typename enable_if_c<!is_same<ArgType, no_arg_t>::value>::type * = 0) const
+ { new(address)T(m_arg); }
+
+ bool operator()(void *address, std::size_t, bool created) const
+ {
+ switch(m_creation_type){
+ case DoOpen:
+ return true;
+ break;
+ case DoCreate:
+ case DoOpenOrCreate:
+ if(created){
+ construct<Arg>(address);
+ }
+ return true;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ }
+ private:
+ create_enum_t m_creation_type;
+ Arg m_arg;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP
diff --git a/boost/interprocess/sync/shm/named_mutex.hpp b/boost/interprocess/sync/shm/named_mutex.hpp
new file mode 100644
index 0000000000..a71eb4fe68
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_mutex.hpp
@@ -0,0 +1,184 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+
+//!\file
+//!Describes a named mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class named_condition;
+
+//!A mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named mutex.
+class shm_named_mutex
+{
+ /// @cond
+
+ //Non-copyable
+ shm_named_mutex();
+ shm_named_mutex(const shm_named_mutex &);
+ shm_named_mutex &operator=(const shm_named_mutex &);
+ friend class named_condition;
+ /// @endcond
+
+ public:
+ //!Creates a global interprocess_mutex with a name.
+ //!Throws interprocess_exception on error.
+ shm_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global mutex with a name.
+ //!If the mutex is created, this call is equivalent to
+ //!shm_named_mutex(create_only_t, ... )
+ //!If the mutex is already created, this call is equivalent
+ //!shm_named_mutex(open_only_t, ... )
+ //!Does not throw
+ shm_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global mutex with a name if that mutex is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ shm_named_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~shm_named_mutex();
+
+ //!Unlocks a previously locked
+ //!interprocess_mutex.
+ void unlock();
+
+ //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked.
+ //!Throws interprocess_exception if a severe error is found
+ void lock();
+
+ //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
+ //!is already locked, returns true when success.
+ //!Throws interprocess_exception if a severe error is found
+ bool try_lock();
+
+ //!Tries to lock the interprocess_mutex until time abs_time,
+ //!Returns false when timeout expires, returns true when locks.
+ //!Throws interprocess_exception if a severe error is found
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Erases a named mutex from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ interprocess_mutex *mutex() const
+ { return static_cast<interprocess_mutex*>(m_shmem.get_user_address()); }
+
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::named_creation_functor<interprocess_mutex> construct_func_t;
+ /// @endcond
+};
+
+/// @cond
+
+inline void shm_named_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline shm_named_mutex::~shm_named_mutex()
+{}
+
+inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoCreate)
+ ,perm)
+{}
+
+inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpenOrCreate)
+ ,perm)
+{}
+
+inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpen))
+{}
+
+inline void shm_named_mutex::lock()
+{ this->mutex()->lock(); }
+
+inline void shm_named_mutex::unlock()
+{ this->mutex()->unlock(); }
+
+inline bool shm_named_mutex::try_lock()
+{ return this->mutex()->try_lock(); }
+
+inline bool shm_named_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);
+}
+
+inline bool shm_named_mutex::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+/// @endcond
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP
diff --git a/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/boost/interprocess/sync/shm/named_recursive_mutex.hpp
new file mode 100644
index 0000000000..461c97eb32
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_recursive_mutex.hpp
@@ -0,0 +1,175 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+//!\file
+//!Describes a named shm_named_recursive_mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+/// @cond
+class interprocess_tester;
+/// @endcond
+
+class shm_named_recursive_mutex
+{
+ /// @cond
+ //Non-copyable
+ shm_named_recursive_mutex();
+ shm_named_recursive_mutex(const shm_named_recursive_mutex &);
+ shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &);
+ /// @endcond
+ public:
+
+ //!Creates a global recursive_mutex with a name.
+ //!If the recursive_mutex can't be created throws interprocess_exception
+ shm_named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global recursive_mutex with a name.
+ //!If the recursive_mutex is created, this call is equivalent to
+ //!shm_named_recursive_mutex(create_only_t, ... )
+ //!If the recursive_mutex is already created, this call is equivalent
+ //!shm_named_recursive_mutex(open_only_t, ... )
+ //!Does not throw
+ shm_named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global recursive_mutex with a name if that recursive_mutex is previously
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ shm_named_recursive_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~shm_named_recursive_mutex();
+
+ //!Unlocks a previously locked
+ //!shm_named_recursive_mutex.
+ void unlock();
+
+ //!Locks shm_named_recursive_mutex, sleeps when shm_named_recursive_mutex is already locked.
+ //!Throws interprocess_exception if a severe error is found.
+ void lock();
+
+ //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex
+ //!is already locked, returns true when success.
+ //!Throws interprocess_exception if a severe error is found.
+ bool try_lock();
+
+ //!Tries to lock the shm_named_recursive_mutex until time abs_time,
+ //!Returns false when timeout expires, returns true when locks.
+ //!Throws interprocess_exception if a severe error is found
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Erases a named recursive mutex
+ //!from the system
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+
+ interprocess_recursive_mutex *mutex() const
+ { return static_cast<interprocess_recursive_mutex*>(m_shmem.get_user_address()); }
+
+ managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef named_creation_functor<interprocess_recursive_mutex> construct_func_t;
+ /// @endcond
+};
+
+inline shm_named_recursive_mutex::~shm_named_recursive_mutex()
+{}
+
+inline void shm_named_recursive_mutex::dont_close_on_destruction()
+{ interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_recursive_mutex) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoCreate)
+ ,perm)
+{}
+
+inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_recursive_mutex) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpenOrCreate)
+ ,perm)
+{}
+
+inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpen))
+{}
+
+inline void shm_named_recursive_mutex::lock()
+{ this->mutex()->lock(); }
+
+inline void shm_named_recursive_mutex::unlock()
+{ this->mutex()->unlock(); }
+
+inline bool shm_named_recursive_mutex::try_lock()
+{ return this->mutex()->try_lock(); }
+
+inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
+
+inline bool shm_named_recursive_mutex::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/shm/named_semaphore.hpp b/boost/interprocess/sync/shm/named_semaphore.hpp
new file mode 100644
index 0000000000..c6d3830db5
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_semaphore.hpp
@@ -0,0 +1,141 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/sync/interprocess_semaphore.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class shm_named_semaphore
+{
+ /// @cond
+
+ //Non-copyable
+ shm_named_semaphore();
+ shm_named_semaphore(const shm_named_semaphore &);
+ shm_named_semaphore &operator=(const shm_named_semaphore &);
+ /// @endcond
+
+ public:
+ shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ shm_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ shm_named_semaphore(open_only_t, const char *name);
+
+ ~shm_named_semaphore();
+
+ void post();
+ void wait();
+ bool try_wait();
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+
+ interprocess_semaphore *semaphore() const
+ { return static_cast<interprocess_semaphore*>(m_shmem.get_user_address()); }
+
+ managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef named_creation_functor<interprocess_semaphore, int> construct_func_t;
+ /// @endcond
+};
+
+inline shm_named_semaphore::~shm_named_semaphore()
+{}
+
+inline void shm_named_semaphore::dont_close_on_destruction()
+{ interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline shm_named_semaphore::shm_named_semaphore
+ (create_only_t, const char *name, unsigned int initialCount, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_semaphore) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoCreate, initialCount)
+ ,perm)
+{}
+
+inline shm_named_semaphore::shm_named_semaphore
+ (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_semaphore) +
+ managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpenOrCreate, initialCount)
+ ,perm)
+{}
+
+inline shm_named_semaphore::shm_named_semaphore
+ (open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(DoOpen, 0))
+{}
+
+inline void shm_named_semaphore::post()
+{ semaphore()->post(); }
+
+inline void shm_named_semaphore::wait()
+{ semaphore()->wait(); }
+
+inline bool shm_named_semaphore::try_wait()
+{ return semaphore()->try_wait(); }
+
+inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ return semaphore()->timed_wait(abs_time);
+}
+
+inline bool shm_named_semaphore::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp
new file mode 100644
index 0000000000..338fa98f7d
--- /dev/null
+++ b/boost/interprocess/sync/shm/named_upgradable_mutex.hpp
@@ -0,0 +1,372 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
+#define BOOST_INTERPROCESS_NAMED_UPGRADABLE_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_upgradable_mutex.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+//!\file
+//!Describes a named upgradable mutex class for inter-process synchronization
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+/// @endcond
+
+class named_condition;
+
+//!A upgradable mutex with a global name, so it can be found from different
+//!processes. This mutex can't be placed in shared memory, and
+//!each process should have it's own named upgradable mutex.
+class named_upgradable_mutex
+{
+ /// @cond
+ //Non-copyable
+ named_upgradable_mutex();
+ named_upgradable_mutex(const named_upgradable_mutex &);
+ named_upgradable_mutex &operator=(const named_upgradable_mutex &);
+ friend class named_condition;
+ /// @endcond
+ public:
+
+ //!Creates a global upgradable mutex with a name.
+ //!If the upgradable mutex can't be created throws interprocess_exception
+ named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
+
+ //!Opens or creates a global upgradable mutex with a name, and an initial count.
+ //!If the upgradable mutex is created, this call is equivalent to
+ //!named_upgradable_mutex(create_only_t, ...)
+ //!If the upgradable mutex is already created, this call is equivalent to
+ //!named_upgradable_mutex(open_only_t, ... ).
+ named_upgradable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
+
+ //!Opens a global upgradable mutex with a name if that upgradable mutex
+ //!is previously.
+ //!created. If it is not previously created this function throws
+ //!interprocess_exception.
+ named_upgradable_mutex(open_only_t open_only, const char *name);
+
+ //!Destroys *this and indicates that the calling process is finished using
+ //!the resource. The destructor function will deallocate
+ //!any system resources allocated by the system for use by this process for
+ //!this resource. The resource can still be opened again calling
+ //!the open constructor overload. To erase the resource from the system
+ //!use remove().
+ ~named_upgradable_mutex();
+
+ //Exclusive locking
+
+ //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
+ //! and if another thread has exclusive, sharable or upgradable ownership of
+ //! the mutex, it waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! without waiting. If no other thread has exclusive, sharable or upgradable
+ //! ownership of the mutex this succeeds.
+ //!Returns: If it can acquire exclusive ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock();
+
+ //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive, sharable or
+ //! upgradable ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The calling thread releases the exclusive ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock();
+
+ //Sharable locking
+
+ //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
+ //! and if another thread has exclusive ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! without waiting. If no other thread has exclusive ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire sharable ownership immediately returns true. If it
+ //! has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_sharable();
+
+ //!Effects: The calling thread tries to acquire sharable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The calling thread releases the sharable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_sharable();
+
+ //Upgradable locking
+
+ //!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
+ //! and if another thread has exclusive or upgradable ownership of the mutex,
+ //! waits until it can obtain the ownership.
+ //!Throws: interprocess_exception on error.
+ void lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! without waiting. If no other thread has exclusive or upgradable ownership
+ //! of the mutex this succeeds.
+ //!Returns: If it can acquire upgradable ownership immediately returns true.
+ //! If it has to wait, returns false.
+ //!Throws: interprocess_exception on error.
+ bool try_lock_upgradable();
+
+ //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
+ //! waiting if necessary until no other thread has exclusive or upgradable
+ //! ownership of the mutex or abs_time is reached.
+ //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
+ //!Throws: interprocess_exception on error.
+ bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The calling thread releases the upgradable ownership of the mutex.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable();
+
+ //Demotions
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! upgradable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_upgradable();
+
+ //!Precondition: The thread must have exclusive ownership of the mutex.
+ //!Effects: The thread atomically releases exclusive ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_and_lock_sharable();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! sharable ownership. This operation is non-blocking.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock_sharable();
+
+ //Promotions
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and acquires
+ //! exclusive ownership. This operation will block until all threads with
+ //! sharable ownership release it.
+ //!Throws: An exception derived from interprocess_exception on error.
+ void unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to
+ //! acquire exclusive ownership. This operation will fail if there are threads
+ //! with sharable ownership, but it will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_upgradable_and_lock();
+
+ //!Precondition: The thread must have upgradable ownership of the mutex.
+ //!Effects: The thread atomically releases upgradable ownership and tries to acquire
+ //! exclusive ownership, waiting if necessary until abs_time. This operation will
+ //! fail if there are threads with sharable ownership or timeout reaches, but it
+ //! will maintain upgradable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
+
+ //!Precondition: The thread must have sharable ownership of the mutex.
+ //!Effects: The thread atomically releases sharable ownership and tries to acquire
+ //! exclusive ownership. This operation will fail if there are threads with sharable
+ //! or upgradable ownership, but it will maintain sharable ownership.
+ //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
+ //!Throws: An exception derived from interprocess_exception on error.
+ bool try_unlock_sharable_and_lock();
+
+ bool try_unlock_sharable_and_lock_upgradable();
+
+ //!Erases a named upgradable mutex from the system.
+ //!Returns false on error. Never throws.
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class ipcdetail::interprocess_tester;
+ void dont_close_on_destruction();
+
+ interprocess_upgradable_mutex *mutex() const
+ { return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_user_address()); }
+
+ ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+ typedef ipcdetail::named_creation_functor<interprocess_upgradable_mutex> construct_func_t;
+ /// @endcond
+};
+
+/// @cond
+
+inline named_upgradable_mutex::~named_upgradable_mutex()
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (create_only_t, const char *name, const permissions &perm)
+ : m_shmem (create_only
+ ,name
+ ,sizeof(interprocess_upgradable_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoCreate)
+ ,perm)
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_shmem (open_or_create
+ ,name
+ ,sizeof(interprocess_upgradable_mutex) +
+ ipcdetail::managed_open_or_create_impl<shared_memory_object>::
+ ManagedOpenOrCreateUserOffset
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpenOrCreate)
+ ,perm)
+{}
+
+inline named_upgradable_mutex::named_upgradable_mutex
+ (open_only_t, const char *name)
+ : m_shmem (open_only
+ ,name
+ ,read_write
+ ,0
+ ,construct_func_t(ipcdetail::DoOpen))
+{}
+
+inline void named_upgradable_mutex::dont_close_on_destruction()
+{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
+
+inline void named_upgradable_mutex::lock()
+{ this->mutex()->lock(); }
+
+inline void named_upgradable_mutex::unlock()
+{ this->mutex()->unlock(); }
+
+inline bool named_upgradable_mutex::try_lock()
+{ return this->mutex()->try_lock(); }
+
+inline bool named_upgradable_mutex::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
+
+inline void named_upgradable_mutex::lock_upgradable()
+{ this->mutex()->lock_upgradable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable()
+{ this->mutex()->unlock_upgradable(); }
+
+inline bool named_upgradable_mutex::try_lock_upgradable()
+{ return this->mutex()->try_lock_upgradable(); }
+
+inline bool named_upgradable_mutex::timed_lock_upgradable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_upgradable();
+ return true;
+ }
+ return this->mutex()->timed_lock_upgradable(abs_time);
+}
+
+inline void named_upgradable_mutex::lock_sharable()
+{ this->mutex()->lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_sharable()
+{ this->mutex()->unlock_sharable(); }
+
+inline bool named_upgradable_mutex::try_lock_sharable()
+{ return this->mutex()->try_lock_sharable(); }
+
+inline bool named_upgradable_mutex::timed_lock_sharable
+ (const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
+ return this->mutex()->timed_lock_sharable(abs_time);
+}
+
+inline void named_upgradable_mutex::unlock_and_lock_upgradable()
+{ this->mutex()->unlock_and_lock_upgradable(); }
+
+inline void named_upgradable_mutex::unlock_and_lock_sharable()
+{ this->mutex()->unlock_and_lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable()
+{ this->mutex()->unlock_upgradable_and_lock_sharable(); }
+
+inline void named_upgradable_mutex::unlock_upgradable_and_lock()
+{ this->mutex()->unlock_upgradable_and_lock(); }
+
+inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
+{ return this->mutex()->try_unlock_upgradable_and_lock(); }
+
+inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
+ (const boost::posix_time::ptime &abs_time)
+{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
+
+inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
+{ return this->mutex()->try_unlock_sharable_and_lock(); }
+
+inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
+{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); }
+
+inline bool named_upgradable_mutex::remove(const char *name)
+{ return shared_memory_object::remove(name); }
+
+/// @endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP
diff --git a/boost/interprocess/sync/spin/condition.hpp b/boost/interprocess/sync/spin/condition.hpp
new file mode 100644
index 0000000000..5a37d9be2d
--- /dev/null
+++ b/boost/interprocess/sync/spin/condition.hpp
@@ -0,0 +1,295 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
+#define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/move/move.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class spin_condition
+{
+ spin_condition(const spin_condition &);
+ spin_condition &operator=(const spin_condition &);
+ public:
+ spin_condition();
+ ~spin_condition();
+
+ void notify_one();
+ void notify_all();
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ return this->do_timed_wait(abs_time, *lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ while (!pred()){
+ if (!this->do_timed_wait(abs_time, *lock.mutex()))
+ return pred();
+ }
+ return true;
+ }
+
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ do_wait(*lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ do_wait(*lock.mutex());
+ }
+
+ template<class InterprocessMutex>
+ void do_wait(InterprocessMutex &mut);
+
+ template<class InterprocessMutex>
+ bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+
+ private:
+ template<class InterprocessMutex>
+ bool do_timed_wait(bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+
+ enum { SLEEP = 0, NOTIFY_ONE, NOTIFY_ALL };
+ spin_mutex m_enter_mut;
+ volatile boost::uint32_t m_command;
+ volatile boost::uint32_t m_num_waiters;
+ void notify(boost::uint32_t command);
+};
+
+inline spin_condition::spin_condition()
+{
+ //Note that this class is initialized to zero.
+ //So zeroed memory can be interpreted as an initialized
+ //condition variable
+ m_command = SLEEP;
+ m_num_waiters = 0;
+}
+
+inline spin_condition::~spin_condition()
+{
+ //Trivial destructor
+}
+
+inline void spin_condition::notify_one()
+{
+ this->notify(NOTIFY_ONE);
+}
+
+inline void spin_condition::notify_all()
+{
+ this->notify(NOTIFY_ALL);
+}
+
+inline void spin_condition::notify(boost::uint32_t command)
+{
+ //This mutex guarantees that no other thread can enter to the
+ //do_timed_wait method logic, so that thread count will be
+ //constant until the function writes a NOTIFY_ALL command.
+ //It also guarantees that no other notification can be signaled
+ //on this spin_condition before this one ends
+ m_enter_mut.lock();
+
+ //Return if there are no waiters
+ if(!atomic_read32(&m_num_waiters)) {
+ m_enter_mut.unlock();
+ return;
+ }
+
+ //Notify that all threads should execute wait logic
+ while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
+ thread_yield();
+ }
+/*
+ //Wait until the threads are woken
+ while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){
+ thread_yield();
+ }
+*/
+ //The enter mutex will rest locked until the last waiting thread unlocks it
+}
+
+template<class InterprocessMutex>
+inline void spin_condition::do_wait(InterprocessMutex &mut)
+{
+ this->do_timed_wait(false, boost::posix_time::ptime(), mut);
+}
+
+template<class InterprocessMutex>
+inline bool spin_condition::do_timed_wait
+ (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
+{
+ return this->do_timed_wait(true, abs_time, mut);
+}
+
+template<class InterprocessMutex>
+inline bool spin_condition::do_timed_wait(bool tout_enabled,
+ const boost::posix_time::ptime &abs_time,
+ InterprocessMutex &mut)
+{
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ if(tout_enabled){
+ if(now >= abs_time) return false;
+ }
+
+ typedef boost::interprocess::scoped_lock<spin_mutex> InternalLock;
+ //The enter mutex guarantees that while executing a notification,
+ //no other thread can execute the do_timed_wait method.
+ {
+ //---------------------------------------------------------------
+ InternalLock lock;
+ if(tout_enabled){
+ InternalLock dummy(m_enter_mut, abs_time);
+ lock = boost::move(dummy);
+ }
+ else{
+ InternalLock dummy(m_enter_mut);
+ lock = boost::move(dummy);
+ }
+
+ if(!lock)
+ return false;
+ //---------------------------------------------------------------
+ //We increment the waiting thread count protected so that it will be
+ //always constant when another thread enters the notification logic.
+ //The increment marks this thread as "waiting on spin_condition"
+ atomic_inc32(const_cast<boost::uint32_t*>(&m_num_waiters));
+
+ //We unlock the external mutex atomically with the increment
+ mut.unlock();
+ }
+
+ //By default, we suppose that no timeout has happened
+ bool timed_out = false, unlock_enter_mut= false;
+
+ //Loop until a notification indicates that the thread should
+ //exit or timeout occurs
+ while(1){
+ //The thread sleeps/spins until a spin_condition commands a notification
+ //Notification occurred, we will lock the checking mutex so that
+ while(atomic_read32(&m_command) == SLEEP){
+ thread_yield();
+
+ //Check for timeout
+ if(tout_enabled){
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ //If we can lock the mutex it means that no notification
+ //is being executed in this spin_condition variable
+ timed_out = m_enter_mut.try_lock();
+
+ //If locking fails, indicates that another thread is executing
+ //notification, so we play the notification game
+ if(!timed_out){
+ //There is an ongoing notification, we will try again later
+ continue;
+ }
+ //No notification in execution, since enter mutex is locked.
+ //We will execute time-out logic, so we will decrement count,
+ //release the enter mutex and return false.
+ break;
+ }
+ }
+ }
+
+ //If a timeout occurred, the mutex will not execute checking logic
+ if(tout_enabled && timed_out){
+ //Decrement wait count
+ atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ unlock_enter_mut = true;
+ break;
+ }
+ else{
+ boost::uint32_t result = atomic_cas32
+ (const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ONE);
+ if(result == SLEEP){
+ //Other thread has been notified and since it was a NOTIFY one
+ //command, this thread must sleep again
+ continue;
+ }
+ else if(result == NOTIFY_ONE){
+ //If it was a NOTIFY_ONE command, only this thread should
+ //exit. This thread has atomically marked command as sleep before
+ //so no other thread will exit.
+ //Decrement wait count.
+ unlock_enter_mut = true;
+ atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ break;
+ }
+ else{
+ //If it is a NOTIFY_ALL command, all threads should return
+ //from do_timed_wait function. Decrement wait count.
+ unlock_enter_mut = 1 == atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ //Check if this is the last thread of notify_all waiters
+ //Only the last thread will release the mutex
+ if(unlock_enter_mut){
+ atomic_cas32(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ALL);
+ }
+ break;
+ }
+ }
+ }
+
+ //Unlock the enter mutex if it is a single notification, if this is
+ //the last notified thread in a notify_all or a timeout has occurred
+ if(unlock_enter_mut){
+ m_enter_mut.unlock();
+ }
+
+ //Lock external again before returning from the method
+ mut.lock();
+ return !timed_out;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP
diff --git a/boost/interprocess/sync/spin/interprocess_barrier.hpp b/boost/interprocess/sync/spin/interprocess_barrier.hpp
new file mode 100644
index 0000000000..f8ee09948d
--- /dev/null
+++ b/boost/interprocess/sync/spin/interprocess_barrier.hpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include<boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+
+namespace boost {
+namespace interprocess {
+
+inline barrier::barrier(unsigned int count)
+ : m_threshold(count), m_count(count), m_generation(0)
+{
+ if (count == 0)
+ throw std::invalid_argument("count cannot be zero.");
+}
+
+inline barrier::~barrier(){}
+
+inline bool barrier::wait()
+{
+ scoped_lock<interprocess_mutex> lock(m_mutex);
+ unsigned int gen = m_generation;
+
+ if (--m_count == 0){
+ m_generation++;
+ m_count = m_threshold;
+ m_cond.notify_all();
+ return true;
+ }
+
+ while (gen == m_generation){
+ m_cond.wait(lock);
+ }
+ return false;
+}
+
+} //namespace interprocess {
+} //namespace boost {
diff --git a/boost/interprocess/sync/spin/mutex.hpp b/boost/interprocess/sync/spin/mutex.hpp
new file mode 100644
index 0000000000..ef0b47d95a
--- /dev/null
+++ b/boost/interprocess/sync/spin/mutex.hpp
@@ -0,0 +1,114 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/assert.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class spin_mutex
+{
+ spin_mutex(const spin_mutex &);
+ spin_mutex &operator=(const spin_mutex &);
+ public:
+
+ spin_mutex();
+ ~spin_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+ void take_ownership(){};
+ private:
+ volatile boost::uint32_t m_s;
+};
+
+inline spin_mutex::spin_mutex()
+ : m_s(0)
+{
+ //Note that this class is initialized to zero.
+ //So zeroed memory can be interpreted as an
+ //initialized mutex
+}
+
+inline spin_mutex::~spin_mutex()
+{
+ //Trivial destructor
+}
+
+inline void spin_mutex::lock(void)
+{
+ do{
+ boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
+
+ if (m_s == 1 && prev_s == 0){
+ break;
+ }
+ // relinquish current timeslice
+ ipcdetail::thread_yield();
+ }while (true);
+}
+
+inline bool spin_mutex::try_lock(void)
+{
+ boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
+ return m_s == 1 && prev_s == 0;
+}
+
+inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ do{
+ if(this->try_lock()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return false;
+ }
+ // relinquish current time slice
+ ipcdetail::thread_yield();
+ }while (true);
+
+ return true;
+}
+
+inline void spin_mutex::unlock(void)
+{ ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); }
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
diff --git a/boost/interprocess/sync/spin/recursive_mutex.hpp b/boost/interprocess/sync/spin/recursive_mutex.hpp
new file mode 100644
index 0000000000..05ad65eac0
--- /dev/null
+++ b/boost/interprocess/sync/spin/recursive_mutex.hpp
@@ -0,0 +1,175 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Parts of the pthread code come from Boost Threads code:
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. William E. Kempf makes no representations
+// about the suitability of this software for any purpose.
+// It is provided "as is" without express or implied warranty.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class spin_recursive_mutex
+{
+ spin_recursive_mutex(const spin_recursive_mutex &);
+ spin_recursive_mutex &operator=(const spin_recursive_mutex &);
+ public:
+
+ spin_recursive_mutex();
+ ~spin_recursive_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+ void take_ownership();
+ private:
+ spin_mutex m_mutex;
+ unsigned int m_nLockCount;
+ volatile ipcdetail::OS_systemwide_thread_id_t m_nOwner;
+ volatile boost::uint32_t m_s;
+};
+
+inline spin_recursive_mutex::spin_recursive_mutex()
+ : m_nLockCount(0), m_nOwner(ipcdetail::get_invalid_systemwide_thread_id()){}
+
+inline spin_recursive_mutex::~spin_recursive_mutex(){}
+
+inline void spin_recursive_mutex::lock()
+{
+ typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
+ const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
+ handle_t old_id;
+ ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
+ if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)){
+ if((unsigned int)(m_nLockCount+1) == 0){
+ //Overflow, throw an exception
+ throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
+ }
+ ++m_nLockCount;
+ }
+ else{
+ m_mutex.lock();
+ ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
+ m_nLockCount = 1;
+ }
+}
+
+inline bool spin_recursive_mutex::try_lock()
+{
+ typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
+ handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
+ handle_t old_id;
+ ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
+ if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
+ if((unsigned int)(m_nLockCount+1) == 0){
+ //Overflow, throw an exception
+ throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
+ }
+ ++m_nLockCount;
+ return true;
+ }
+ if(m_mutex.try_lock()){
+ ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
+ m_nLockCount = 1;
+ return true;
+ }
+ return false;
+}
+
+inline bool spin_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
+ handle_t old_id;
+ ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
+ if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
+ if((unsigned int)(m_nLockCount+1) == 0){
+ //Overflow, throw an exception
+ throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
+ }
+ ++m_nLockCount;
+ return true;
+ }
+ if(m_mutex.timed_lock(abs_time)){
+ ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
+ m_nLockCount = 1;
+ return true;
+ }
+ return false;
+}
+
+inline void spin_recursive_mutex::unlock()
+{
+ typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
+ handle_t old_id;
+ ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
+ const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
+ (void)old_id;
+ (void)thr_id;
+ BOOST_ASSERT(ipcdetail::equal_systemwide_thread_id(thr_id, old_id));
+ --m_nLockCount;
+ if(!m_nLockCount){
+ const handle_t new_id(ipcdetail::get_invalid_systemwide_thread_id());
+ ipcdetail::systemwide_thread_id_copy(new_id, m_nOwner);
+ m_mutex.unlock();
+ }
+}
+
+inline void spin_recursive_mutex::take_ownership()
+{
+ typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
+ this->m_nLockCount = 1;
+ const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
+ ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/spin/semaphore.hpp b/boost/interprocess/sync/spin/semaphore.hpp
new file mode 100644
index 0000000000..1b8cac35aa
--- /dev/null
+++ b/boost/interprocess/sync/spin/semaphore.hpp
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class spin_semaphore
+{
+ spin_semaphore(const spin_semaphore &);
+ spin_semaphore &operator=(const spin_semaphore &);
+
+ public:
+ spin_semaphore(unsigned int initialCount);
+ ~spin_semaphore();
+
+ void post();
+ void wait();
+ bool try_wait();
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+// int get_count() const;
+ private:
+ volatile boost::uint32_t m_count;
+};
+
+
+inline spin_semaphore::~spin_semaphore()
+{}
+
+inline spin_semaphore::spin_semaphore(unsigned int initialCount)
+{ ipcdetail::atomic_write32(&this->m_count, boost::uint32_t(initialCount)); }
+
+inline void spin_semaphore::post()
+{
+ ipcdetail::atomic_inc32(&m_count);
+}
+
+inline void spin_semaphore::wait()
+{
+ while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){
+ while(ipcdetail::atomic_read32(&m_count) == 0){
+ ipcdetail::thread_yield();
+ }
+ }
+}
+
+inline bool spin_semaphore::try_wait()
+{
+ return ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0));
+}
+
+inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ //Obtain current count and target time
+ boost::posix_time::ptime now(microsec_clock::universal_time());
+
+ do{
+ if(this->try_wait()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return this->try_wait();
+ }
+ // relinquish current time slice
+ ipcdetail::thread_yield();
+ }while (true);
+ return true;
+}
+
+
+//inline int spin_semaphore::get_count() const
+//{
+ //return (int)ipcdetail::atomic_read32(&m_count);
+//}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/upgradable_lock.hpp b/boost/interprocess/sync/upgradable_lock.hpp
new file mode 100644
index 0000000000..93c2ed6bc4
--- /dev/null
+++ b/boost/interprocess/sync/upgradable_lock.hpp
@@ -0,0 +1,309 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This interface is inspired by Howard Hinnant's lock proposal.
+// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
+#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
+
+#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/interprocess_fwd.hpp>
+#include <boost/interprocess/sync/lock_options.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+//!\file
+//!Describes the upgradable_lock class that serves to acquire the upgradable
+//!lock of a mutex.
+
+namespace boost {
+namespace interprocess {
+
+//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking,
+//!try-read-locking and timed-read-locking (recursive or not) for the Mutex.
+//!Additionally the upgradable_lock can transfer ownership to a scoped_lock
+//!using transfer_lock syntax. The Mutex need not supply all of the functionality.
+//!If the client of upgradable_lock<Mutex> does not use functionality which the
+//!Mutex does not supply, no harm is done. Mutex ownership can be shared among
+//!read_locks, and a single upgradable_lock. upgradable_lock does not support
+//!copy semantics. However upgradable_lock supports ownership transfer from
+//!a upgradable_locks or scoped_locks via transfer_lock syntax.
+template <class UpgradableMutex>
+class upgradable_lock
+{
+ public:
+ typedef UpgradableMutex mutex_type;
+ /// @cond
+ private:
+ typedef upgradable_lock<UpgradableMutex> this_type;
+ explicit upgradable_lock(scoped_lock<mutex_type>&);
+ typedef bool this_type::*unspecified_bool_type;
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock)
+ /// @endcond
+ public:
+
+ //!Effects: Default constructs a upgradable_lock.
+ //!Postconditions: owns() == false and mutex() == 0.
+ upgradable_lock()
+ : mp_mutex(0), m_locked(false)
+ {}
+
+ explicit upgradable_lock(mutex_type& m)
+ : mp_mutex(&m), m_locked(false)
+ { mp_mutex->lock_upgradable(); m_locked = true; }
+
+ //!Postconditions: owns() == false, and mutex() == &m.
+ //!Notes: The constructor will not take ownership of the mutex. There is no effect
+ //! required on the referenced mutex.
+ upgradable_lock(mutex_type& m, defer_lock_type)
+ : mp_mutex(&m), m_locked(false)
+ {}
+
+ //!Postconditions: owns() == true, and mutex() == &m.
+ //!Notes: The constructor will suppose that the mutex is already upgradable
+ //! locked. There is no effect required on the referenced mutex.
+ upgradable_lock(mutex_type& m, accept_ownership_type)
+ : mp_mutex(&m), m_locked(true)
+ {}
+
+ //!Effects: m.try_lock_upgradable().
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.try_lock_upgradable() executed within the constructor.
+ //!Notes: The constructor will take upgradable-ownership of the mutex
+ //! if it can do so without waiting. Whether or not this constructor
+ //! handles recursive locking depends upon the mutex. If the mutex_type
+ //! does not support try_lock_upgradable, this constructor will fail at
+ //! compile time if instantiated, but otherwise have no effect.
+ upgradable_lock(mutex_type& m, try_to_lock_type)
+ : mp_mutex(&m), m_locked(false)
+ { m_locked = mp_mutex->try_lock_upgradable(); }
+
+ //!Effects: m.timed_lock_upgradable(abs_time)
+ //!Postconditions: mutex() == &m. owns() == the return value of the
+ //! m.timed_lock_upgradable() executed within the constructor.
+ //!Notes: The constructor will take upgradable-ownership of the mutex if it
+ //! can do so within the time specified. Whether or not this constructor
+ //! handles recursive locking depends upon the mutex. If the mutex_type
+ //! does not support timed_lock_upgradable, this constructor will fail
+ //! at compile time if instantiated, but otherwise have no effect.
+ upgradable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
+ : mp_mutex(&m), m_locked(false)
+ { m_locked = mp_mutex->timed_lock_upgradable(abs_time); }
+
+ //!Effects: No effects on the underlying mutex.
+ //!Postconditions: mutex() == the value upgr.mutex() had before the
+ //! construction. upgr.mutex() == 0. owns() == upgr.owns() before the
+ //! construction. upgr.owns() == false.
+ //!Notes: If upgr is locked, this constructor will lock this upgradable_lock
+ //! while unlocking upgr. If upgr is unlocked, then this upgradable_lock will
+ //! be unlocked as well. Only a moved upgradable_lock's will match this
+ //! signature. An non-moved upgradable_lock can be moved with the
+ //! expression: "boost::move(lock);". This constructor does not alter the
+ //! state of the mutex, only potentially who owns it.
+ upgradable_lock(BOOST_RV_REF(upgradable_lock<mutex_type>) upgr)
+ : mp_mutex(0), m_locked(upgr.owns())
+ { mp_mutex = upgr.release(); }
+
+ //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable().
+ //!Postconditions: mutex() == the value scop.mutex() had before the construction.
+ //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the
+ //! construction, scop.owns() == false.
+ //!Notes: If scop is locked, this constructor will transfer the exclusive-ownership
+ //! to an upgradable-ownership of this upgradable_lock.
+ //! Only a moved sharable_lock's will match this
+ //! signature. An non-moved sharable_lock can be moved with the
+ //! expression: "boost::move(lock);".
+ template<class T>
+ upgradable_lock(BOOST_RV_REF(scoped_lock<T>) scop
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, UpgradableMutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ scoped_lock<mutex_type> &u_lock = scop;
+ if(u_lock.owns()){
+ u_lock.mutex()->unlock_and_lock_upgradable();
+ m_locked = true;
+ }
+ mp_mutex = u_lock.release();
+ }
+
+ //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable()
+ //! on the referenced mutex.
+ //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex()
+ //! obtains the value from shar.release() and owns() is set to true.
+ //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is
+ //! unaffected and this upgradable_lock construction has the same
+ //! effects as a default construction.
+ //! c)Else shar.owns() is false. mutex() obtains the value from shar.release()
+ //! and owns() is set to false.
+ //!Notes: This construction will not block. It will try to obtain mutex
+ //! ownership from shar immediately, while changing the lock type from a
+ //! "read lock" to an "upgradable lock". If the "read lock" isn't held
+ //! in the first place, the mutex merely changes type to an unlocked
+ //! "upgradable lock". If the "read lock" is held, then mutex transfer
+ //! occurs only if it can do so in a non-blocking manner.
+ template<class T>
+ upgradable_lock( BOOST_RV_REF(sharable_lock<T>) shar, try_to_lock_type
+ , typename ipcdetail::enable_if< ipcdetail::is_same<T, UpgradableMutex> >::type * = 0)
+ : mp_mutex(0), m_locked(false)
+ {
+ sharable_lock<mutex_type> &s_lock = shar;
+ if(s_lock.owns()){
+ if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){
+ mp_mutex = s_lock.release();
+ }
+ }
+ else{
+ s_lock.release();
+ }
+ }
+
+ //!Effects: if (owns()) m_->unlock_upgradable().
+ //!Notes: The destructor behavior ensures that the mutex lock is not leaked.
+ ~upgradable_lock()
+ {
+ try{
+ if(m_locked && mp_mutex) mp_mutex->unlock_upgradable();
+ }
+ catch(...){}
+ }
+
+ //!Effects: If owns(), then unlock_upgradable() is called on mutex().
+ //! *this gets the state of upgr and upgr gets set to a default constructed state.
+ //!Notes: With a recursive mutex it is possible that both this and upgr own the
+ //! mutex before the assignment. In this case, this will own the mutex
+ //! after the assignment (and upgr will not), but the mutex's upgradable lock
+ //! count will be decremented by one.
+ upgradable_lock &operator=(BOOST_RV_REF(upgradable_lock) upgr)
+ {
+ if(this->owns())
+ this->unlock();
+ m_locked = upgr.owns();
+ mp_mutex = upgr.release();
+ return *this;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls lock_upgradable() on the referenced mutex.
+ //!Postconditions: owns() == true.
+ //!Notes: The sharable_lock changes from a state of not owning the mutex,
+ //! to owning the mutex, blocking if necessary.
+ void lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ mp_mutex->lock_upgradable();
+ m_locked = true;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls try_lock_upgradable() on the referenced mutex.
+ //!Postconditions: owns() == the value returned from
+ //! mutex()->try_lock_upgradable().
+ //!Notes: The upgradable_lock changes from a state of not owning the mutex,
+ //! to owning the mutex, but only if blocking was not required. If the
+ //! mutex_type does not support try_lock_upgradable(), this function will
+ //! fail at compile time if instantiated, but otherwise have no effect.
+ bool try_lock()
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->try_lock_upgradable();
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex.
+ //!Postconditions: owns() == the value returned from
+ //! mutex()->timed_lock_upgradable(abs_time).
+ //!Notes: The upgradable_lock changes from a state of not owning the mutex,
+ //! to owning the mutex, but only if it can obtain ownership within the
+ //! specified time. If the mutex_type does not support
+ //! timed_lock_upgradable(abs_time), this function will fail at compile
+ //! time if instantiated, but otherwise have no effect.
+ bool timed_lock(const boost::posix_time::ptime& abs_time)
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->timed_lock_upgradable(abs_time);
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
+ //! exception. Calls unlock_upgradable() on the referenced mutex.
+ //!Postconditions: owns() == false.
+ //!Notes: The upgradable_lock changes from a state of owning the mutex,
+ //! to not owning the mutex.
+ void unlock()
+ {
+ if(!mp_mutex || !m_locked)
+ throw lock_exception();
+ mp_mutex->unlock_upgradable();
+ m_locked = false;
+ }
+
+ //!Effects: Returns true if this scoped_lock has acquired the
+ //!referenced mutex.
+ bool owns() const
+ { return m_locked && mp_mutex; }
+
+ //!Conversion to bool.
+ //!Returns owns().
+ operator unspecified_bool_type() const
+ { return m_locked? &this_type::m_locked : 0; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if
+ //!there is no mutex to reference.
+ mutex_type* mutex() const
+ { return mp_mutex; }
+
+ //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
+ //! mutex to reference.
+ //!Postconditions: mutex() == 0 and owns() == false.
+ mutex_type* release()
+ {
+ mutex_type *mut = mp_mutex;
+ mp_mutex = 0;
+ m_locked = false;
+ return mut;
+ }
+
+ //!Effects: Swaps state with moved lock.
+ //!Throws: Nothing.
+ void swap(upgradable_lock<mutex_type> &other)
+ {
+ std::swap(mp_mutex, other.mp_mutex);
+ std::swap(m_locked, other.m_locked);
+ }
+
+ /// @cond
+ private:
+ mutex_type *mp_mutex;
+ bool m_locked;
+ /// @endcond
+};
+
+} // namespace interprocess
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
diff --git a/boost/interprocess/sync/windows/condition.hpp b/boost/interprocess/sync/windows/condition.hpp
new file mode 100644
index 0000000000..167b8730c3
--- /dev/null
+++ b/boost/interprocess/sync/windows/condition.hpp
@@ -0,0 +1,383 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/windows/semaphore.hpp>
+#include <boost/interprocess/sync/windows/mutex.hpp>
+#include <boost/cstdint.hpp>
+#include <limits>
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//
+// Condition variable algorithm taken from pthreads-win32 discussion.
+//
+// The algorithm was developed by Alexander Terekhov in colaboration with
+// Louis Thomas.
+//
+// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+//
+// semBlockLock - bin.semaphore
+// semBlockQueue - semaphore
+// mtxExternal - mutex or CS
+// mtxUnblockLock - mutex or CS
+// nWaitersGone - int
+// nWaitersBlocked - int
+// nWaitersToUnblock - int
+//
+// wait( timeout ) {
+//
+// [auto: register int result ] // error checking omitted
+// [auto: register int nSignalsWasLeft ]
+// [auto: register int nWaitersWasGone ]
+//
+// sem_wait( semBlockLock );
+// nWaitersBlocked++;
+// sem_post( semBlockLock );
+//
+// unlock( mtxExternal );
+// bTimedOut = sem_wait( semBlockQueue,timeout );
+//
+// lock( mtxUnblockLock );
+// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+// if ( bTimedOut ) { // timeout (or canceled)
+// if ( 0 != nWaitersBlocked ) {
+// nWaitersBlocked--;
+// }
+// else {
+// nWaitersGone++; // count spurious wakeups.
+// }
+// }
+// if ( 0 == --nWaitersToUnblock ) {
+// if ( 0 != nWaitersBlocked ) {
+// sem_post( semBlockLock ); // open the gate.
+// nSignalsWasLeft = 0; // do not open the gate
+// // below again.
+// }
+// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+// nWaitersGone = 0;
+// }
+// }
+// }
+// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+// // spurious semaphore :-)
+// sem_wait( semBlockLock );
+// nWaitersBlocked -= nWaitersGone; // something is going on here
+// // - test of timeouts? :-)
+// sem_post( semBlockLock );
+// nWaitersGone = 0;
+// }
+// unlock( mtxUnblockLock );
+//
+// if ( 1 == nSignalsWasLeft ) {
+// if ( 0 != nWaitersWasGone ) {
+// // sem_adjust( semBlockQueue,-nWaitersWasGone );
+// while ( nWaitersWasGone-- ) {
+// sem_wait( semBlockQueue ); // better now than spurious later
+// }
+// } sem_post( semBlockLock ); // open the gate
+// }
+//
+// lock( mtxExternal );
+//
+// return ( bTimedOut ) ? ETIMEOUT : 0;
+// }
+//
+// signal(bAll) {
+//
+// [auto: register int result ]
+// [auto: register int nSignalsToIssue]
+//
+// lock( mtxUnblockLock );
+//
+// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+// if ( 0 == nWaitersBlocked ) { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+// if (bAll) {
+// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = 1;
+// nWaitersToUnblock++;
+// nWaitersBlocked--;
+// }
+// }
+// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+// sem_wait( semBlockLock ); // close the gate
+// if ( 0 != nWaitersGone ) {
+// nWaitersBlocked -= nWaitersGone;
+// nWaitersGone = 0;
+// }
+// if (bAll) {
+// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = nWaitersToUnblock = 1;
+// nWaitersBlocked--;
+// }
+// }
+// else { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+//
+// unlock( mtxUnblockLock );
+// sem_post( semBlockQueue,nSignalsToIssue );
+// return result;
+// }
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_condition
+{
+ windows_condition(const windows_condition &);
+ windows_condition &operator=(const windows_condition &);
+ public:
+ windows_condition();
+ ~windows_condition();
+
+ void notify_one();
+ void notify_all();
+
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ return this->do_timed_wait(abs_time, *lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ while (!pred()){
+ if (!this->do_timed_wait(abs_time, *lock.mutex()))
+ return pred();
+ }
+ return true;
+ }
+
+ template <typename L>
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ do_wait(*lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ do_wait(*lock.mutex());
+ }
+
+ template<class InterprocessMutex>
+ void do_wait(InterprocessMutex &mut);
+
+ template<class InterprocessMutex>
+ bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+
+ private:
+
+ template<class InterprocessMutex>
+ bool do_timed_wait(bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ void do_signal (bool broadcast);
+
+ boost::int32_t m_nwaiters_blocked;
+ boost::int32_t m_nwaiters_gone;
+ boost::int32_t m_nwaiters_to_unblock;
+ windows_semaphore m_sem_block_queue;
+ windows_semaphore m_sem_block_lock;
+ windows_mutex m_mtx_unblock_lock;
+};
+
+inline windows_condition::windows_condition()
+ : m_nwaiters_blocked(0)
+ , m_nwaiters_gone(0)
+ , m_nwaiters_to_unblock(0)
+ , m_sem_block_queue(0)
+ , m_sem_block_lock(1)
+ , m_mtx_unblock_lock()
+{}
+
+inline windows_condition::~windows_condition()
+{}
+
+inline void windows_condition::notify_one()
+{ this->do_signal(false); }
+
+inline void windows_condition::notify_all()
+{ this->do_signal(true); }
+
+inline void windows_condition::do_signal(bool broadcast)
+{
+ boost::int32_t nsignals_to_issue;
+
+ {
+ scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
+
+ if ( 0 != m_nwaiters_to_unblock ) { // the gate is closed!!!
+ if ( 0 == m_nwaiters_blocked ) { // NO-OP
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ return;
+ }
+ if (broadcast) {
+ m_nwaiters_to_unblock += nsignals_to_issue = m_nwaiters_blocked;
+ m_nwaiters_blocked = 0;
+ }
+ else {
+ nsignals_to_issue = 1;
+ m_nwaiters_to_unblock++;
+ m_nwaiters_blocked--;
+ }
+ }
+ else if ( m_nwaiters_blocked > m_nwaiters_gone ) { // HARMLESS RACE CONDITION!
+ m_sem_block_lock.wait(); // close the gate
+ if ( 0 != m_nwaiters_gone ) {
+ m_nwaiters_blocked -= m_nwaiters_gone;
+ m_nwaiters_gone = 0;
+ }
+ if (broadcast) {
+ nsignals_to_issue = m_nwaiters_to_unblock = m_nwaiters_blocked;
+ m_nwaiters_blocked = 0;
+ }
+ else {
+ nsignals_to_issue = m_nwaiters_to_unblock = 1;
+ m_nwaiters_blocked--;
+ }
+ }
+ else { // NO-OP
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ return;
+ }
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ }
+ m_sem_block_queue.post(nsignals_to_issue);
+}
+
+template<class InterprocessMutex>
+inline void windows_condition::do_wait(InterprocessMutex &mut)
+{ this->do_timed_wait(false, boost::posix_time::ptime(), mut); }
+
+template<class InterprocessMutex>
+inline bool windows_condition::do_timed_wait
+ (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
+{ return this->do_timed_wait(true, abs_time, mut); }
+
+template<class InterprocessMutex>
+inline bool windows_condition::do_timed_wait
+ (bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal)
+{
+ //Initialize to avoid warnings
+ boost::int32_t nsignals_was_left = 0;
+ boost::int32_t nwaiters_was_gone = 0;
+
+ m_sem_block_lock.wait();
+ ++m_nwaiters_blocked;
+ m_sem_block_lock.post();
+
+ struct scoped_unlock
+ {
+ InterprocessMutex & mut;
+ scoped_unlock(InterprocessMutex & m)
+ : mut(m)
+ { m.unlock(); }
+
+ ~scoped_unlock()
+ { mut.lock(); }
+ } unlocker(mtxExternal);
+
+
+ bool bTimedOut = tout_enabled ? !m_sem_block_queue.timed_wait(abs_time) : (m_sem_block_queue.wait(), false);
+
+ {
+ scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
+ if ( 0 != (nsignals_was_left = m_nwaiters_to_unblock) ) {
+ if ( bTimedOut ) { // timeout (or canceled)
+ if ( 0 != m_nwaiters_blocked ) {
+ m_nwaiters_blocked--;
+ }
+ else {
+ m_nwaiters_gone++; // count spurious wakeups.
+ }
+ }
+ if ( 0 == --m_nwaiters_to_unblock ) {
+ if ( 0 != m_nwaiters_blocked ) {
+ m_sem_block_lock.post(); // open the gate.
+ nsignals_was_left = 0; // do not open the gate below again.
+ }
+ else if ( 0 != (nwaiters_was_gone = m_nwaiters_gone) ) {
+ m_nwaiters_gone = 0;
+ }
+ }
+ }
+ else if ( (std::numeric_limits<boost::int32_t>::max)()/2
+ == ++m_nwaiters_gone ) { // timeout/canceled or spurious semaphore :-)
+ m_sem_block_lock.wait();
+ m_nwaiters_blocked -= m_nwaiters_gone; // something is going on here - test of timeouts? :-)
+ m_sem_block_lock.post();
+ m_nwaiters_gone = 0;
+ }
+ //locker's destructor triggers m_mtx_unblock_lock.unlock()
+ }
+
+ if ( 1 == nsignals_was_left ) {
+ if ( 0 != nwaiters_was_gone ) {
+ // sem_adjust( m_sem_block_queue,-nwaiters_was_gone );
+ while ( nwaiters_was_gone-- ) {
+ m_sem_block_queue.wait(); // better now than spurious later
+ }
+ }
+ m_sem_block_lock.post(); // open the gate
+ }
+
+ //mtxExternal.lock(); called from unlocker
+
+ return ( bTimedOut ) ? false : true;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP
diff --git a/boost/interprocess/sync/windows/mutex.hpp b/boost/interprocess/sync/windows/mutex.hpp
new file mode 100644
index 0000000000..5eca522339
--- /dev/null
+++ b/boost/interprocess/sync/windows/mutex.hpp
@@ -0,0 +1,137 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_mutex
+{
+ windows_mutex(const windows_mutex &);
+ windows_mutex &operator=(const windows_mutex &);
+ public:
+
+ windows_mutex();
+ ~windows_mutex();
+
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+ void take_ownership(){};
+
+ private:
+ const sync_id id_;
+};
+
+inline windows_mutex::windows_mutex()
+ : id_()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //Create mutex with the initial count
+ bool open_or_created;
+ handles.obtain_mutex(this->id_, &open_or_created);
+ //The mutex must be created, never opened
+ assert(open_or_created);
+ assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ (void)open_or_created;
+}
+
+inline windows_mutex::~windows_mutex()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ handles.destroy_handle(this->id_);
+}
+
+inline void windows_mutex::lock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool windows_mutex::try_lock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, 0);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ boost::posix_time::ptime now
+ = boost::posix_time::microsec_clock::universal_time();
+
+ unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ unsigned long ret = winapi::wait_for_single_object(hnd, ms);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline void windows_mutex::unlock(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_mutex(this->id_);
+ int ret = winapi::release_mutex(hnd);
+ (void)ret;
+ assert(ret);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
diff --git a/boost/interprocess/sync/windows/recursive_mutex.hpp b/boost/interprocess/sync/windows/recursive_mutex.hpp
new file mode 100644
index 0000000000..9565cb6fb4
--- /dev/null
+++ b/boost/interprocess/sync/windows/recursive_mutex.hpp
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/windows/mutex.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+//Windows mutex is already recursive
+class windows_recursive_mutex
+ : public windows_mutex
+{
+ windows_recursive_mutex(const windows_recursive_mutex &);
+ windows_recursive_mutex &operator=(const windows_recursive_mutex &);
+ public:
+ windows_recursive_mutex() : windows_mutex() {}
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP
diff --git a/boost/interprocess/sync/windows/semaphore.hpp b/boost/interprocess/sync/windows/semaphore.hpp
new file mode 100644
index 0000000000..d5835ceec7
--- /dev/null
+++ b/boost/interprocess/sync/windows/semaphore.hpp
@@ -0,0 +1,137 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_semaphore
+{
+ windows_semaphore(const windows_semaphore &);
+ windows_semaphore &operator=(const windows_semaphore &);
+ public:
+
+ windows_semaphore(unsigned int initialCount);
+ ~windows_semaphore();
+
+ void post(long release_count = 1);
+ void wait();
+ bool try_wait();
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ private:
+ const sync_id id_;
+};
+
+inline windows_semaphore::windows_semaphore(unsigned int initialCount)
+ : id_()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //Force smeaphore creation with the initial count
+ bool open_or_created;
+ handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
+ //The semaphore must be created, never opened
+ assert(open_or_created);
+ assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ (void)open_or_created;
+}
+
+inline windows_semaphore::~windows_semaphore()
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ handles.destroy_handle(this->id_);
+}
+
+inline void windows_semaphore::wait(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+}
+
+inline bool windows_semaphore::try_wait(void)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, 0);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline bool windows_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ boost::posix_time::ptime now
+ = boost::posix_time::microsec_clock::universal_time();
+
+ unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ unsigned long ret = winapi::wait_for_single_object(hnd, ms);
+ if(ret == winapi::wait_failed){
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ return ret != winapi::wait_timeout;
+}
+
+inline void windows_semaphore::post(long release_count)
+{
+ sync_handles &handles =
+ intermodule_singleton<sync_handles>::get();
+ //This can throw
+ void *hnd = handles.obtain_semaphore(this->id_, 0);
+ long prev_count;
+ int ret = winapi::release_semaphore(hnd, release_count, &prev_count);
+ (void)ret;
+ assert(ret);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp
new file mode 100644
index 0000000000..89c4aeda0b
--- /dev/null
+++ b/boost/interprocess/sync/windows/sync_utils.hpp
@@ -0,0 +1,173 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
+#define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/unordered/unordered_map.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
+{
+ const std::size_t need_mem = mem_length*2+1;
+ if(out_length < need_mem){
+ return false;
+ }
+
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ std::size_t char_counter = 0;
+ const char *buf = (const char *)mem;
+ for(std::size_t i = 0; i != mem_length; ++i){
+ out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
+ out_str[char_counter++] = Characters[(buf[i]&0x0F)];
+ }
+ out_str[char_counter] = 0;
+ return true;
+}
+
+struct sync_id
+{
+ sync_id()
+ { winapi::query_performance_counter(&rand); }
+
+ __int64 rand;
+
+ friend std::size_t hash_value(const sync_id &m)
+ { return boost::hash_value(m.rand); }
+
+ friend bool operator==(const sync_id &l, const sync_id &r)
+ { return l.rand == r.rand; }
+};
+/*
+#define BOOST_NO_LONG_LONG ss
+
+#if defined(BOOST_NO_LONG_LONG)
+
+#error "defined(BOOST_NO_LONG_LONG)"
+#else
+#error "NOT defined(BOOST_NO_LONG_LONG)"
+#endif
+*/
+class sync_handles
+{
+ public:
+ enum type { MUTEX, SEMAPHORE };
+
+ private:
+ typedef boost::unordered_map<sync_id, void*> map_type;
+ static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
+ static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
+ typedef char NameBuf[StrSize];
+
+ void fill_name(NameBuf &name, const sync_id &id)
+ {
+ const char *n = "Global\\boost.ipc";
+ std::size_t i = 0;
+ do{
+ name[i] = n[i];
+ ++i;
+ } while(n[i]);
+ std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
+ bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len);
+ }
+
+ void erase_and_throw_if_error(void *hnd_val, const sync_id &id)
+ {
+ if(!hnd_val){
+ map_.erase(id);
+ error_info err(winapi::get_last_error());
+ throw interprocess_exception(err);
+ }
+ }
+
+ void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
+ {
+ NameBuf name;
+ fill_name(name, id);
+ void *hnd_val = winapi::open_or_create_semaphore
+ (name, (long)initial_count, (long)(((unsigned long)(-1))>>1), unrestricted_security.get_attributes());
+ erase_and_throw_if_error(hnd_val, id);
+ return hnd_val;
+ }
+
+ void* open_or_create_mutex(const sync_id &id)
+ {
+ NameBuf name;
+ fill_name(name, id);
+ void *hnd_val = winapi::open_or_create_mutex
+ (name, false, unrestricted_security.get_attributes());
+ erase_and_throw_if_error(hnd_val, id);
+ return hnd_val;
+ }
+
+ public:
+ void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ void *&hnd_val = map_[id];
+ if(!hnd_val){
+ hnd_val = open_or_create_mutex(id);
+ if(popen_created) *popen_created = true;
+ }
+ return hnd_val;
+ }
+
+ void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ void *&hnd_val = map_[id];
+ if(!hnd_val){
+ hnd_val = open_or_create_semaphore(id, initial_count);
+ if(popen_created) *popen_created = true;
+ }
+ return hnd_val;
+ }
+
+ void destroy_handle(const sync_id &id)
+ {
+ scoped_lock<spin_mutex> lock(mtx_);
+ map_type::iterator it = map_.find(id);
+ if(it != map_.end()){
+ winapi::close_handle(it->second);
+ map_.erase(it);
+ }
+ }
+
+ private:
+ winapi::interprocess_all_access_security unrestricted_security;
+ spin_mutex mtx_;
+ map_type map_;
+};
+
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
diff --git a/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp
new file mode 100644
index 0000000000..a0c3a91adf
--- /dev/null
+++ b/boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp
@@ -0,0 +1,193 @@
+/*
+ * Provide an simpler and easier to understand interface to the System V
+ * semaphore system calls. There are 7 routines available to the user:
+ *
+ * id = sem_create(key, initval); # create with initial value or open
+ * id = sem_open(key); # open (must already exist)
+ * sem_wait(id); # wait = P = down by 1
+ * sem_signal(id); # signal = V = up by 1
+ * sem_op(id, amount); # wait if (amount < 0)
+ * # signal if (amount > 0)
+ * sem_close(id); # close
+ * sem_rm(id); # remove (delete)
+ *
+ * We create and use a 3-member set for the requested semaphore.
+ * The first member, [0], is the actual semaphore value, and the second
+ * member, [1], is a counter used to know when all processes have finished
+ * with the semaphore. The counter is initialized to a large number,
+ * decremented on every create or open and incremented on every close.
+ * This way we can use the "adjust" feature provided by System V so that
+ * any process that exit's without calling sem_close() is accounted
+ * for. It doesn't help us if the last process does this (as we have
+ * no way of getting control to remove the semaphore) but it will
+ * work if any process other than the last does an exit (intentional
+ * or unintentional).
+ * The third member, [2], of the semaphore set is used as a lock variable
+ * to avoid any race conditions in the sem_create() and sem_close()
+ * functions.
+ */
+
+#ifndef BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <errno.h>
+
+namespace boost {
+namespace interprocess {
+namespace xsi {
+
+// Create a semaphore with a specified initial value.
+// If the semaphore already exists, we don't initialize it (of course).
+// We return the semaphore ID if all OK, else -1.
+
+inline bool advanced_sem_open_or_create(::key_t key, int initval, int &semid, int perm)
+{
+ semid = -1;
+ int id, semval;
+ union semun {
+ int val;
+ ::semid_ds *buf;
+ ushort *array;
+ } semctl_arg;
+
+ if (key == IPC_PRIVATE)
+ return false; //not intended for private semaphores
+
+ else if (key == (::key_t) -1)
+ return false; //probably an ftok() error by caller
+
+ again:
+ if ((id = ::semget(key, 3, (perm & 0x01FF) | IPC_CREAT)) < 0)
+ return false; //permission problem or tables full
+
+ // When the semaphore is created, we know that the value of all
+ // 3 members is 0.
+ // Get a lock on the semaphore by waiting for [2] to equal 0,
+ // then increment it.
+ //
+ // There is a race condition here. There is a possibility that
+ // between the semget() above and the ::semop() below, another
+ // process can call our sem_close() function which can remove
+ // the semaphore if that process is the last one using it.
+ // Therefore, we handle the error condition of an invalid
+ // semaphore ID specially below, and if it does happen, we just
+ // go back and create it again.
+ struct sembuf op_lock[2] = {
+ {2, 0, 0}, // wait for [2] (lock) to equal 0
+ {2, 1, SEM_UNDO} // then increment [2] to 1 - this locks it
+ // UNDO to release the lock if processes exits
+ // before explicitly unlocking
+ };
+
+ if (::semop(id, &op_lock[0], 2) < 0) {
+ if (errno == EINVAL)
+ goto again;
+ }
+
+ // Get the value of the process counter. If it equals 0,
+ // then no one has initialized the semaphore yet.
+ if ((semval = ::semctl(id, 1, GETVAL, 0)) < 0)
+ return false;
+
+ if (semval == 0) {
+ // We could initialize by doing a SETALL, but that
+ // would clear the adjust value that we set when we
+ // locked the semaphore above. Instead, we'll do 2
+ // system calls to initialize [0] and [1].
+ semctl_arg.val = initval;
+ if (::semctl(id, 0, SETVAL, semctl_arg) < 0)
+ return false;
+
+ semctl_arg.val = 1;
+ if (::semctl(id, 1, SETVAL, semctl_arg) < 0)
+ return false;
+ }
+
+ // Decrement the process counter and then release the lock.
+ struct sembuf op_unlock[1] = {
+ 2, -1, 0/*SEM_UNDO*/ // decrement [2] (lock) back to 0
+ };
+
+ if (::semop(id, &op_unlock[0], 1) < 0)
+ return false;
+
+ semid = id;
+ return true;
+}
+
+// Open a semaphore that must already exist.
+// This function should be used, instead of sem_create(), if the caller
+// knows that the semaphore must already exist. For example a client
+// from a client-server pair would use this, if its the server's
+// responsibility to create the semaphore.
+// We return the semaphore ID if all OK, else -1.
+/*
+inline bool advanced_sem_open(key_t key, int &semid)
+{
+ semid = -1;
+ if (key == IPC_PRIVATE)
+ return false; // not intended for private semaphores
+
+ else if (key == (::key_t) -1)
+ return false; // probably an ftok() error by caller
+
+ if ((semid = ::semget(key, 3, 0)) < 0)
+ return false; // doesn't exist, or tables full
+
+ // Decrement the process counter. We don't need a lock
+ struct sembuf op_open[1] = {
+ 1, -1, SEM_UNDO // decrement [1] (proc counter) with undo on exit
+ };
+
+ if (::semop(id, &op_open[0], 1) < 0)
+ return false;
+
+ return true;
+}
+*/
+/****************************************************************************
+ * Remove a semaphore.
+ * This call is intended to be called by a server, for example,
+ * when it is being shut down, as we do an IPC_RMID on the semaphore,
+ * regardless whether other processes may be using it or not.
+ * Most other processes should use sem_close() below.
+ */
+
+inline bool advanced_sem_rm(int id)
+{
+ if (::semctl(id, 0, IPC_RMID, 0) < 0)
+ return false;
+ return true;
+}
+
+
+/****************************************************************************
+ * General semaphore operation. Increment or decrement by a user-specified
+ * amount (positive or negative; amount can't be zero).
+ */
+
+inline bool advanced_sem_op(int id, int value, bool undo = true)
+{
+ ::sembuf op_op[1] = {
+ 0, 99, 0 // decrement or increment [0] with undo on exit
+ // the 99 is set to the actual amount to add
+ // or subtract (positive or negative)
+ };
+ if(undo){
+ op_op[0].sem_flg = SEM_UNDO;
+ }
+ if ((op_op[0].sem_op = value) == 0)
+ return false;
+
+ if (::semop(id, &op_op[0], 1) < 0)
+ return false;
+ return true;
+}
+
+} //namespace xsi {
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //BOOST_INTERPROCESS_SYNC_XSI_ADVANCED_XSI_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp
new file mode 100644
index 0000000000..266e7c5dac
--- /dev/null
+++ b/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp
@@ -0,0 +1,116 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
+
+/*
+ * Provide an simpler and easier to understand interface to the System V
+ * semaphore system calls. There are 7 routines available to the user:
+ *
+ * id = sem_create(key, initval); # create with initial value or open
+ * id = sem_open(key); # open (must already exist)
+ * sem_wait(id); # wait = P = down by 1
+ * sem_signal(id); # signal = V = up by 1
+ * sem_op(id, amount); # wait if (amount < 0)
+ * # signal if (amount > 0)
+ * sem_close(id); # close
+ * sem_rm(id); # remove (delete)
+ *
+ * We create and use a 3-member set for the requested semaphore.
+ * The first member, [0], is the actual semaphore value, and the second
+ * member, [1], is a counter used to know when all processes have finished
+ * with the semaphore. The counter is initialized to a large number,
+ * decremented on every create or open and incremented on every close.
+ * This way we can use the "adjust" feature provided by System V so that
+ * any process that exit's without calling sem_close() is accounted
+ * for. It doesn't help us if the last process does this (as we have
+ * no way of getting control to remove the semaphore) but it will
+ * work if any process other than the last does an exit (intentional
+ * or unintentional).
+ * The third member, [2], of the semaphore set is used as a lock variable
+ * to avoid any race conditions in the sem_create() and sem_close()
+ * functions.
+ */
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <errno.h>
+
+namespace boost {
+namespace interprocess {
+namespace xsi {
+
+// Create a semaphore with a specified initial value.
+// If the semaphore already exists, we don't initialize it (of course).
+// We return the semaphore ID if all OK, else -1.
+
+inline bool simple_sem_open_or_create(::key_t key, int initval, int &semid, int perm)
+{
+ int id, semval;
+ semid = -1;
+
+ if (key == IPC_PRIVATE)
+ return false; //not intended for private semaphores
+
+ else if (key == (::key_t) -1)
+ return false; //probably an ftok() error by caller
+
+ again:
+ if ((id = ::semget(key, 1, (perm & 0x01FF) | IPC_CREAT)) < 0)
+ return false; //permission problem or tables full
+
+ semid = id;
+ return true;
+}
+
+/****************************************************************************
+ * Remove a semaphore.
+ * This call is intended to be called by a server, for example,
+ * when it is being shut down, as we do an IPC_RMID on the semaphore,
+ * regardless whether other processes may be using it or not.
+ * Most other processes should use sem_close() below.
+ */
+
+inline bool simple_sem_rm(int id)
+{
+ if (::semctl(id, 0, IPC_RMID, 0) < 0)
+ return false;
+ return true;
+}
+
+
+/****************************************************************************
+ * General semaphore operation. Increment or decrement by a user-specified
+ * amount (positive or negative; amount can't be zero).
+ */
+
+inline bool simple_sem_op(int id, int value, bool undo = true)
+{
+ ::sembuf op_op[1] = {
+ 0, 99, 0 // decrement or increment [0] with undo on exit
+ // the 99 is set to the actual amount to add
+ // or subtract (positive or negative)
+ };
+ if(undo){
+ op_op[0].sem_flg = SEM_UNDO;
+ }
+ if ((op_op[0].sem_op = value) == 0)
+ return false;
+
+ if (::semop(id, &op_op[0], 1) < 0)
+ return false;
+ return true;
+}
+
+} //namespace xsi {
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
diff --git a/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp
new file mode 100644
index 0000000000..3dffdcc2ed
--- /dev/null
+++ b/boost/interprocess/sync/xsi/xsi_named_mutex.hpp
@@ -0,0 +1,228 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+#error "This header can't be used in Windows operating systems"
+#endif
+
+#include <boost/move/move.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/sync/xsi/basic_xsi_semaphore.hpp>
+#include <cstddef>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <boost/assert.hpp>
+
+//!\file
+//!Describes a class representing a xsi-based named_mutex.
+
+namespace boost {
+namespace interprocess {
+
+//!A class that wraps a XSI (System V)-based named semaphore
+//!that undoes the operation if the process crashes.
+class xsi_named_mutex
+{
+ /// @cond
+ //Non-copyable and non-assignable
+ xsi_named_mutex(xsi_named_mutex &);
+ xsi_named_mutex &operator=(xsi_named_mutex &);
+ /// @endcond
+
+ public:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex)
+
+ //!Default constructor.
+ //!Represents an empty xsi_named_mutex.
+ xsi_named_mutex();
+
+ //!Tries to create a new XSI-based named mutex with a key obtained from a call to ftok (with path
+ //!"path" and id "id"), and permissions "perm".
+ //!If the named mutex previously exists, it tries to open it.
+ //!Otherwise throws an error.
+ xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666)
+ { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, path, id, perm); }
+
+ //!Moves the ownership of "moved"'s named mutex to *this.
+ //!After the call, "moved" does not represent any named mutex
+ //!Does not throw
+ xsi_named_mutex(BOOST_RV_REF(xsi_named_mutex) moved)
+ { this->swap(moved); }
+
+ //!Moves the ownership of "moved"'s named mutex to *this.
+ //!After the call, "moved" does not represent any named mutex.
+ //!Does not throw
+ xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved)
+ {
+ xsi_named_mutex tmp(boost::move(moved));
+ this->swap(tmp);
+ return *this;
+ }
+
+ //!Swaps two xsi_named_mutex. Does not throw
+ void swap(xsi_named_mutex &other);
+
+ //!Destroys *this. The named mutex is still valid after
+ //!destruction. use remove() to destroy the named mutex.
+ ~xsi_named_mutex();
+
+ //!Returns the path used to construct the
+ //!named mutex.
+ const char *get_path() const;
+
+ //!Returns access
+ //!permissions
+ int get_permissions() const;
+
+ //!Returns the mapping handle.
+ //!Never throws
+ mapping_handle_t get_mapping_handle() const;
+
+ //!Erases a XSI-based named mutex from the system.
+ //!Returns false on error. Never throws
+ bool remove();
+
+ void lock();
+
+ void unlock();
+
+ /// @cond
+ private:
+
+ //!Closes a previously opened file mapping. Never throws.
+ void priv_close();
+
+ //!Closes a previously opened file mapping. Never throws.
+ bool priv_open_or_create( ipcdetail::create_enum_t type
+ , const char *path
+ , boost::uint8_t id
+ , int perm);
+ int m_semid;
+ key_t m_key;
+ boost::uint8_t m_id;
+ int m_perm;
+ std::string m_path;
+ /// @endcond
+};
+
+/// @cond
+
+inline xsi_named_mutex::xsi_named_mutex()
+ : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path()
+{}
+
+inline xsi_named_mutex::~xsi_named_mutex()
+{ this->priv_close(); }
+
+inline const char *xsi_named_mutex::get_path() const
+{ return m_path.c_str(); }
+
+inline void xsi_named_mutex::swap(xsi_named_mutex &other)
+{
+ std::swap(m_key, other.m_key);
+ std::swap(m_id, other.m_id);
+ std::swap(m_semid, other.m_semid);
+ std::swap(m_perm, other.m_perm);
+ m_path.swap(other.m_path);
+}
+
+inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const
+{ mapping_handle_t mhnd = { m_semid, true}; return mhnd; }
+
+inline int xsi_named_mutex::get_permissions() const
+{ return m_perm; }
+
+inline bool xsi_named_mutex::priv_open_or_create
+ (ipcdetail::create_enum_t type, const char *path, boost::uint8_t id, int perm)
+{
+ key_t key;
+ if(path){
+ key = ::ftok(path, id);
+ if(((key_t)-1) == key){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+ else{
+ key = IPC_PRIVATE;
+ }
+
+ perm &= 0x01FF;
+
+ int semid;
+ if(!xsi::simple_sem_open_or_create(key, 1, semid, perm)){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+
+ m_perm = perm;
+ m_semid = semid;
+ m_path = path ? path : "";
+ m_id = id;
+ m_key = key;
+
+ return true;
+}
+
+inline void xsi_named_mutex::priv_close()
+{
+}
+
+inline void xsi_named_mutex::lock()
+{
+ if(!xsi::simple_sem_op(m_semid, -1)){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+}
+
+inline void xsi_named_mutex::unlock()
+{
+ bool success = xsi::simple_sem_op(m_semid, 1);
+ (void)success;
+ BOOST_ASSERT(success);
+}
+
+inline bool xsi_named_mutex::remove()
+{
+ if(m_semid != -1){
+ int ret = ::semctl(m_semid, IPC_RMID, 0);
+ if(-1 == ret)
+ return false;
+ //Now put it in default-constructed state
+ m_semid = -1;
+ m_key = -1;
+ m_id = 0;
+ m_perm = 0;
+ m_path.clear();
+ }
+ return false;
+}
+
+///@endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP