• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // (C) Copyright 2012 Vicente J. Botet Escriba
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 
6 
7 #ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP
8 #define BOOST_THREAD_EXTERNALLY_LOCKED_HPP
9 
10 #include <boost/thread/detail/config.hpp>
11 
12 #include <boost/thread/exceptions.hpp>
13 #include <boost/thread/lock_concepts.hpp>
14 #include <boost/thread/lock_traits.hpp>
15 #include <boost/thread/lockable_concepts.hpp>
16 #include <boost/thread/strict_lock.hpp>
17 
18 #include <boost/static_assert.hpp>
19 #include <boost/type_traits/is_same.hpp>
20 #include <boost/throw_exception.hpp>
21 #include <boost/core/swap.hpp>
22 
23 #include <boost/config/abi_prefix.hpp>
24 
25 namespace boost
26 {
27   class mutex;
28 
29   /**
30    * externally_locked cloaks an object of type T, and actually provides full
31    * access to that object through the get and set member functions, provided you
32    * pass a reference to a strict lock object
33    */
34 
35   //[externally_locked
36   template <typename T, typename MutexType = boost::mutex>
37   class externally_locked;
38   template <typename T, typename MutexType>
39   class externally_locked
40   {
41     //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
42     BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
43 
44   public:
45     typedef MutexType mutex_type;
46 
47     BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked )
48     /**
49      * Requires: T is a model of CopyConstructible.
50      * Effects: Constructs an externally locked object copying the cloaked type.
51      */
externally_locked(mutex_type & mtx,const T & obj)52     externally_locked(mutex_type& mtx, const T& obj) :
53       obj_(obj), mtx_(&mtx)
54     {
55     }
56 
57     /**
58      * Requires: T is a model of Movable.
59      * Effects: Constructs an externally locked object by moving the cloaked type.
60      */
externally_locked(mutex_type & mtx,BOOST_THREAD_RV_REF (T)obj)61     externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) :
62       obj_(move(obj)), mtx_(&mtx)
63     {
64     }
65 
66     /**
67      * Requires: T is a model of DefaultConstructible.
68      * Effects: Constructs an externally locked object initializing the cloaked type with the default constructor.
69      */
externally_locked(mutex_type & mtx)70     externally_locked(mutex_type& mtx) // BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T()))
71     : obj_(), mtx_(&mtx)
72     {
73     }
74 
75     /**
76      *  Copy constructor
77      */
externally_locked(externally_locked const & rhs)78     externally_locked(externally_locked const& rhs) //BOOST_NOEXCEPT
79     : obj_(rhs.obj_), mtx_(rhs.mtx_)
80     {
81     }
82     /**
83      *  Move constructor
84      */
externally_locked(BOOST_THREAD_RV_REF (externally_locked)rhs)85     externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) //BOOST_NOEXCEPT
86     : obj_(move(rhs.obj_)), mtx_(rhs.mtx_)
87     {
88     }
89 
90     /// assignment
operator =(externally_locked const & rhs)91     externally_locked& operator=(externally_locked const& rhs) //BOOST_NOEXCEPT
92     {
93       obj_=rhs.obj_;
94       mtx_=rhs.mtx_;
95       return *this;
96     }
97 
98     /// move assignment
operator =(BOOST_THREAD_RV_REF (externally_locked)rhs)99     externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT
100     {
101       obj_=move(BOOST_THREAD_RV(rhs).obj_);
102       mtx_=rhs.mtx_;
103       return *this;
104     }
105 
swap(externally_locked & rhs)106     void swap(externally_locked& rhs) //BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR)
107     {
108       swap(obj_, rhs.obj_);
109       swap(mtx_, rhs.mtx_);
110     }
111 
112     /**
113      * Requires: The lk parameter must be locking the associated mtx.
114      *
115      * Returns: The address of the cloaked object..
116      *
117      * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
118      */
get(strict_lock<mutex_type> & lk)119     T& get(strict_lock<mutex_type>& lk)
120     {
121       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
122       return obj_;
123     }
124 
get(strict_lock<mutex_type> & lk) const125     const T& get(strict_lock<mutex_type>& lk) const
126     {
127       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
128       return obj_;
129     }
130 
131     template <class Lock>
get(nested_strict_lock<Lock> & lk)132     T& get(nested_strict_lock<Lock>& lk)
133     {
134       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
135       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
136       return obj_;
137     }
138 
139     template <class Lock>
get(nested_strict_lock<Lock> & lk) const140     const T& get(nested_strict_lock<Lock>& lk) const
141     {
142       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
143       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
144       return obj_;
145     }
146 
147     /**
148      * Requires: The lk parameter must be locking the associated mtx.
149      * Returns: The address of the cloaked object..
150      *
151      * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
152      */
153     template <class Lock>
get(Lock & lk)154     T& get(Lock& lk)
155     {
156       BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
157       BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
158       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
159 
160       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
161 
162       return obj_;
163     }
164 
mutex() const165     mutex_type* mutex() const BOOST_NOEXCEPT
166     {
167       return mtx_;
168     }
169 
170     // modifiers
171 
lock()172     void lock()
173     {
174       mtx_->lock();
175     }
unlock()176     void unlock()
177     {
178       mtx_->unlock();
179     }
try_lock()180     bool try_lock()
181     {
182       return mtx_->try_lock();
183     }
184     // todo add time related functions
185 
186   private:
187     T obj_;
188     mutex_type* mtx_;
189   };
190   //]
191 
192   /**
193    * externally_locked<T&,M> specialization for T& that cloaks an reference to an object of type T, and actually
194    * provides full access to that object through the get and set member functions, provided you
195    * pass a reference to a strict lock object.
196    */
197 
198   //[externally_locked_ref
199   template <typename T, typename MutexType>
200   class externally_locked<T&, MutexType>
201   {
202     //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
203     BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
204 
205   public:
206     typedef MutexType mutex_type;
207 
208     BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked )
209 
210     /**
211      * Effects: Constructs an externally locked object storing the cloaked reference object.
212      */
externally_locked(T & obj,mutex_type & mtx)213     externally_locked(T& obj, mutex_type& mtx) BOOST_NOEXCEPT :
214       obj_(&obj), mtx_(&mtx)
215     {
216     }
217 
218     /// copy constructor
externally_locked(externally_locked const & rhs)219     externally_locked(externally_locked const& rhs) BOOST_NOEXCEPT :
220     obj_(rhs.obj_), mtx_(rhs.mtx_)
221     {
222     }
223 
224     /// move constructor
externally_locked(BOOST_THREAD_RV_REF (externally_locked)rhs)225     externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT :
226     obj_(rhs.obj_), mtx_(rhs.mtx_)
227     {
228     }
229 
230     /// assignment
operator =(externally_locked const & rhs)231     externally_locked& operator=(externally_locked const& rhs) BOOST_NOEXCEPT
232     {
233       obj_=rhs.obj_;
234       mtx_=rhs.mtx_;
235       return *this;
236     }
237 
238     /// move assignment
operator =(BOOST_THREAD_RV_REF (externally_locked)rhs)239     externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT
240     {
241       obj_=rhs.obj_;
242       mtx_=rhs.mtx_;
243       return *this;
244     }
245 
swap(externally_locked & rhs)246     void swap(externally_locked& rhs) BOOST_NOEXCEPT
247     {
248       swap(obj_, rhs.obj_);
249       swap(mtx_, rhs.mtx_);
250     }
251     /**
252      * Requires: The lk parameter must be locking the associated mtx.
253      *
254      * Returns: The address of the cloaked object..
255      *
256      * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
257      */
get(strict_lock<mutex_type> const & lk)258     T& get(strict_lock<mutex_type> const& lk)
259     {
260       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
261       return *obj_;
262     }
263 
get(strict_lock<mutex_type> const & lk) const264     const T& get(strict_lock<mutex_type> const& lk) const
265     {
266       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
267       return *obj_;
268     }
269 
270     template <class Lock>
get(nested_strict_lock<Lock> const & lk)271     T& get(nested_strict_lock<Lock> const& lk)
272     {
273       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
274       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
275       return *obj_;
276     }
277 
278     template <class Lock>
get(nested_strict_lock<Lock> const & lk) const279     const T& get(nested_strict_lock<Lock> const& lk) const
280     {
281       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
282       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
283       return *obj_;
284     }
285 
286     /**
287      * Requires: The lk parameter must be locking the associated mtx.
288      * Returns: The address of the cloaked object..
289      *
290      * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
291      */
292     template <class Lock>
get(Lock const & lk)293     T& get(Lock const& lk)
294     {
295       BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
296       BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
297       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
298       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
299       return *obj_;
300     }
301 
302     /**
303      * Requires: The lk parameter must be locking the associated mtx.
304      * Returns: The address of the cloaked object..
305      *
306      * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
307      */
308     template <class Lock>
get(Lock const & lk) const309     T const& get(Lock const& lk) const
310     {
311       BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
312       BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
313       BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
314       BOOST_THREAD_ASSERT_PRECONDITION(  lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
315       return *obj_;
316     }
mutex() const317     mutex_type* mutex() const BOOST_NOEXCEPT
318     {
319       return mtx_;
320     }
321 
lock()322     void lock()
323     {
324       mtx_->lock();
325     }
unlock()326     void unlock()
327     {
328       mtx_->unlock();
329     }
try_lock()330     bool try_lock()
331     {
332       return mtx_->try_lock();
333     }
334     // todo add time related functions
335 
336   protected:
337     T* obj_;
338     mutex_type* mtx_;
339   };
340   //]
341 
342   template <typename T, typename MutexType>
swap(externally_locked<T,MutexType> & lhs,externally_locked<T,MutexType> & rhs)343   void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs) // BOOST_NOEXCEPT
344   {
345     lhs.swap(rhs);
346   }
347 
348 }
349 
350 #include <boost/config/abi_suffix.hpp>
351 
352 #endif // header
353