Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/interprocess/sync/sharable_lock.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 //
0011 // This interface is inspired by Howard Hinnant's lock proposal.
0012 // http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
0013 //
0014 //////////////////////////////////////////////////////////////////////////////
0015 
0016 #ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
0017 #define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP
0018 
0019 #ifndef BOOST_CONFIG_HPP
0020 #  include <boost/config.hpp>
0021 #endif
0022 0023 ">#
0024 #if defined(BOOST_HAS_PRAGMA_ONCE)
0025 #  pragma once
0026 #endif
0027 
0028 #include <boost/interprocess/detail/config_begin.hpp>
0029 #include <boost/interprocess/detail/workaround.hpp>
0030 #include <boost/interprocess/interprocess_fwd.hpp>
0031 #include <boost/interprocess/sync/lock_options.hpp>
0032 #include <boost/interprocess/exceptions.hpp>
0033 #include <boost/interprocess/detail/mpl.hpp>
0034 #include <boost/interprocess/detail/type_traits.hpp>
0035 #include <boost/interprocess/detail/simple_swap.hpp>
0036 #include <boost/move/utility_core.hpp>
0037 
0038 //!\file
0039 //!Describes the upgradable_lock class that serves to acquire the upgradable
0040 //!lock of a mutex.
0041 
0042 namespace boost {
0043 namespace interprocess {
0044 
0045 
0046 //!sharable_lock is meant to carry out the tasks for sharable-locking
0047 //!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking
0048 //!(recursive or not) for the Mutex. The Mutex need not supply all of this
0049 //!functionality. If the client of sharable_lock<Mutex> does not use functionality which
0050 //!the Mutex does not supply, no harm is done. Mutex ownership can be shared among
0051 //!sharable_locks, and a single upgradable_lock. sharable_lock does not support
0052 //!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock,
0053 //!upgradable_lock and scoped_lock via transfer_lock syntax.*/
0054 template <class SharableMutex>
0055 class sharable_lock
0056 {
0057    public:
0058    typedef SharableMutex mutex_type;
0059    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0060    private:
0061    typedef sharable_lock<SharableMutex> this_type;
0062    explicit sharable_lock(scoped_lock<mutex_type>&);
0063    typedef bool this_type::*unspecified_bool_type;
0064    BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock)
0065    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0066    public:
0067 
0068    //!Effects: Default constructs a sharable_lock.
0069    //!Postconditions: owns() == false and mutex() == 0.
0070    sharable_lock() BOOST_NOEXCEPT
0071       : mp_mutex(0), m_locked(false)
0072    {}
0073 
0074    //!Effects: m.lock_sharable().
0075    //!Postconditions: owns() == true and mutex() == &m.
0076    //!Notes: The constructor will take sharable-ownership of the mutex. If
0077    //!   another thread already owns the mutex with exclusive ownership
0078    //!   (scoped_lock), this thread will block until the mutex is released.
0079    //!   If another thread owns the mutex with sharable or upgradable ownership,
0080    //!   then no blocking will occur. Whether or not this constructor handles
0081    //!   recursive locking depends upon the mutex.
0082    explicit sharable_lock(mutex_type& m)
0083       : mp_mutex(&m), m_locked(false)
0084    {  mp_mutex->lock_sharable();   m_locked = true;  }
0085 
0086    //!Postconditions: owns() == false, and mutex() == &m.
0087    //!Notes: The constructor will not take ownership of the mutex. There is no effect
0088    //!   required on the referenced mutex.
0089    sharable_lock(mutex_type& m, defer_lock_type)
0090       : mp_mutex(&m), m_locked(false)
0091    {}
0092 
0093    //!Postconditions: owns() == true, and mutex() == &m.
0094    //!Notes: The constructor will suppose that the mutex is already sharable
0095    //!   locked. There is no effect required on the referenced mutex.
0096    sharable_lock(mutex_type& m, accept_ownership_type)
0097       : mp_mutex(&m), m_locked(true)
0098    {}
0099 
0100    //!Effects: m.try_lock_sharable()
0101    //!Postconditions: mutex() == &m. owns() == the return value of the
0102    //!   m.try_lock_sharable() executed within the constructor.
0103    //!Notes: The constructor will take sharable-ownership of the mutex if it
0104    //!   can do so without waiting. Whether or not this constructor handles
0105    //!   recursive locking depends upon the mutex. If the mutex_type does not
0106    //!   support try_lock_sharable, this constructor will fail at compile
0107    //!   time if instantiated, but otherwise have no effect.
0108    sharable_lock(mutex_type& m, try_to_lock_type)
0109       : mp_mutex(&m), m_locked(false)
0110    {  m_locked = mp_mutex->try_lock_sharable();   }
0111 
0112    //!Effects: m.timed_lock_sharable(abs_time)
0113    //!Postconditions: mutex() == &m. owns() == the return value of the
0114    //!   m.timed_lock_sharable() executed within the constructor.
0115    //!Notes: The constructor will take sharable-ownership of the mutex if it
0116    //!   can do so within the time specified. Whether or not this constructor
0117    //!   handles recursive locking depends upon the mutex. If the mutex_type
0118    //!   does not support timed_lock_sharable, this constructor will fail at
0119    //!   compile time if instantiated, but otherwise have no effect.
0120    template<class TimePoint>
0121    sharable_lock(mutex_type& m, const TimePoint& abs_time)
0122       : mp_mutex(&m), m_locked(false)
0123    {  m_locked = mp_mutex->timed_lock_sharable(abs_time);  }
0124 
0125    //!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns()
0126    //!   before the construction. upgr.owns() == false after the construction.
0127    //!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this
0128    //!   sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then
0129    //!   neither will this sharable_lock. Only a moved sharable_lock's will match this
0130    //!   signature. An non-moved sharable_lock can be moved with the expression:
0131    //!   "boost::move(lock);". This constructor does not alter the state of the mutex,
0132    //!   only potentially who owns it.
0133    sharable_lock(BOOST_RV_REF(sharable_lock<mutex_type>) upgr) BOOST_NOEXCEPT
0134       : mp_mutex(0), m_locked(upgr.owns())
0135    {  mp_mutex = upgr.release(); }
0136 
0137    //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the
0138    //!   referenced mutex.
0139    //!Postconditions: mutex() == the value upgr.mutex() had before the construction.
0140    //!   upgr.mutex() == 0 owns() == the value of upgr.owns() before construction.
0141    //!   upgr.owns() == false after the construction.
0142    //!Notes: If upgr is locked, this constructor will lock this sharable_lock while
0143    //!   unlocking upgr. Only a moved sharable_lock's will match this
0144    //!   signature. An non-moved upgradable_lock can be moved with the expression:
0145    //!   "boost::move(lock);".*/
0146    template<class T>
0147    sharable_lock(BOOST_RV_REF(upgradable_lock<T>) upgr
0148       , typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
0149       : mp_mutex(0), m_locked(false)
0150    {
0151       upgradable_lock<mutex_type> &u_lock = upgr;
0152       if(u_lock.owns()){
0153          u_lock.mutex()->unlock_upgradable_and_lock_sharable();
0154          m_locked = true;
0155       }
0156       mp_mutex = u_lock.release();
0157    }
0158 
0159    //!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the
0160    //!   referenced mutex.
0161    //!Postconditions: mutex() == the value scop.mutex() had before the construction.
0162    //!   scop.mutex() == 0 owns() == scop.owns() before the constructor. After the
0163    //!   construction, scop.owns() == false.
0164    //!Notes: If scop is locked, this constructor will transfer the exclusive ownership
0165    //!   to a sharable-ownership of this sharable_lock.
0166    //!   Only a moved scoped_lock's will match this
0167    //!   signature. An non-moved scoped_lock can be moved with the expression:
0168    //!   "boost::move(lock);".
0169    template<class T>
0170    sharable_lock(BOOST_RV_REF(scoped_lock<T>) scop
0171                , typename ipcdetail::enable_if< ipcdetail::is_same<T, SharableMutex> >::type * = 0)
0172       : mp_mutex(0), m_locked(false)
0173    {
0174       scoped_lock<mutex_type> &e_lock = scop;
0175       if(e_lock.owns()){
0176          e_lock.mutex()->unlock_and_lock_sharable();
0177          m_locked = true;
0178       }
0179       mp_mutex = e_lock.release();
0180    }
0181 
0182    //!Effects: if (owns()) mp_mutex->unlock_sharable().
0183    //!Notes: The destructor behavior ensures that the mutex lock is not leaked.
0184    ~sharable_lock()
0185    {
0186       BOOST_INTERPROCESS_TRY{
0187          if(m_locked && mp_mutex)   mp_mutex->unlock_sharable();
0188       }
0189       BOOST_INTERPROCESS_CATCH(...){} BOOST_INTERPROCESS_CATCH_END
0190    }
0191 
0192    //!Effects: If owns() before the call, then unlock_sharable() is called on mutex().
0193    //!   *this gets the state of upgr and upgr gets set to a default constructed state.
0194    //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex
0195    //!   before the assignment. In this case, this will own the mutex after the assignment
0196    //!   (and upgr will not), but the mutex's lock count will be decremented by one.
0197    sharable_lock &operator=(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
0198    {
0199       if(this->owns())
0200          this->unlock();
0201       m_locked = upgr.owns();
0202       mp_mutex = upgr.release();
0203       return *this;
0204    }
0205 
0206    //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
0207    //!   exception. Calls lock_sharable() on the referenced mutex.
0208    //!Postconditions: owns() == true.
0209    //!Notes: The sharable_lock changes from a state of not owning the
0210    //!   mutex, to owning the mutex, blocking if necessary.
0211    void lock()
0212    {
0213       if(!mp_mutex || m_locked)
0214          throw lock_exception();
0215       mp_mutex->lock_sharable();
0216       m_locked = true;
0217    }
0218 
0219    //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
0220    //!   exception. Calls try_lock_sharable() on the referenced mutex.
0221    //!Postconditions: owns() == the value returned from
0222    //!   mutex()->try_lock_sharable().
0223    //!Notes: The sharable_lock changes from a state of not owning the mutex,
0224    //!   to owning the mutex, but only if blocking was not required. If the
0225    //!   mutex_type does not support try_lock_sharable(), this function will
0226    //!   fail at compile time if instantiated, but otherwise have no effect.
0227    bool try_lock()
0228    {
0229       if(!mp_mutex || m_locked)
0230          throw lock_exception();
0231       m_locked = mp_mutex->try_lock_sharable();
0232       return m_locked;
0233    }
0234 
0235    //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
0236    //!   exception. Calls timed_lock_sharable(abs_time) on the referenced mutex.
0237    //!Postconditions: owns() == the value returned from
0238    //!   mutex()->timed_lock_sharable(elps_time).
0239    //!Notes: The sharable_lock changes from a state of not owning the mutex,
0240    //!   to owning the mutex, but only if it can obtain ownership within the
0241    //!   specified time interval. If the mutex_type does not support
0242    //!   timed_lock_sharable(), this function will fail at compile time if
0243    //!   instantiated, but otherwise have no effect.
0244    template<class TimePoint>
0245    bool timed_lock(const TimePoint& abs_time)
0246    {
0247       if(!mp_mutex || m_locked)
0248          throw lock_exception();
0249       m_locked = mp_mutex->timed_lock_sharable(abs_time);
0250       return m_locked;
0251    }
0252 
0253    //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
0254    //!   exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
0255    //!Postconditions: owns() == the value returned from
0256    //!   mutex()->timed_lock_sharable(elps_time).
0257    //!Notes: The sharable_lock changes from a state of not owning the mutex,
0258    //!   to owning the mutex, but only if it can obtain ownership within the
0259    //!   specified time interval. If the mutex_type does not support
0260    //!   timed_lock_sharable(), this function will fail at compile time if
0261    //!   instantiated, but otherwise have no effect.
0262    //!
0263    //!Note: Similar to timed_lock, but with a std-like interface
0264    template<class TimePoint>
0265    bool try_lock_until(const TimePoint& abs_time)
0266    {
0267       if(!mp_mutex || m_locked)
0268          throw lock_exception();
0269       m_locked = mp_mutex->try_lock_shared_until(abs_time);
0270       return m_locked;
0271    }
0272 
0273    //!Effects: If mutex() == 0 or already locked, throws a lock_exception()
0274    //!   exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
0275    //!Postconditions: owns() == the value returned from
0276    //!   mutex()->timed_lock_sharable(elps_time).
0277    //!Notes: The sharable_lock changes from a state of not owning the mutex,
0278    //!   to owning the mutex, but only if it can obtain ownership within the
0279    //!   specified time interval. If the mutex_type does not support
0280    //!   timed_lock_sharable(), this function will fail at compile time if
0281    //!   instantiated, but otherwise have no effect.
0282    //!
0283    //!Note: Similar to timed_lock, but with a std-like interface
0284    template<class Duration>
0285    bool try_lock_for(const Duration& dur)
0286    {
0287       if(!mp_mutex || m_locked)
0288          throw lock_exception();
0289       m_locked = mp_mutex->try_lock_shared_for(dur);
0290       return m_locked;
0291    }
0292 
0293    //!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception.
0294    //!   Calls unlock_sharable() on the referenced mutex.
0295    //!Postconditions: owns() == false.
0296    //!Notes: The sharable_lock changes from a state of owning the mutex, to
0297    //!   not owning the mutex.
0298    void unlock()
0299    {
0300       if(!mp_mutex || !m_locked)
0301          throw lock_exception();
0302       mp_mutex->unlock_sharable();
0303       m_locked = false;
0304    }
0305 
0306    //!Effects: Returns true if this scoped_lock has
0307    //!acquired the referenced mutex.
0308    bool owns() const BOOST_NOEXCEPT
0309    {  return m_locked && mp_mutex;  }
0310 
0311    //!Conversion to bool.
0312    //!Returns owns().
0313    operator unspecified_bool_type() const BOOST_NOEXCEPT
0314    {  return m_locked? &this_type::m_locked : 0;   }
0315 
0316    //!Effects: Returns a pointer to the referenced mutex, or 0 if
0317    //!there is no mutex to reference.
0318    mutex_type* mutex() const BOOST_NOEXCEPT
0319    {  return  mp_mutex;  }
0320 
0321    //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
0322    //!   mutex to reference.
0323    //!Postconditions: mutex() == 0 and owns() == false.
0324    mutex_type* release() BOOST_NOEXCEPT
0325    {
0326       mutex_type *mut = mp_mutex;
0327       mp_mutex = 0;
0328       m_locked = false;
0329       return mut;
0330    }
0331 
0332    //!Effects: Swaps state with moved lock.
0333    //!Throws: Nothing.
0334    void swap(sharable_lock<mutex_type> &other) BOOST_NOEXCEPT
0335    {
0336       (simple_swap)(mp_mutex, other.mp_mutex);
0337       (simple_swap)(m_locked, other.m_locked);
0338    }
0339 
0340    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0341    private:
0342    mutex_type *mp_mutex;
0343    bool        m_locked;
0344    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0345 };
0346 
0347 } // namespace interprocess
0348 } // namespace boost
0349 
0350 #include <boost/interprocess/detail/config_end.hpp>
0351 
0352 #endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP