| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2005-2009. 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/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 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 or upgradable 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 has exclusive or upgradable 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 has exclusive or upgradable |
| //! 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 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 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 |