diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/interprocess/sync/shm | |
download | boost-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/shm')
-rw-r--r-- | boost/interprocess/sync/shm/named_condition.hpp | 379 | ||||
-rw-r--r-- | boost/interprocess/sync/shm/named_creation_functor.hpp | 68 | ||||
-rw-r--r-- | boost/interprocess/sync/shm/named_mutex.hpp | 184 | ||||
-rw-r--r-- | boost/interprocess/sync/shm/named_recursive_mutex.hpp | 175 | ||||
-rw-r--r-- | boost/interprocess/sync/shm/named_semaphore.hpp | 141 | ||||
-rw-r--r-- | boost/interprocess/sync/shm/named_upgradable_mutex.hpp | 372 |
6 files changed, 1319 insertions, 0 deletions
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 |