Line data Source code
1 : // Distributed under the Boost Software License, Version 1.0. (See
2 : // accompanying file LICENSE_1_0.txt or copy at
3 : // http://www.boost.org/LICENSE_1_0.txt)
4 : // (C) Copyright 2007 Anthony Williams
5 : // (C) Copyright 2011-2012 Vicente J. Botet Escriba
6 :
7 : #ifndef BOOST_THREAD_LOCK_TYPES_HPP
8 : #define BOOST_THREAD_LOCK_TYPES_HPP
9 :
10 : #include <boost/thread/detail/config.hpp>
11 : #include <boost/thread/detail/move.hpp>
12 : #include <boost/thread/exceptions.hpp>
13 : #include <boost/thread/lock_options.hpp>
14 : #include <boost/thread/lockable_traits.hpp>
15 : #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
16 : #include <boost/thread/is_locked_by_this_thread.hpp>
17 : #endif
18 : #include <boost/thread/thread_time.hpp>
19 :
20 : #include <boost/assert.hpp>
21 : #ifdef BOOST_THREAD_USES_CHRONO
22 : #include <boost/chrono/time_point.hpp>
23 : #include <boost/chrono/duration.hpp>
24 : #endif
25 : #include <boost/detail/workaround.hpp>
26 :
27 : #include <boost/config/abi_prefix.hpp>
28 :
29 : namespace boost
30 : {
31 : struct xtime;
32 :
33 : template <typename Mutex>
34 : class shared_lock;
35 :
36 : template <typename Mutex>
37 : class upgrade_lock;
38 :
39 : template <typename Mutex>
40 : class unique_lock;
41 :
42 : namespace detail
43 : {
44 : template <typename Mutex>
45 : class try_lock_wrapper;
46 : }
47 :
48 : #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
49 : namespace sync
50 : {
51 : template<typename T>
52 : struct is_basic_lockable<unique_lock<T> >
53 : {
54 : BOOST_STATIC_CONSTANT(bool, value = true);
55 : };
56 : template<typename T>
57 : struct is_lockable<unique_lock<T> >
58 : {
59 : BOOST_STATIC_CONSTANT(bool, value = true);
60 : };
61 :
62 : template<typename T>
63 : struct is_basic_lockable<shared_lock<T> >
64 : {
65 : BOOST_STATIC_CONSTANT(bool, value = true);
66 : };
67 : template<typename T>
68 : struct is_lockable<shared_lock<T> >
69 : {
70 : BOOST_STATIC_CONSTANT(bool, value = true);
71 : };
72 :
73 : template<typename T>
74 : struct is_basic_lockable<upgrade_lock<T> >
75 : {
76 : BOOST_STATIC_CONSTANT(bool, value = true);
77 : };
78 : template<typename T>
79 : struct is_lockable<upgrade_lock<T> >
80 : {
81 : BOOST_STATIC_CONSTANT(bool, value = true);
82 : };
83 :
84 : template<typename T>
85 : struct is_basic_lockable<detail::try_lock_wrapper<T> >
86 : {
87 : BOOST_STATIC_CONSTANT(bool, value = true);
88 : };
89 : template<typename T>
90 : struct is_lockable<detail::try_lock_wrapper<T> >
91 : {
92 : BOOST_STATIC_CONSTANT(bool, value = true);
93 : };
94 : }
95 : #endif
96 :
97 :
98 : template <typename Mutex>
99 : class unique_lock
100 : {
101 : private:
102 : Mutex* m;
103 : bool is_locked;
104 :
105 : private:
106 : explicit unique_lock(upgrade_lock<Mutex>&);
107 : unique_lock& operator=(upgrade_lock<Mutex>& other);
108 : public:
109 : typedef Mutex mutex_type;
110 : BOOST_THREAD_MOVABLE_ONLY( unique_lock)
111 :
112 : #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
113 : #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
114 : unique_lock(const volatile unique_lock&);
115 : #endif
116 : #endif
117 : unique_lock()BOOST_NOEXCEPT :
118 : m(0),is_locked(false)
119 : {}
120 :
121 0 : explicit unique_lock(Mutex& m_) :
122 0 : m(&m_), is_locked(false)
123 : {
124 0 : lock();
125 0 : }
126 : unique_lock(Mutex& m_, adopt_lock_t) :
127 : m(&m_), is_locked(true)
128 : {
129 : #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
130 : BOOST_ASSERT(is_locked_by_this_thread(m));
131 : #endif
132 : }
133 : unique_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
134 : m(&m_),is_locked(false)
135 : {}
136 : unique_lock(Mutex& m_, try_to_lock_t) :
137 : m(&m_), is_locked(false)
138 : {
139 : try_lock();
140 : }
141 : #if defined BOOST_THREAD_USES_DATETIME
142 : template<typename TimeDuration>
143 : unique_lock(Mutex& m_,TimeDuration const& target_time):
144 : m(&m_),is_locked(false)
145 : {
146 : timed_lock(target_time);
147 : }
148 : unique_lock(Mutex& m_,system_time const& target_time):
149 : m(&m_),is_locked(false)
150 : {
151 : timed_lock(target_time);
152 : }
153 : #endif
154 : #ifdef BOOST_THREAD_USES_CHRONO
155 : template <class Clock, class Duration>
156 : unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
157 : : m(&mtx), is_locked(mtx.try_lock_until(t))
158 : {
159 : }
160 : template <class Rep, class Period>
161 : unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
162 : : m(&mtx), is_locked(mtx.try_lock_for(d))
163 : {
164 : }
165 : #endif
166 :
167 : unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT:
168 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
169 : {
170 : BOOST_THREAD_RV(other).is_locked=false;
171 : BOOST_THREAD_RV(other).m=0;
172 : }
173 :
174 : BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other);
175 :
176 : #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
177 : //std-2104 unique_lock move-assignment should not be noexcept
178 : unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
179 : {
180 : unique_lock temp(::boost::move(other));
181 : swap(temp);
182 : return *this;
183 : }
184 : #endif
185 :
186 : //std-2104 unique_lock move-assignment should not be noexcept
187 : unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) //BOOST_NOEXCEPT
188 : {
189 : unique_lock temp(::boost::move(other));
190 : swap(temp);
191 : return *this;
192 : }
193 : #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
194 : #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
195 : unique_lock& operator=(unique_lock<Mutex> other)
196 : {
197 : swap(other);
198 : return *this;
199 : }
200 : #endif // BOOST_WORKAROUND
201 : #endif
202 :
203 : // Conversion from upgrade locking
204 : unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, try_to_lock_t)
205 : : m(0),is_locked(false)
206 : {
207 : if (BOOST_THREAD_RV(ul).owns_lock())
208 : {
209 : if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock())
210 : {
211 : m = BOOST_THREAD_RV(ul).release();
212 : is_locked = true;
213 : }
214 : }
215 : else
216 : {
217 : m = BOOST_THREAD_RV(ul).release();
218 : }
219 : }
220 :
221 : #ifdef BOOST_THREAD_USES_CHRONO
222 : template <class Clock, class Duration>
223 : unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
224 : const chrono::time_point<Clock, Duration>& abs_time)
225 : : m(0),is_locked(false)
226 : {
227 : if (BOOST_THREAD_RV(ul).owns_lock())
228 : {
229 : if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time))
230 : {
231 : m = BOOST_THREAD_RV(ul).release();
232 : is_locked = true;
233 : }
234 : }
235 : else
236 : {
237 : m = BOOST_THREAD_RV(ul).release();
238 : }
239 : }
240 :
241 : template <class Rep, class Period>
242 : unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
243 : const chrono::duration<Rep, Period>& rel_time)
244 : : m(0),is_locked(false)
245 : {
246 : if (BOOST_THREAD_RV(ul).owns_lock())
247 : {
248 : if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time))
249 : {
250 : m = BOOST_THREAD_RV(ul).release();
251 : is_locked = true;
252 : }
253 : }
254 : else
255 : {
256 : m = BOOST_THREAD_RV(ul).release();
257 : }
258 : }
259 : #endif
260 :
261 : #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
262 : // Conversion from shared locking
263 : unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
264 : : m(0),is_locked(false)
265 : {
266 : if (BOOST_THREAD_RV(sl).owns_lock())
267 : {
268 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock())
269 : {
270 : m = BOOST_THREAD_RV(sl).release();
271 : is_locked = true;
272 : }
273 : }
274 : else
275 : {
276 : m = BOOST_THREAD_RV(sl).release();
277 : }
278 : }
279 :
280 : #ifdef BOOST_THREAD_USES_CHRONO
281 : template <class Clock, class Duration>
282 : unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
283 : const chrono::time_point<Clock, Duration>& abs_time)
284 : : m(0),is_locked(false)
285 : {
286 : if (BOOST_THREAD_RV(sl).owns_lock())
287 : {
288 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time))
289 : {
290 : m = BOOST_THREAD_RV(sl).release();
291 : is_locked = true;
292 : }
293 : }
294 : else
295 : {
296 : m = BOOST_THREAD_RV(sl).release();
297 : }
298 : }
299 :
300 : template <class Rep, class Period>
301 : unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
302 : const chrono::duration<Rep, Period>& rel_time)
303 : : m(0),is_locked(false)
304 : {
305 : if (BOOST_THREAD_RV(sl).owns_lock())
306 : {
307 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time))
308 : {
309 : m = BOOST_THREAD_RV(sl).release();
310 : is_locked = true;
311 : }
312 : }
313 : else
314 : {
315 : m = BOOST_THREAD_RV(sl).release();
316 : }
317 : }
318 : #endif // BOOST_THREAD_USES_CHRONO
319 : #endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
320 :
321 : void swap(unique_lock& other)BOOST_NOEXCEPT
322 : {
323 : std::swap(m,other.m);
324 : std::swap(is_locked,other.is_locked);
325 : }
326 :
327 0 : ~unique_lock()
328 : {
329 0 : if (owns_lock())
330 : {
331 0 : m->unlock();
332 : }
333 0 : }
334 0 : void lock()
335 : {
336 0 : if (m == 0)
337 : {
338 0 : boost::throw_exception(
339 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
340 : }
341 0 : if (owns_lock())
342 : {
343 0 : boost::throw_exception(
344 : boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
345 : }
346 0 : m->lock();
347 0 : is_locked = true;
348 0 : }
349 : bool try_lock()
350 : {
351 : if (m == 0)
352 : {
353 : boost::throw_exception(
354 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
355 : }
356 : if (owns_lock())
357 : {
358 : boost::throw_exception(
359 : boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
360 : }
361 : is_locked = m->try_lock();
362 : return is_locked;
363 : }
364 : #if defined BOOST_THREAD_USES_DATETIME
365 : template<typename TimeDuration>
366 : bool timed_lock(TimeDuration const& relative_time)
367 : {
368 : if(m==0)
369 : {
370 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
371 : }
372 : if(owns_lock())
373 : {
374 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
375 : }
376 : is_locked=m->timed_lock(relative_time);
377 : return is_locked;
378 : }
379 :
380 : bool timed_lock(::boost::system_time const& absolute_time)
381 : {
382 : if(m==0)
383 : {
384 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
385 : }
386 : if(owns_lock())
387 : {
388 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
389 : }
390 : is_locked=m->timed_lock(absolute_time);
391 : return is_locked;
392 : }
393 : bool timed_lock(::boost::xtime const& absolute_time)
394 : {
395 : if(m==0)
396 : {
397 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
398 : }
399 : if(owns_lock())
400 : {
401 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
402 : }
403 : is_locked=m->timed_lock(absolute_time);
404 : return is_locked;
405 : }
406 : #endif
407 : #ifdef BOOST_THREAD_USES_CHRONO
408 :
409 : template <class Rep, class Period>
410 : bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
411 : {
412 : if(m==0)
413 : {
414 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
415 : }
416 : if(owns_lock())
417 : {
418 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
419 : }
420 : is_locked=m->try_lock_for(rel_time);
421 : return is_locked;
422 : }
423 : template <class Clock, class Duration>
424 : bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
425 : {
426 : if(m==0)
427 : {
428 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
429 : }
430 : if(owns_lock())
431 : {
432 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
433 : }
434 : is_locked=m->try_lock_until(abs_time);
435 : return is_locked;
436 : }
437 : #endif
438 :
439 0 : void unlock()
440 : {
441 0 : if (m == 0)
442 : {
443 0 : boost::throw_exception(
444 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
445 : }
446 0 : if (!owns_lock())
447 : {
448 0 : boost::throw_exception(
449 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock doesn't own the mutex"));
450 : }
451 0 : m->unlock();
452 0 : is_locked = false;
453 0 : }
454 :
455 : #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
456 : typedef void (unique_lock::*bool_type)();
457 : operator bool_type() const BOOST_NOEXCEPT
458 : {
459 : return is_locked?&unique_lock::lock:0;
460 : }
461 : bool operator!() const BOOST_NOEXCEPT
462 : {
463 : return !owns_lock();
464 : }
465 : #else
466 : explicit operator bool() const BOOST_NOEXCEPT
467 : {
468 : return owns_lock();
469 : }
470 : #endif
471 0 : bool owns_lock() const BOOST_NOEXCEPT
472 : {
473 : return is_locked;
474 : }
475 :
476 : Mutex* mutex() const BOOST_NOEXCEPT
477 : {
478 : return m;
479 : }
480 :
481 0 : Mutex* release()BOOST_NOEXCEPT
482 : {
483 0 : Mutex* const res=m;
484 0 : m=0;
485 0 : is_locked=false;
486 : return res;
487 : }
488 :
489 : friend class shared_lock<Mutex> ;
490 : friend class upgrade_lock<Mutex> ;
491 : };
492 :
493 : template<typename Mutex>
494 : void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs)
495 : BOOST_NOEXCEPT
496 : {
497 : lhs.swap(rhs);
498 : }
499 :
500 : BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
501 :
502 : template<typename Mutex>
503 : class shared_lock
504 : {
505 : protected:
506 : Mutex* m;
507 : bool is_locked;
508 :
509 : public:
510 : typedef Mutex mutex_type;
511 : BOOST_THREAD_MOVABLE_ONLY(shared_lock)
512 :
513 : shared_lock() BOOST_NOEXCEPT:
514 : m(0),is_locked(false)
515 : {}
516 :
517 : explicit shared_lock(Mutex& m_):
518 : m(&m_),is_locked(false)
519 : {
520 : lock();
521 : }
522 : shared_lock(Mutex& m_,adopt_lock_t):
523 : m(&m_),is_locked(true)
524 : {
525 : #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
526 : BOOST_ASSERT(is_locked_by_this_thread(m));
527 : #endif
528 : }
529 : shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
530 : m(&m_),is_locked(false)
531 : {}
532 : shared_lock(Mutex& m_,try_to_lock_t):
533 : m(&m_),is_locked(false)
534 : {
535 : try_lock();
536 : }
537 : #if defined BOOST_THREAD_USES_DATETIME
538 : shared_lock(Mutex& m_,system_time const& target_time):
539 : m(&m_),is_locked(false)
540 : {
541 : timed_lock(target_time);
542 : }
543 : #endif
544 : #ifdef BOOST_THREAD_USES_CHRONO
545 : template <class Clock, class Duration>
546 : shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
547 : : m(&mtx), is_locked(mtx.try_lock_shared_until(t))
548 : {
549 : }
550 : template <class Rep, class Period>
551 : shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
552 : : m(&mtx), is_locked(mtx.try_lock_shared_for(d))
553 : {
554 : }
555 : #endif
556 :
557 : shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
558 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
559 : {
560 : BOOST_THREAD_RV(other).is_locked=false;
561 : BOOST_THREAD_RV(other).m=0;
562 : }
563 :
564 : BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
565 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
566 : {
567 : if(is_locked)
568 : {
569 : m->unlock_and_lock_shared();
570 : }
571 : BOOST_THREAD_RV(other).is_locked=false;
572 : BOOST_THREAD_RV(other).m=0;
573 : }
574 :
575 : BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
576 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
577 : {
578 : if(is_locked)
579 : {
580 : m->unlock_upgrade_and_lock_shared();
581 : }
582 : BOOST_THREAD_RV(other).is_locked=false;
583 : BOOST_THREAD_RV(other).m=0;
584 : }
585 :
586 : //std-2104 unique_lock move-assignment should not be noexcept
587 : shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
588 : {
589 : shared_lock temp(::boost::move(other));
590 : swap(temp);
591 : return *this;
592 : }
593 : #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
594 : shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
595 : {
596 : shared_lock temp(::boost::move(other));
597 : swap(temp);
598 : return *this;
599 : }
600 :
601 : shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
602 : {
603 : shared_lock temp(::boost::move(other));
604 : swap(temp);
605 : return *this;
606 : }
607 : #endif
608 :
609 : void swap(shared_lock& other) BOOST_NOEXCEPT
610 : {
611 : std::swap(m,other.m);
612 : std::swap(is_locked,other.is_locked);
613 : }
614 :
615 : Mutex* mutex() const BOOST_NOEXCEPT
616 : {
617 : return m;
618 : }
619 :
620 : Mutex* release() BOOST_NOEXCEPT
621 : {
622 : Mutex* const res=m;
623 : m=0;
624 : is_locked=false;
625 : return res;
626 : }
627 :
628 : ~shared_lock()
629 : {
630 : if(owns_lock())
631 : {
632 : m->unlock_shared();
633 : }
634 : }
635 : void lock()
636 : {
637 : if(m==0)
638 : {
639 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
640 : }
641 : if(owns_lock())
642 : {
643 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
644 : }
645 : m->lock_shared();
646 : is_locked=true;
647 : }
648 : bool try_lock()
649 : {
650 : if(m==0)
651 : {
652 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
653 : }
654 : if(owns_lock())
655 : {
656 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
657 : }
658 : is_locked=m->try_lock_shared();
659 : return is_locked;
660 : }
661 : #if defined BOOST_THREAD_USES_DATETIME
662 : bool timed_lock(boost::system_time const& target_time)
663 : {
664 : if(m==0)
665 : {
666 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
667 : }
668 : if(owns_lock())
669 : {
670 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
671 : }
672 : is_locked=m->timed_lock_shared(target_time);
673 : return is_locked;
674 : }
675 : template<typename Duration>
676 : bool timed_lock(Duration const& target_time)
677 : {
678 : if(m==0)
679 : {
680 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
681 : }
682 : if(owns_lock())
683 : {
684 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
685 : }
686 : is_locked=m->timed_lock_shared(target_time);
687 : return is_locked;
688 : }
689 : #endif
690 : #ifdef BOOST_THREAD_USES_CHRONO
691 : template <class Rep, class Period>
692 : bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
693 : {
694 : if(m==0)
695 : {
696 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
697 : }
698 : if(owns_lock())
699 : {
700 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
701 : }
702 : is_locked=m->try_lock_shared_for(rel_time);
703 : return is_locked;
704 : }
705 : template <class Clock, class Duration>
706 : bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
707 : {
708 : if(m==0)
709 : {
710 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
711 : }
712 : if(owns_lock())
713 : {
714 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
715 : }
716 : is_locked=m->try_lock_shared_until(abs_time);
717 : return is_locked;
718 : }
719 : #endif
720 : void unlock()
721 : {
722 : if(m==0)
723 : {
724 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
725 : }
726 : if(!owns_lock())
727 : {
728 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock doesn't own the mutex"));
729 : }
730 : m->unlock_shared();
731 : is_locked=false;
732 : }
733 :
734 : #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
735 : typedef void (shared_lock<Mutex>::*bool_type)();
736 : operator bool_type() const BOOST_NOEXCEPT
737 : {
738 : return is_locked?&shared_lock::lock:0;
739 : }
740 : bool operator!() const BOOST_NOEXCEPT
741 : {
742 : return !owns_lock();
743 : }
744 : #else
745 : explicit operator bool() const BOOST_NOEXCEPT
746 : {
747 : return owns_lock();
748 : }
749 : #endif
750 : bool owns_lock() const BOOST_NOEXCEPT
751 : {
752 : return is_locked;
753 : }
754 :
755 : };
756 :
757 : BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
758 :
759 : template<typename Mutex>
760 : void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT
761 : {
762 : lhs.swap(rhs);
763 : }
764 :
765 : template <typename Mutex>
766 : class upgrade_lock
767 : {
768 : protected:
769 : Mutex* m;
770 : bool is_locked;
771 :
772 : public:
773 : typedef Mutex mutex_type;
774 : BOOST_THREAD_MOVABLE_ONLY( upgrade_lock)
775 :
776 : upgrade_lock()BOOST_NOEXCEPT:
777 : m(0),is_locked(false)
778 : {}
779 :
780 : explicit upgrade_lock(Mutex& m_) :
781 : m(&m_), is_locked(false)
782 : {
783 : lock();
784 : }
785 : upgrade_lock(Mutex& m_, adopt_lock_t) :
786 : m(&m_), is_locked(true)
787 : {
788 : #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
789 : BOOST_ASSERT(is_locked_by_this_thread(m));
790 : #endif
791 : }
792 : upgrade_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
793 : m(&m_),is_locked(false)
794 : {}
795 : upgrade_lock(Mutex& m_, try_to_lock_t) :
796 : m(&m_), is_locked(false)
797 : {
798 : try_lock();
799 : }
800 :
801 : #ifdef BOOST_THREAD_USES_CHRONO
802 : template <class Clock, class Duration>
803 : upgrade_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
804 : : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t))
805 : {
806 : }
807 : template <class Rep, class Period>
808 : upgrade_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
809 : : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d))
810 : {
811 : }
812 : #endif
813 :
814 : upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
815 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
816 : {
817 : BOOST_THREAD_RV(other).is_locked=false;
818 : BOOST_THREAD_RV(other).m=0;
819 : }
820 :
821 : BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
822 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
823 : {
824 : if(is_locked)
825 : {
826 : m->unlock_and_lock_upgrade();
827 : }
828 : BOOST_THREAD_RV(other).is_locked=false;
829 : BOOST_THREAD_RV(other).m=0;
830 : }
831 :
832 : //std-2104 unique_lock move-assignment should not be noexcept
833 : upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
834 : {
835 : upgrade_lock temp(::boost::move(other));
836 : swap(temp);
837 : return *this;
838 : }
839 :
840 : #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
841 : upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
842 : {
843 : upgrade_lock temp(::boost::move(other));
844 : swap(temp);
845 : return *this;
846 : }
847 : #endif
848 :
849 : #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
850 : // Conversion from shared locking
851 : upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
852 : : m(0),is_locked(false)
853 : {
854 : if (BOOST_THREAD_RV(sl).owns_lock())
855 : {
856 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade())
857 : {
858 : m = BOOST_THREAD_RV(sl).release();
859 : is_locked = true;
860 : }
861 : }
862 : else
863 : {
864 : m = BOOST_THREAD_RV(sl).release();
865 : }
866 : }
867 :
868 : #ifdef BOOST_THREAD_USES_CHRONO
869 : template <class Clock, class Duration>
870 : upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
871 : const chrono::time_point<Clock, Duration>& abs_time)
872 : : m(0),is_locked(false)
873 : {
874 : if (BOOST_THREAD_RV(sl).owns_lock())
875 : {
876 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time))
877 : {
878 : m = BOOST_THREAD_RV(sl).release();
879 : is_locked = true;
880 : }
881 : }
882 : else
883 : {
884 : m = BOOST_THREAD_RV(sl).release();
885 : }
886 : }
887 :
888 : template <class Rep, class Period>
889 : upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
890 : const chrono::duration<Rep, Period>& rel_time)
891 : : m(0),is_locked(false)
892 : {
893 : if (BOOST_THREAD_RV(sl).owns_lock())
894 : {
895 : if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time))
896 : {
897 : m = BOOST_THREAD_RV(sl).release();
898 : is_locked = true;
899 : }
900 : }
901 : else
902 : {
903 : m = BOOST_THREAD_RV(sl).release();
904 : }
905 : }
906 : #endif // BOOST_THREAD_USES_CHRONO
907 : #endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
908 : void swap(upgrade_lock& other)BOOST_NOEXCEPT
909 : {
910 : std::swap(m,other.m);
911 : std::swap(is_locked,other.is_locked);
912 : }
913 : Mutex* mutex() const BOOST_NOEXCEPT
914 : {
915 : return m;
916 : }
917 :
918 : Mutex* release()BOOST_NOEXCEPT
919 : {
920 : Mutex* const res=m;
921 : m=0;
922 : is_locked=false;
923 : return res;
924 : }
925 : ~upgrade_lock()
926 : {
927 : if (owns_lock())
928 : {
929 : m->unlock_upgrade();
930 : }
931 : }
932 : void lock()
933 : {
934 : if (m == 0)
935 : {
936 : boost::throw_exception(
937 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
938 : }
939 : if (owns_lock())
940 : {
941 : boost::throw_exception(
942 : boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
943 : }
944 : m->lock_upgrade();
945 : is_locked = true;
946 : }
947 : bool try_lock()
948 : {
949 : if (m == 0)
950 : {
951 : boost::throw_exception(
952 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
953 : }
954 : if (owns_lock())
955 : {
956 : boost::throw_exception(
957 : boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
958 : }
959 : is_locked = m->try_lock_upgrade();
960 : return is_locked;
961 : }
962 : void unlock()
963 : {
964 : if (m == 0)
965 : {
966 : boost::throw_exception(
967 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
968 : }
969 : if (!owns_lock())
970 : {
971 : boost::throw_exception(
972 : boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock doesn't own the mutex"));
973 : }
974 : m->unlock_upgrade();
975 : is_locked = false;
976 : }
977 : #ifdef BOOST_THREAD_USES_CHRONO
978 : template <class Rep, class Period>
979 : bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
980 : {
981 : if(m==0)
982 : {
983 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
984 : }
985 : if(owns_lock())
986 : {
987 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
988 : }
989 : is_locked=m->try_lock_upgrade_for(rel_time);
990 : return is_locked;
991 : }
992 : template <class Clock, class Duration>
993 : bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
994 : {
995 : if(m==0)
996 : {
997 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
998 : }
999 : if(owns_lock())
1000 : {
1001 : boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
1002 : }
1003 : is_locked=m->try_lock_upgrade_until(abs_time);
1004 : return is_locked;
1005 : }
1006 : #endif
1007 : #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1008 : typedef void (upgrade_lock::*bool_type)();
1009 : operator bool_type() const BOOST_NOEXCEPT
1010 : {
1011 : return is_locked?&upgrade_lock::lock:0;
1012 : }
1013 : bool operator!() const BOOST_NOEXCEPT
1014 : {
1015 : return !owns_lock();
1016 : }
1017 : #else
1018 : explicit operator bool() const BOOST_NOEXCEPT
1019 : {
1020 : return owns_lock();
1021 : }
1022 : #endif
1023 : bool owns_lock() const BOOST_NOEXCEPT
1024 : {
1025 : return is_locked;
1026 : }
1027 : friend class shared_lock<Mutex> ;
1028 : friend class unique_lock<Mutex> ;
1029 : };
1030 :
1031 : template<typename Mutex>
1032 : void swap(upgrade_lock<Mutex>& lhs, upgrade_lock<Mutex>& rhs)
1033 : BOOST_NOEXCEPT
1034 : {
1035 : lhs.swap(rhs);
1036 : }
1037 :
1038 : BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
1039 :
1040 : template<typename Mutex>
1041 : unique_lock<Mutex>::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
1042 : m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
1043 : {
1044 : if(is_locked)
1045 : {
1046 : m->unlock_upgrade_and_lock();
1047 : }
1048 : BOOST_THREAD_RV(other).release();
1049 : }
1050 :
1051 : template <class Mutex>
1052 : class upgrade_to_unique_lock
1053 : {
1054 : private:
1055 : upgrade_lock<Mutex>* source;
1056 : unique_lock<Mutex> exclusive;
1057 :
1058 : public:
1059 : typedef Mutex mutex_type;
1060 : BOOST_THREAD_MOVABLE_ONLY( upgrade_to_unique_lock)
1061 :
1062 : explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_) :
1063 : source(&m_), exclusive(::boost::move(*source))
1064 : {
1065 : }
1066 : ~upgrade_to_unique_lock()
1067 : {
1068 : if (source)
1069 : {
1070 : *source = BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex> (::boost::move(exclusive)));
1071 : }
1072 : }
1073 :
1074 : upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
1075 : source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive))
1076 : {
1077 : BOOST_THREAD_RV(other).source=0;
1078 : }
1079 :
1080 : //std-2104 unique_lock move-assignment should not be noexcept
1081 : upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
1082 : {
1083 : upgrade_to_unique_lock temp(::boost::move(other));
1084 : swap(temp);
1085 : return *this;
1086 : }
1087 :
1088 : void swap(upgrade_to_unique_lock& other)BOOST_NOEXCEPT
1089 : {
1090 : std::swap(source,other.source);
1091 : exclusive.swap(other.exclusive);
1092 : }
1093 :
1094 : #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1095 : typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
1096 : operator bool_type() const BOOST_NOEXCEPT
1097 : {
1098 : return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
1099 : }
1100 : bool operator!() const BOOST_NOEXCEPT
1101 : {
1102 : return !owns_lock();
1103 : }
1104 : #else
1105 : explicit operator bool() const BOOST_NOEXCEPT
1106 : {
1107 : return owns_lock();
1108 : }
1109 : #endif
1110 :
1111 : bool owns_lock() const BOOST_NOEXCEPT
1112 : {
1113 : return exclusive.owns_lock();
1114 : }
1115 : Mutex* mutex() const BOOST_NOEXCEPT
1116 : {
1117 : return exclusive.mutex();
1118 : }
1119 : };
1120 :
1121 : BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
1122 :
1123 : namespace detail
1124 : {
1125 : template<typename Mutex>
1126 : class try_lock_wrapper:
1127 : private unique_lock<Mutex>
1128 : {
1129 : typedef unique_lock<Mutex> base;
1130 : public:
1131 : BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper)
1132 :
1133 : try_lock_wrapper()
1134 : {}
1135 :
1136 : explicit try_lock_wrapper(Mutex& m):
1137 : base(m,try_to_lock)
1138 : {}
1139 :
1140 : try_lock_wrapper(Mutex& m_,adopt_lock_t):
1141 : base(m_,adopt_lock)
1142 : {
1143 : #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
1144 : BOOST_ASSERT(is_locked_by_this_thread(m_));
1145 : #endif
1146 : }
1147 : try_lock_wrapper(Mutex& m_,defer_lock_t):
1148 : base(m_,defer_lock)
1149 : {}
1150 : try_lock_wrapper(Mutex& m_,try_to_lock_t):
1151 : base(m_,try_to_lock)
1152 : {}
1153 : #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1154 : try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1155 : base(::boost::move(other))
1156 : {}
1157 :
1158 : #elif defined BOOST_THREAD_USES_MOVE
1159 : try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1160 : base(::boost::move(static_cast<base&>(other)))
1161 : {}
1162 :
1163 : #else
1164 : try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1165 : base(BOOST_THREAD_RV_REF(base)(*other))
1166 : {}
1167 : #endif
1168 : try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
1169 : {
1170 : try_lock_wrapper temp(::boost::move(other));
1171 : swap(temp);
1172 : return *this;
1173 : }
1174 : void swap(try_lock_wrapper& other)
1175 : {
1176 : base::swap(other);
1177 : }
1178 : void lock()
1179 : {
1180 : base::lock();
1181 : }
1182 : bool try_lock()
1183 : {
1184 : return base::try_lock();
1185 : }
1186 : void unlock()
1187 : {
1188 : base::unlock();
1189 : }
1190 : bool owns_lock() const
1191 : {
1192 : return base::owns_lock();
1193 : }
1194 : Mutex* mutex() const BOOST_NOEXCEPT
1195 : {
1196 : return base::mutex();
1197 : }
1198 : Mutex* release()
1199 : {
1200 : return base::release();
1201 : }
1202 :
1203 : #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1204 : typedef typename base::bool_type bool_type;
1205 : operator bool_type() const
1206 : {
1207 : return base::operator bool_type();
1208 : }
1209 : bool operator!() const
1210 : {
1211 : return !this->owns_lock();
1212 : }
1213 : #else
1214 : explicit operator bool() const
1215 : {
1216 : return owns_lock();
1217 : }
1218 : #endif
1219 : };
1220 :
1221 : template<typename Mutex>
1222 : void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
1223 : {
1224 : lhs.swap(rhs);
1225 : }
1226 : }
1227 : }
1228 : #include <boost/config/abi_suffix.hpp>
1229 :
1230 : #endif
|