You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
10 KiB
352 lines
10 KiB
// (C) Copyright 2012 Vicente J. Botet Escriba |
|
// 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) |
|
|
|
|
|
#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP |
|
#define BOOST_THREAD_EXTERNALLY_LOCKED_HPP |
|
|
|
#include <boost/thread/detail/config.hpp> |
|
|
|
#include <boost/thread/exceptions.hpp> |
|
#include <boost/thread/lock_concepts.hpp> |
|
#include <boost/thread/lock_traits.hpp> |
|
#include <boost/thread/lockable_concepts.hpp> |
|
#include <boost/thread/strict_lock.hpp> |
|
|
|
#include <boost/static_assert.hpp> |
|
#include <boost/type_traits/is_same.hpp> |
|
#include <boost/throw_exception.hpp> |
|
#include <boost/core/swap.hpp> |
|
|
|
#include <boost/config/abi_prefix.hpp> |
|
|
|
namespace boost |
|
{ |
|
class mutex; |
|
|
|
/** |
|
* externally_locked cloaks an object of type T, and actually provides full |
|
* access to that object through the get and set member functions, provided you |
|
* pass a reference to a strict lock object |
|
*/ |
|
|
|
//[externally_locked |
|
template <typename T, typename MutexType = boost::mutex> |
|
class externally_locked; |
|
template <typename T, typename MutexType> |
|
class externally_locked |
|
{ |
|
//BOOST_CONCEPT_ASSERT(( CopyConstructible<T> )); |
|
BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> )); |
|
|
|
public: |
|
typedef MutexType mutex_type; |
|
|
|
BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) |
|
/** |
|
* Requires: T is a model of CopyConstructible. |
|
* Effects: Constructs an externally locked object copying the cloaked type. |
|
*/ |
|
externally_locked(mutex_type& mtx, const T& obj) : |
|
obj_(obj), mtx_(&mtx) |
|
{ |
|
} |
|
|
|
/** |
|
* Requires: T is a model of Movable. |
|
* Effects: Constructs an externally locked object by moving the cloaked type. |
|
*/ |
|
externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) : |
|
obj_(move(obj)), mtx_(&mtx) |
|
{ |
|
} |
|
|
|
/** |
|
* Requires: T is a model of DefaultConstructible. |
|
* Effects: Constructs an externally locked object initializing the cloaked type with the default constructor. |
|
*/ |
|
externally_locked(mutex_type& mtx) // BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T())) |
|
: obj_(), mtx_(&mtx) |
|
{ |
|
} |
|
|
|
/** |
|
* Copy constructor |
|
*/ |
|
externally_locked(externally_locked const& rhs) //BOOST_NOEXCEPT |
|
: obj_(rhs.obj_), mtx_(rhs.mtx_) |
|
{ |
|
} |
|
/** |
|
* Move constructor |
|
*/ |
|
externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) //BOOST_NOEXCEPT |
|
: obj_(move(rhs.obj_)), mtx_(rhs.mtx_) |
|
{ |
|
} |
|
|
|
/// assignment |
|
externally_locked& operator=(externally_locked const& rhs) //BOOST_NOEXCEPT |
|
{ |
|
obj_=rhs.obj_; |
|
mtx_=rhs.mtx_; |
|
return *this; |
|
} |
|
|
|
/// move assignment |
|
externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT |
|
{ |
|
obj_=move(BOOST_THREAD_RV(rhs).obj_); |
|
mtx_=rhs.mtx_; |
|
return *this; |
|
} |
|
|
|
void swap(externally_locked& rhs) //BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR) |
|
{ |
|
swap(obj_, rhs.obj_); |
|
swap(mtx_, rhs.mtx_); |
|
} |
|
|
|
/** |
|
* Requires: The lk parameter must be locking the associated mtx. |
|
* |
|
* Returns: The address of the cloaked object.. |
|
* |
|
* Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions |
|
*/ |
|
T& get(strict_lock<mutex_type>& lk) |
|
{ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return obj_; |
|
} |
|
|
|
const T& get(strict_lock<mutex_type>& lk) const |
|
{ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return obj_; |
|
} |
|
|
|
template <class Lock> |
|
T& get(nested_strict_lock<Lock>& lk) |
|
{ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return obj_; |
|
} |
|
|
|
template <class Lock> |
|
const T& get(nested_strict_lock<Lock>& lk) const |
|
{ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return obj_; |
|
} |
|
|
|
/** |
|
* Requires: The lk parameter must be locking the associated mtx. |
|
* Returns: The address of the cloaked object.. |
|
* |
|
* Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions |
|
*/ |
|
template <class Lock> |
|
T& get(Lock& lk) |
|
{ |
|
BOOST_CONCEPT_ASSERT(( StrictLock<Lock> )); |
|
BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
|
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
|
|
return obj_; |
|
} |
|
|
|
mutex_type* mutex() const BOOST_NOEXCEPT |
|
{ |
|
return mtx_; |
|
} |
|
|
|
// modifiers |
|
|
|
void lock() |
|
{ |
|
mtx_->lock(); |
|
} |
|
void unlock() |
|
{ |
|
mtx_->unlock(); |
|
} |
|
bool try_lock() |
|
{ |
|
return mtx_->try_lock(); |
|
} |
|
// todo add time related functions |
|
|
|
private: |
|
T obj_; |
|
mutex_type* mtx_; |
|
}; |
|
//] |
|
|
|
/** |
|
* externally_locked<T&,M> specialization for T& that cloaks an reference to an object of type T, and actually |
|
* provides full access to that object through the get and set member functions, provided you |
|
* pass a reference to a strict lock object. |
|
*/ |
|
|
|
//[externally_locked_ref |
|
template <typename T, typename MutexType> |
|
class externally_locked<T&, MutexType> |
|
{ |
|
//BOOST_CONCEPT_ASSERT(( CopyConstructible<T> )); |
|
BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> )); |
|
|
|
public: |
|
typedef MutexType mutex_type; |
|
|
|
BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) |
|
|
|
/** |
|
* Effects: Constructs an externally locked object storing the cloaked reference object. |
|
*/ |
|
externally_locked(T& obj, mutex_type& mtx) BOOST_NOEXCEPT : |
|
obj_(&obj), mtx_(&mtx) |
|
{ |
|
} |
|
|
|
/// copy constructor |
|
externally_locked(externally_locked const& rhs) BOOST_NOEXCEPT : |
|
obj_(rhs.obj_), mtx_(rhs.mtx_) |
|
{ |
|
} |
|
|
|
/// move constructor |
|
externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT : |
|
obj_(rhs.obj_), mtx_(rhs.mtx_) |
|
{ |
|
} |
|
|
|
/// assignment |
|
externally_locked& operator=(externally_locked const& rhs) BOOST_NOEXCEPT |
|
{ |
|
obj_=rhs.obj_; |
|
mtx_=rhs.mtx_; |
|
return *this; |
|
} |
|
|
|
/// move assignment |
|
externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT |
|
{ |
|
obj_=rhs.obj_; |
|
mtx_=rhs.mtx_; |
|
return *this; |
|
} |
|
|
|
void swap(externally_locked& rhs) BOOST_NOEXCEPT |
|
{ |
|
swap(obj_, rhs.obj_); |
|
swap(mtx_, rhs.mtx_); |
|
} |
|
/** |
|
* Requires: The lk parameter must be locking the associated mtx. |
|
* |
|
* Returns: The address of the cloaked object.. |
|
* |
|
* Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions |
|
*/ |
|
T& get(strict_lock<mutex_type> const& lk) |
|
{ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
|
|
const T& get(strict_lock<mutex_type> const& lk) const |
|
{ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
|
|
template <class Lock> |
|
T& get(nested_strict_lock<Lock> const& lk) |
|
{ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
|
|
template <class Lock> |
|
const T& get(nested_strict_lock<Lock> const& lk) const |
|
{ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
|
|
/** |
|
* Requires: The lk parameter must be locking the associated mtx. |
|
* Returns: The address of the cloaked object.. |
|
* |
|
* Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions |
|
*/ |
|
template <class Lock> |
|
T& get(Lock const& lk) |
|
{ |
|
BOOST_CONCEPT_ASSERT(( StrictLock<Lock> )); |
|
BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
|
|
/** |
|
* Requires: The lk parameter must be locking the associated mtx. |
|
* Returns: The address of the cloaked object.. |
|
* |
|
* Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions |
|
*/ |
|
template <class Lock> |
|
T const& get(Lock const& lk) const |
|
{ |
|
BOOST_CONCEPT_ASSERT(( StrictLock<Lock> )); |
|
BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/ |
|
BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/ |
|
BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ |
|
return *obj_; |
|
} |
|
mutex_type* mutex() const BOOST_NOEXCEPT |
|
{ |
|
return mtx_; |
|
} |
|
|
|
void lock() |
|
{ |
|
mtx_->lock(); |
|
} |
|
void unlock() |
|
{ |
|
mtx_->unlock(); |
|
} |
|
bool try_lock() |
|
{ |
|
return mtx_->try_lock(); |
|
} |
|
// todo add time related functions |
|
|
|
protected: |
|
T* obj_; |
|
mutex_type* mtx_; |
|
}; |
|
//] |
|
|
|
template <typename T, typename MutexType> |
|
void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs) // BOOST_NOEXCEPT |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
|
|
} |
|
|
|
#include <boost/config/abi_suffix.hpp> |
|
|
|
#endif // header
|
|
|