Chris@16: // (C) Copyright 2012 Vicente J. Botet Escriba Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: Chris@16: #ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP Chris@16: #define BOOST_THREAD_EXTERNALLY_LOCKED_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: /** Chris@16: * externally_locked cloaks an object of type T, and actually provides full Chris@16: * access to that object through the get and set member functions, provided you Chris@16: * pass a reference to a strict lock object Chris@16: */ Chris@16: Chris@16: //[externally_locked Chris@16: template Chris@16: class externally_locked; Chris@16: template Chris@16: class externally_locked Chris@16: { Chris@16: //BOOST_CONCEPT_ASSERT(( CopyConstructible )); Chris@16: BOOST_CONCEPT_ASSERT(( BasicLockable )); Chris@16: Chris@16: public: Chris@16: typedef MutexType mutex_type; Chris@16: Chris@16: BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) Chris@16: /** Chris@16: * Requires: T is a model of CopyConstructible. Chris@16: * Effects: Constructs an externally locked object copying the cloaked type. Chris@16: */ Chris@16: externally_locked(mutex_type& mtx, const T& obj) : Chris@16: obj_(obj), mtx_(&mtx) Chris@16: { Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: T is a model of Movable. Chris@16: * Effects: Constructs an externally locked object by moving the cloaked type. Chris@16: */ Chris@16: externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) : Chris@16: obj_(move(obj)), mtx_(&mtx) Chris@16: { Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: T is a model of DefaultConstructible. Chris@16: * Effects: Constructs an externally locked object initializing the cloaked type with the default constructor. Chris@16: */ Chris@16: externally_locked(mutex_type& mtx) // BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T())) Chris@16: : obj_(), mtx_(&mtx) Chris@16: { Chris@16: } Chris@16: Chris@16: /** Chris@16: * Copy constructor Chris@16: */ Chris@16: externally_locked(externally_locked const& rhs) //BOOST_NOEXCEPT Chris@16: : obj_(rhs.obj_), mtx_(rhs.mtx_) Chris@16: { Chris@16: } Chris@16: /** Chris@16: * Move constructor Chris@16: */ Chris@16: externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) //BOOST_NOEXCEPT Chris@16: : obj_(move(rhs.obj_)), mtx_(rhs.mtx_) Chris@16: { Chris@16: } Chris@16: Chris@16: /// assignment Chris@16: externally_locked& operator=(externally_locked const& rhs) //BOOST_NOEXCEPT Chris@16: { Chris@16: obj_=rhs.obj_; Chris@16: mtx_=rhs.mtx_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /// move assignment Chris@16: externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT Chris@16: { Chris@101: obj_=move(BOOST_THREAD_RV(rhs).obj_); Chris@16: mtx_=rhs.mtx_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(externally_locked& rhs) //BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR) Chris@16: { Chris@16: swap(obj_, rhs.obj_); Chris@16: swap(mtx_, rhs.mtx_); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: The lk parameter must be locking the associated mtx. Chris@16: * Chris@16: * Returns: The address of the cloaked object.. Chris@16: * Chris@16: * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions Chris@16: */ Chris@16: T& get(strict_lock& lk) Chris@16: { Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return obj_; Chris@16: } Chris@16: Chris@16: const T& get(strict_lock& lk) const Chris@16: { Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return obj_; Chris@16: } Chris@16: Chris@16: template Chris@16: T& get(nested_strict_lock& lk) Chris@16: { Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return obj_; Chris@16: } Chris@16: Chris@16: template Chris@16: const T& get(nested_strict_lock& lk) const Chris@16: { Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return obj_; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: The lk parameter must be locking the associated mtx. Chris@16: * Returns: The address of the cloaked object.. Chris@16: * Chris@16: * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions Chris@16: */ Chris@16: template Chris@16: T& get(Lock& lk) Chris@16: { Chris@16: BOOST_CONCEPT_ASSERT(( StrictLock )); Chris@16: BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: Chris@16: return obj_; Chris@16: } Chris@16: Chris@16: mutex_type* mutex() const BOOST_NOEXCEPT Chris@16: { Chris@16: return mtx_; Chris@16: } Chris@16: Chris@16: // modifiers Chris@16: Chris@16: void lock() Chris@16: { Chris@16: mtx_->lock(); Chris@16: } Chris@16: void unlock() Chris@16: { Chris@16: mtx_->unlock(); Chris@16: } Chris@16: bool try_lock() Chris@16: { Chris@16: return mtx_->try_lock(); Chris@16: } Chris@16: // todo add time related functions Chris@16: Chris@16: private: Chris@16: T obj_; Chris@16: mutex_type* mtx_; Chris@16: }; Chris@16: //] Chris@16: Chris@16: /** Chris@16: * externally_locked specialization for T& that cloaks an reference to an object of type T, and actually Chris@16: * provides full access to that object through the get and set member functions, provided you Chris@16: * pass a reference to a strict lock object. Chris@16: */ Chris@16: Chris@16: //[externally_locked_ref Chris@16: template Chris@16: class externally_locked Chris@16: { Chris@16: //BOOST_CONCEPT_ASSERT(( CopyConstructible )); Chris@16: BOOST_CONCEPT_ASSERT(( BasicLockable )); Chris@16: Chris@16: public: Chris@16: typedef MutexType mutex_type; Chris@16: Chris@16: BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) Chris@16: Chris@16: /** Chris@16: * Effects: Constructs an externally locked object storing the cloaked reference object. Chris@16: */ Chris@16: externally_locked(T& obj, mutex_type& mtx) BOOST_NOEXCEPT : Chris@16: obj_(&obj), mtx_(&mtx) Chris@16: { Chris@16: } Chris@16: Chris@16: /// copy constructor Chris@16: externally_locked(externally_locked const& rhs) BOOST_NOEXCEPT : Chris@16: obj_(rhs.obj_), mtx_(rhs.mtx_) Chris@16: { Chris@16: } Chris@16: Chris@16: /// move constructor Chris@16: externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT : Chris@16: obj_(rhs.obj_), mtx_(rhs.mtx_) Chris@16: { Chris@16: } Chris@16: Chris@16: /// assignment Chris@16: externally_locked& operator=(externally_locked const& rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: obj_=rhs.obj_; Chris@16: mtx_=rhs.mtx_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /// move assignment Chris@16: externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: obj_=rhs.obj_; Chris@16: mtx_=rhs.mtx_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(externally_locked& rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: swap(obj_, rhs.obj_); Chris@16: swap(mtx_, rhs.mtx_); Chris@16: } Chris@16: /** Chris@16: * Requires: The lk parameter must be locking the associated mtx. Chris@16: * Chris@16: * Returns: The address of the cloaked object.. Chris@16: * Chris@16: * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions Chris@16: */ Chris@16: T& get(strict_lock const& lk) Chris@16: { Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: Chris@16: const T& get(strict_lock const& lk) const Chris@16: { Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: Chris@16: template Chris@16: T& get(nested_strict_lock const& lk) Chris@16: { Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: Chris@16: template Chris@16: const T& get(nested_strict_lock const& lk) const Chris@16: { Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: The lk parameter must be locking the associated mtx. Chris@16: * Returns: The address of the cloaked object.. Chris@16: * Chris@16: * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions Chris@16: */ Chris@16: template Chris@16: T& get(Lock const& lk) Chris@16: { Chris@16: BOOST_CONCEPT_ASSERT(( StrictLock )); Chris@16: BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Requires: The lk parameter must be locking the associated mtx. Chris@16: * Returns: The address of the cloaked object.. Chris@16: * Chris@16: * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions Chris@16: */ Chris@16: template Chris@16: T const& get(Lock const& lk) const Chris@16: { Chris@16: BOOST_CONCEPT_ASSERT(( StrictLock )); Chris@16: BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ Chris@16: BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ Chris@16: BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ Chris@16: return *obj_; Chris@16: } Chris@16: mutex_type* mutex() const BOOST_NOEXCEPT Chris@16: { Chris@16: return mtx_; Chris@16: } Chris@16: Chris@16: void lock() Chris@16: { Chris@16: mtx_->lock(); Chris@16: } Chris@16: void unlock() Chris@16: { Chris@16: mtx_->unlock(); Chris@16: } Chris@16: bool try_lock() Chris@16: { Chris@16: return mtx_->try_lock(); Chris@16: } Chris@16: // todo add time related functions Chris@16: Chris@16: protected: Chris@16: T* obj_; Chris@16: mutex_type* mtx_; Chris@16: }; Chris@16: //] Chris@16: Chris@16: template Chris@16: void swap(externally_locked & lhs, externally_locked & rhs) // BOOST_NOEXCEPT Chris@16: { Chris@16: lhs.swap(rhs); Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // header