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