1[/
2  (C) Copyright 2007-8 Anthony Williams.
3  (C) Copyright 2011-12 Vicente J. Botet Escriba.
4  Distributed under the Boost Software License, Version 1.0.
5  (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7]
8
9[section:mutex_concepts Mutex Concepts]
10
11A mutex object facilitates protection against data races and allows thread-safe synchronization of data between threads. A thread
12obtains ownership of a mutex object by calling one of the lock functions and relinquishes ownership by calling the corresponding
13unlock function. Mutexes may be either recursive or non-recursive, and may grant simultaneous ownership to one or many
14threads. __boost_thread__ supplies recursive and non-recursive mutexes with exclusive ownership semantics, along with a shared
15ownership (multiple-reader / single-writer) mutex.
16
17__boost_thread__ supports four basic concepts for lockable objects: __lockable_concept_type__, __timed_lockable_concept_type__,
18__shared_lockable_concept_type__ and __upgrade_lockable_concept_type__. Each mutex type implements one or more of these concepts, as
19do the various lock types.
20
21[section:basic_lockable `BasicLockable` Concept]
22
23  // #include <boost/thread/lockable_concepts.hpp>
24
25  namespace boost
26  {
27
28    template<typename L>
29    class BasicLockable; // EXTENSION
30  }
31
32
33The __BasicLockable concept models exclusive ownership.
34A type `L` meets the __BasicLockable requirements if the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`):
35
36* `m.__lock();`
37* `m.__unlock();`
38
39Lock ownership acquired through a call to __lock_ref__ must be released through a call to __unlock_ref__.
40
41[section:lock `m.lock();`]
42
43[variablelist
44
45[[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]]
46
47[[Effects:] [The current thread blocks until ownership can be obtained for the current thread.]]
48
49[[Synchronization:] [Prior `unlock()` operations on the same object synchronizes with this operation. ]]
50
51[[Postcondition:] [The current thread owns `m`.]]
52
53[[Return type:] [`void`.]]
54
55[[Throws:] [__lock_error__ if an error occurs.]]
56
57[[Error Conditions:] [
58
59[*operation_not_permitted]: if the thread does not have the privilege to perform the operation.
60
61[*resource_deadlock_would_occur]:  if the implementation detects that a deadlock would occur.
62
63[*device_or_resource_busy]: if the mutex is already locked and blocking is not possible.
64
65]]
66
67[[Thread safety:] [If an exception is thrown then a lock shall not have been acquired for the current thread.]]
68
69]
70[endsect]
71
72[section:unlock `m.unlock();`]
73
74[variablelist
75
76[[Requires:] [The current thread owns `m`.]]
77
78[[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership on the same object.]]
79
80[[Effects:] [Releases a lock on `m` by the current thread.]]
81
82[[Return type:] [`void`.]]
83
84[[Throws:] [Nothing.]]
85]
86[endsect]
87
88
89[section:is_basic_lockable `is_basic_lockable` trait -- EXTENSION]
90
91  // #include <boost/thread/lockable_traits.hpp>
92
93  namespace boost
94  {
95    namespace sync
96    {
97      template<typename L>
98      class is_basic_lockable;// EXTENSION
99    }
100  }
101
102
103Some of the algorithms on mutexes use this trait via SFINAE.
104
105This trait is true_type if the parameter L meets the __Lockable requirements.
106
107[warning If BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES is defined you will need to specialize this traits for the models of BasicLockable you could build.]
108
109[endsect]
110[endsect]
111
112[section:lockable `Lockable` Concept]
113
114  // #include <boost/thread/lockable_concepts.hpp>
115  namespace boost
116  {
117    template<typename L>
118    class Lockable;
119  }
120
121A type `L` meets the __Lockable requirements if it meets the __BasicLockable requirements and the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`):
122
123* `m.__try_lock()`
124
125Lock ownership acquired through a call to __try_lock_ref__ must be released through a call to __unlock_ref__.
126
127[section:try_lock `m.try_lock()`]
128
129[variablelist
130
131
132[[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]]
133
134[[Effects:] [Attempt to obtain ownership for the current thread without blocking.]]
135
136[[Synchronization:] [If `try_lock()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]]
137
138[[Note:] [Since `lock()` does not synchronize with a failed subsequent
139`try_lock()`, the visibility rules are weak enough that little would be known about the state after a
140failure, even in the absence of spurious failures.]]
141
142[[Return type:] [`bool`.]]
143
144[[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]]
145
146[[Postcondition:] [If the call returns `true`, the current thread owns the `m`.]]
147
148[[Throws:] [Nothing.]]
149
150]
151[endsect]
152
153[section:is_lockable `is_lockable` trait -- EXTENSION]
154
155  // #include <boost/thread/lockable_traits.hpp>
156  namespace boost
157  {
158    namespace sync
159    {
160      template<typename L>
161      class is_lockable;// EXTENSION
162    }
163  }
164
165Some of the algorithms on mutexes use this trait via SFINAE.
166
167This trait is true_type if the parameter L meets the __Lockable requirements.
168
169[warning If BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES is defined you will need to specialize this traits for the models of Lockable you could build.]
170
171[endsect]
172[endsect]
173
174[section:recursive Recursive Lockable Concept]
175
176The user could require that the mutex passed to an algorithm is a recursive one. Whether a lockable is recursive or not can not be checked using template meta-programming. This is the motivation for the following trait.
177
178
179[section:is_recursive_mutex_sur_parole `is_recursive_mutex_sur_parole` trait -- EXTENSION]
180
181  // #include <boost/thread/lockable_traits.hpp>
182
183  namespace boost
184  {
185    namespace sync
186    {
187      template<typename L>
188      class is_recursive_mutex_sur_parole: false_type; // EXTENSION
189      template<>
190      class is_recursive_mutex_sur_parole<recursive_mutex>: true_type; // EXTENSION
191      template<>
192      class is_recursive_mutex_sur_parole<timed_recursive_mutex>: true_type; // EXTENSION
193    }
194  }
195
196The trait `is_recursive_mutex_sur_parole` is `false_type` by default and is specialized for the provide `recursive_mutex` and `timed_recursive_mutex`.
197
198It should be specialized by the user providing other model of recursive lockable.
199
200[endsect]
201
202[section:is_recursive_basic_lockable `is_recursive_basic_lockable` trait -- EXTENSION]
203
204  // #include <boost/thread/lockable_traits.hpp>
205  namespace boost
206  {
207    namespace sync
208    {
209      template<typename L>
210      class is_recursive_basic_lockable;// EXTENSION
211    }
212  }
213
214This traits is true_type if is_basic_lockable and is_recursive_mutex_sur_parole.
215
216[endsect]
217[section:is_recursive_lockable `is_recursive_lockable` trait -- EXTENSION]
218
219  // #include <boost/thread/lockable_traits.hpp>
220  namespace boost
221  {
222    namespace sync
223    {
224      template<typename L>
225      class is_recursive_lockable;// EXTENSION
226    }
227  }
228
229This traits is true_type if is_lockable and is_recursive_mutex_sur_parole.
230
231[endsect]
232
233[endsect]
234
235
236[section:timed_lockable `TimedLockable` Concept]
237
238  // #include <boost/thread/lockable_concepts.hpp>
239
240  namespace boost
241  {
242    template<typename L>
243    class TimedLockable; // EXTENSION
244  }
245
246The __timed_lockable_concept__ refines the __lockable_concept__ to add support for
247timeouts when trying to acquire the lock.
248
249A type `L` meets the __TimedLockable requirements if it meets the __Lockable requirements and the following expressions are well-formed and have the specified semantics.
250
251[*Variables:]
252
253* `m` denotes a value of type `L`,
254* `rel_time` denotes a value of an instantiation of `chrono::duration`, and
255* `abs_time` denotes a value of an instantiation of `chrono::time_point`:
256
257[*Expressions:]
258
259* `m.__try_lock_for(rel_time)`
260* `m.__try_lock_until(abs_time)`
261
262Lock ownership acquired through a call to __try_lock_for or __try_lock_until must be released through a call to __unlock.
263
264[section:try_lock_until `m.try_lock_until(abs_time)`]
265
266[variablelist
267
268[[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]]
269
270[[Effects:] [Attempt to obtain ownership for the current thread. Blocks until ownership can be obtained, or the specified time is
271reached. If the specified time has already passed, behaves as __try_lock_ref__.]]
272
273[[Synchronization:] [If `try_lock_until()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]]
274
275[[Return type:] [`bool`.]]
276
277[[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]]
278
279[[Postcondition:] [If the call returns `true`, the current thread owns `m`.]]
280
281[[Throws:] [Nothing.]]
282]
283[endsect]
284
285[section:try_lock_for `m.try_lock_for(rel_time)`]
286
287[variablelist
288
289[[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]]
290
291[[Effects:] [As-if `__try_lock_until(chrono::steady_clock::now() + rel_time)`.]]
292
293[[Synchronization:] [If `try_lock_for()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]]
294
295]
296[endsect]
297
298[warning
299DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated.
300
301Use instead __try_lock_for, __try_lock_until.
302]
303
304
305[*Variables:]
306
307* `rel_time` denotes a value of an instantiation of an unspecified `DurationType` arithmetic compatible with `boost::system_time`, and
308* `abs_time` denotes a value of an instantiation of `boost::system_time`:
309
310[*Expressions:]
311
312* `m.__timed_lock_duration(rel_time)`
313* `m.__timed_lock(abs_time)`
314
315Lock ownership acquired through a call to __timed_lock_ref__ must be released through a call to __unlock_ref__.
316
317[section:timed_lock `m.timed_lock(abs_time)`]
318
319[variablelist
320
321[[Effects:] [Attempt to obtain ownership for the current thread. Blocks until ownership can be obtained, or the specified time is
322reached. If the specified time has already passed, behaves as __try_lock_ref__.]]
323
324[[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]]
325
326[[Postcondition:] [If the call returns `true`, the current thread owns `m`.]]
327
328[[Throws:] [__lock_error__ if an error occurs.]]
329]
330[endsect]
331
332[section:timed_lock_duration `m.timed_lock(rel_time)`]
333
334[variablelist
335
336[[Effects:] [As-if [timed_lock_ref_link
337`timed_lock(boost::get_system_time()+rel_time)`].]]
338
339]
340[endsect]
341
342
343[endsect]
344
345[section:shared_lockable `SharedLockable` Concept -- C++14]
346
347  // #include <boost/thread/lockable_concepts.hpp>
348
349  namespace boost
350  {
351    template<typename L>
352    class SharedLockable;  // C++14
353  }
354
355
356The __shared_lockable_concept__ is a refinement of the __timed_lockable_concept__ that
357allows for ['shared ownership] as well as ['exclusive ownership]. This is the
358standard multiple-reader / single-write model: at most one thread can have
359exclusive ownership, and if any thread does have exclusive ownership, no other threads
360can have shared or exclusive ownership. Alternatively, many threads may have
361shared ownership.
362
363A type `L` meets the __SharedLockable requirements if it meets the __TimedLockable requirements and the following expressions are well-formed and have the specified semantics.
364
365[*Variables:]
366
367* `m` denotes a value of type `L`,
368* `rel_time` denotes a value of an instantiation of `chrono::duration`, and
369* `abs_time` denotes a value of an instantiation of `chrono::time_point`:
370
371[*Expressions:]
372
373* `m.__lock_shared();`
374* `m.__try_lock_shared()`
375* `m.__try_lock_shared_for(rel_time)`
376* `m.__try_lock_shared_until(abs_time)`
377* `m.__unlock_shared();`
378
379Lock ownership acquired through a call to __lock_shared_ref__, __try_lock_shared_ref__, __try_lock_shared_for or __try_lock_shared_until must be released through a call to __unlock_shared_ref__.
380
381[section:lock_shared `m.lock_shared()`]
382
383[variablelist
384
385[[Effects:] [The current thread blocks until shared ownership can be obtained for the current thread.]]
386
387[[Postcondition:] [The current thread has shared ownership of `m`.]]
388
389[[Throws:] [__lock_error__ if an error occurs.]]
390
391]
392[endsect]
393
394[section:try_lock_shared `m.try_lock_shared()`]
395
396[variablelist
397
398[[Effects:] [Attempt to obtain shared ownership for the current thread without blocking.]]
399
400[[Returns:] [`true` if shared ownership was obtained for the current thread, `false` otherwise.]]
401
402[[Postcondition:] [If the call returns `true`, the current thread has shared ownership of `m`.]]
403
404[[Throws:] [__lock_error__ if an error occurs.]]
405
406]
407[endsect]
408
409[section:try_lock_shared_for `m.try_lock_shared_for(rel_time)`]
410
411[variablelist
412
413[[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the
414specified duration is elapsed. If the specified duration is already elapsed, behaves as __try_lock_shared_ref__.]]
415
416[[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]]
417
418[[Postcondition:] [If the call returns `true`, the current thread has shared
419ownership of `m`.]]
420
421[[Throws:] [__lock_error__ if an error occurs.]]
422
423]
424[endsect]
425
426[section:try_lock_shared_until `m.try_lock_shared_until(abs_time))`]
427
428[variablelist
429
430[[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the
431specified time is reached. If the specified time has already passed, behaves as __try_lock_shared_ref__.]]
432
433[[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]]
434
435[[Postcondition:] [If the call returns `true`, the current thread has shared
436ownership of `m`.]]
437
438[[Throws:] [__lock_error__ if an error occurs.]]
439
440]
441[endsect]
442
443[section:unlock_shared `m.unlock_shared()`]
444
445[variablelist
446
447[[Precondition:] [The current thread has shared ownership of `m`.]]
448
449[[Effects:] [Releases shared ownership of `m` by the current thread.]]
450
451[[Postcondition:] [The current thread no longer has shared ownership of `m`.]]
452
453[[Throws:] [Nothing]]
454
455]
456[endsect]
457
458[warning
459DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated.
460
461Use instead __try_lock_shared_for, __try_lock_shared_until.
462]
463
464[*Variables:]
465
466* `abs_time` denotes a value of an instantiation of `boost::system_time`:
467
468[*Expressions:]
469
470* `m.timed_lock_shared(abs_time);`
471
472Lock ownership acquired through a call to __timed_lock_shared_ref__ must be released through a call to __unlock_shared_ref__.
473
474[section:timed_lock_shared `m.timed_lock_shared(abs_time)`]
475
476[variablelist
477
478[[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the
479specified time is reached. If the specified time has already passed, behaves as __try_lock_shared_ref__.]]
480
481[[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]]
482
483[[Postcondition:] [If the call returns `true`, the current thread has shared
484ownership of `m`.]]
485
486[[Throws:] [__lock_error__ if an error occurs.]]
487
488]
489[endsect]
490
491
492
493[endsect]
494
495[section:upgrade_lockable `UpgradeLockable` Concept -- EXTENSION]
496
497  // #include <boost/thread/lockable_concepts.hpp>
498
499  namespace boost
500  {
501    template<typename L>
502    class UpgradeLockable; // EXTENSION
503  }
504
505
506The __upgrade_lockable_concept__ is a refinement of the __shared_lockable_concept__ that allows for ['upgradable ownership] as well
507as ['shared ownership] and ['exclusive ownership]. This is an extension to the multiple-reader / single-write model provided by the
508__shared_lockable_concept__: a single thread may have ['upgradable ownership] at the same time as others have ['shared
509ownership]. The thread with ['upgradable ownership] may at any time attempt to upgrade that ownership to ['exclusive ownership]. If
510no other threads have shared ownership, the upgrade is completed immediately, and the thread now has ['exclusive ownership], which
511must be relinquished by a call to __unlock_ref__, just as if it had been acquired by a call to __lock_ref__.
512
513If a thread with ['upgradable ownership] tries to upgrade whilst other threads have ['shared ownership], the attempt will fail and
514the thread will block until ['exclusive ownership] can be acquired.
515
516Ownership can also be ['downgraded] as well as ['upgraded]: exclusive ownership of an implementation of the
517__upgrade_lockable_concept__ can be downgraded to upgradable ownership or shared ownership, and upgradable ownership can be
518downgraded to plain shared ownership.
519
520A type `L` meets the __UpgradeLockable requirements if it meets the __SharedLockable
521requirements and the following expressions are well-formed and have the specified semantics.
522
523[*Variables:]
524
525* `m` denotes a value of type `L`,
526* `rel_time` denotes a value of an instantiation of `chrono::duration`, and
527* `abs_time` denotes a value of an instantiation of `chrono::time_point`:
528
529[*Expressions:]
530
531* `m.__lock_upgrade();`
532* `m.__unlock_upgrade()`
533* `m.__try_lock_upgrade()`
534* `m.__try_lock_upgrade_for(rel_time)`
535* `m.__try_lock_upgrade_until(abs_time)`
536* `m.__unlock_and_lock_shared()`
537* `m.__unlock_and_lock_upgrade();`
538* `m.__unlock_upgrade_and_lock();`
539* `m.__try_unlock_upgrade_and_lock()`
540* `m.__try_unlock_upgrade_and_lock_for(rel_time)`
541* `m.__try_unlock_upgrade_and_lock_until(abs_time)`
542* `m.__unlock_upgrade_and_lock_shared();`
543
544
545If `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS is defined the following expressions are also required:
546
547* `m.__try_unlock_shared_and_lock();`
548* `m.__try_unlock_shared_and_lock_for(rel_time);`
549* `m.__try_unlock_shared_and_lock_until(abs_time);`
550* `m.__try_unlock_shared_and_lock_upgrade();`
551* `m.__try_unlock_shared_and_lock_upgrade_for(rel_time);`
552* `m.__try_unlock_shared_and_lock_upgrade_until(abs_time);`
553
554
555Lock ownership acquired through a call to __lock_upgrade_ref__ must be released through a call to __unlock_upgrade_ref__. If the
556ownership type is changed through a call to one of the `unlock_xxx_and_lock_yyy()` functions, ownership must be released through a
557call to the unlock function corresponding to the new level of ownership.
558
559
560[section:lock_upgrade `m.lock_upgrade()`]
561
562[variablelist
563
564[[Precondition:] [The calling thread has no ownership of the mutex. ]]
565
566[[Effects:] [The current thread blocks until upgrade ownership can be obtained for the current thread.]]
567
568[[Postcondition:] [The current thread has upgrade ownership of `m`.]]
569
570[[Synchronization:] [Prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]]
571
572[[Throws:] [__lock_error__ if an error occurs.]]
573
574]
575[endsect]
576
577[section:unlock_upgrade `m.unlock_upgrade()`]
578
579[variablelist
580
581[[Precondition:] [The current thread has upgrade ownership of `m`.]]
582
583[[Effects:] [Releases upgrade ownership of `m` by the current thread.]]
584
585[[Postcondition:] [The current thread no longer has upgrade ownership of `m`.]]
586
587[[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership on the same object.]]
588
589[[Throws:] [Nothing]]
590
591]
592[endsect]
593
594[section:try_lock_upgrade `m.try_lock_upgrade()`]
595
596[variablelist
597
598[[Precondition:] [The calling thread has no ownership of the mutex. ]]
599
600[[Effects:] [Attempts to obtain upgrade ownership of the mutex for the calling thread without blocking. If upgrade ownership is not obtained, there is no effect and try_lock_upgrade() immediately returns.]]
601
602[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
603
604[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
605
606[[Synchronization:] [If `__try_lock_upgrade()` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]]
607
608[[Throws:] [Nothing]]
609
610]
611[endsect]
612
613
614[section:try_lock_upgrade_for `m.try_lock_upgrade_for(rel_time)`]
615
616[variablelist
617
618[[Precondition:] [The calling thread has no ownership of the mutex. ]]
619
620[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
621Attempts to obtain upgrade lock ownership for the calling thread within the relative timeout specified by `rel_time`.
622If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain ownership without blocking (as if by calling `__try_lock_upgrade()`).
623The function returns within the timeout specified by `rel_time` only if it has obtained upgrade ownership of the mutex object.]]
624
625[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
626
627[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
628
629[[Synchronization:] [If `__try_lock_upgrade_for(rel_time)` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]]
630
631[[Throws:] [Nothing]]
632
633[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
634
635]
636[endsect]
637
638[section:try_lock_upgrade_until `m.try_lock_upgrade_until(abs_time)`]
639
640[variablelist
641
642[[Precondition:] [The calling thread has no ownership of the mutex. ]]
643
644[[Effects:] [The function attempts to obtain upgrade ownership of the mutex.
645If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_lock_upgrade()`).
646The function returns before the absolute timeout specified by `abs_time` only if it has obtained upgrade ownership of the mutex object.]]
647
648[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
649
650[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
651
652[[Synchronization:] [If `__try_lock_upgrade_until(abs_time)` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]]
653
654[[Throws:] [Nothing]]
655
656[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
657
658]
659[endsect]
660
661
662[section:try_unlock_shared_and_lock `m.try_unlock_shared_and_lock()`]
663
664[variablelist
665
666[[Precondition:] [The calling thread must hold a shared lock on the mutex.]]
667
668[[Effects:] [The function attempts to atomically convert the ownership from shared to exclusive for the calling thread without blocking.
669For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
670If the conversion is not successful, the shared ownership of m is retained.]]
671
672[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
673
674[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
675
676[[Synchronization:] [If `__try_unlock_shared_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
677
678
679[[Throws:] [Nothing]]
680
681[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
682
683]
684[endsect]
685
686[section:try_unlock_shared_and_lock_for `m.try_unlock_shared_and_lock_for(rel_time)`]
687
688[variablelist
689
690[[Precondition:] [The calling thread shall hold a shared lock on the mutex.]]
691
692[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
693The function attempts to atomically convert the ownership from shared to exclusive for the calling thread within the relative timeout specified by `rel_time`.
694If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain exclusive ownership without blocking (as if by calling `try_unlock_shared_and_lock()`).
695The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
696For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion.
697If the conversion is not successful, the shared ownership of the mutex is retained.]]
698
699[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
700
701[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
702
703[[Synchronization:] [If `__try_unlock_shared_and_lock_for(rel_time)` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
704
705[[Throws:] [Nothing]]
706
707[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
708
709]
710[endsect]
711
712
713[section:try_unlock_shared_and_lock_until `m.try_unlock_shared_and_lock_until(abs_time)`]
714
715[variablelist
716
717[[Precondition:] [The calling thread shall hold a shared lock on the mutex.]]
718
719[[Effects:] [The function attempts to atomically convert the ownership from shared to exclusive for the calling thread within the absolute timeout specified by `abs_time`.
720If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `try_unlock_shared_and_lock()`).
721The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object.
722For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion.
723If the conversion is not successful, the shared ownership of the mutex is retained.]]
724
725[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
726
727[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
728
729[[Synchronization:] [If `__try_unlock_shared_and_lock_until(rel_time)` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
730
731[[Throws:] [Nothing]]
732
733[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
734
735]
736[endsect]
737
738[section:unlock_and_lock_shared `m.unlock_and_lock_shared()`]
739
740[variablelist
741
742[[Precondition:] [The calling thread shall hold an exclusive lock on `m`.]]
743
744[[Effects:] [Atomically converts the ownership from exclusive to shared for the calling thread.]]
745
746[[Postcondition:] [The current thread has shared ownership of `m`.]]
747
748[[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership of the same object.]]
749
750[[Throws:] [Nothing]]
751
752]
753[endsect]
754
755[section:try_unlock_shared_and_lock_upgrade `m.try_unlock_shared_and_lock_upgrade()`]
756
757[variablelist
758
759[[Precondition:] [The calling thread shall hold a shared lock on the mutex.]]
760
761[[Effects:] [The function attempts to atomically convert the ownership from shared to upgrade for the calling thread without blocking.
762For this conversion to be successful, there must be no thread holding upgrade ownership of this object.
763If the conversion is not successful, the shared ownership of the mutex is retained.]]
764
765[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
766
767[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
768
769[[Synchronization:] [If `__try_unlock_shared_and_lock_upgrade()` returns true, prior `__unlock_upgrade()` and subsequent lock operations on the same object synchronize with this operation. ]]
770
771[[Throws:] [Nothing]]
772
773[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
774
775]
776[endsect]
777
778
779[section:try_unlock_shared_and_lock_upgrade_for `m.try_unlock_shared_and_lock_upgrade_for(rel_time)`]
780
781[variablelist
782
783[[Precondition:] [The calling thread shall hold a shared lock on the mutex.]]
784
785[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
786The function attempts to atomically convert the ownership from shared to upgrade for the calling thread within the relative timeout specified by `rel_time`.
787If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_unlock_shared_and_lock_upgrade()`).
788The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
789For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion.
790If the conversion is not successful, the shared ownership of m is retained.]]
791
792[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
793
794[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
795
796[[Synchronization:] [If `__try_unlock_shared_and_lock_upgrade_for(rel_time)` returns true, prior `__unlock_upgrade()` and subsequent lock operations on the same object synchronize with this operation. ]]
797
798[[Throws:] [Nothing]]
799
800[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
801
802
803]
804[endsect]
805
806[section:try_unlock_shared_and_lock_upgrade_until `m.try_unlock_shared_and_lock_upgrade_until(abs_time)`]
807
808[variablelist
809
810[[Precondition:] [The calling thread shall hold a shared lock on the mutex.]]
811
812[[Effects:] [The function attempts to atomically convert the ownership from shared to upgrade for the calling thread within the absolute timeout specified by `abs_time`.
813If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_unlock_shared_and_lock_upgrade()`).
814The function shall return before the absolute timeout specified by `abs_time` only if it has obtained upgrade ownership of the mutex object.
815For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion.
816If the conversion is not successful, the shared ownership of the mutex is retained.]]
817
818[[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]]
819
820[[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]]
821
822[[Synchronization:] [If `__try_unlock_shared_and_lock_upgrade_until(rel_time)` returns true, prior `__unlock_upgrade()` and subsequent lock operations on the same object synchronize with this operation. ]]
823
824[[Throws:] [Nothing]]
825
826[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
827
828]
829[endsect]
830
831[section:unlock_and_lock_upgrade `m.unlock_and_lock_upgrade()`]
832
833[variablelist
834
835[[Precondition:] [The current thread has exclusive ownership of `m`.]]
836
837[[Effects:] [Atomically releases exclusive ownership of `m` by the current thread and acquires upgrade ownership of `m`
838without blocking.]]
839
840[[Postcondition:] [The current thread has upgrade ownership of `m`.]]
841
842[[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership of the same object.]]
843
844[[Throws:] [Nothing]]
845
846]
847[endsect]
848
849
850[section:unlock_upgrade_and_lock `m.unlock_upgrade_and_lock()`]
851
852[variablelist
853
854[[Precondition:] [The current thread has upgrade ownership of `m`.]]
855
856[[Effects:] [Atomically releases upgrade ownership of `m` by the current thread and acquires exclusive ownership of `m`. If
857any other threads have shared ownership, blocks until exclusive ownership can be acquired.]]
858
859[[Postcondition:] [The current thread has exclusive ownership of `m`.]]
860
861[[Synchronization:] [This operation synchronizes with prior `__unlock_shared()` and subsequent lock operations that obtain ownership of the same object.]]
862
863[[Throws:] [Nothing]]
864
865]
866[endsect]
867
868[section:try_unlock_upgrade_and_lock `m.try_unlock_upgrade_and_lock()`]
869
870[variablelist
871
872[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
873
874[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread without blocking.
875For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
876If the conversion is not successful, the upgrade ownership of m is retained.]]
877
878[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
879
880[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
881
882[[Synchronization:] [If `__try_unlock_upgrade_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
883
884[[Throws:] [Nothing]]
885
886[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
887
888
889]
890[endsect]
891
892[section:try_unlock_upgrade_and_lock_for `m.try_unlock_upgrade_and_lock_for(rel_time)`]
893
894[variablelist
895
896[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
897
898[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
899The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the relative timeout specified by `rel_time`.
900If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`).
901The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
902For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion.
903If the conversion is not successful, the upgrade ownership of m is retained.]]
904
905[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
906
907[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
908
909[[Synchronization:] [If `__try_unlock_upgrade_and_lock_for(rel_time)` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
910
911[[Throws:] [Nothing]]
912
913[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
914
915]
916[endsect]
917
918[section:try_unlock_upgrade_and_lock_until `m.try_unlock_upgrade_and_lock_until(abs_time)`]
919
920[variablelist
921
922[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
923
924[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the absolute timeout specified by `abs_time`.
925If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`).
926The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object.
927For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion.
928If the conversion is not successful, the upgrade ownership of m is retained.]]
929
930[[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]]
931
932[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
933
934[[Synchronization:] [If `__try_unlock_upgrade_and_lock_for(rel_time)` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
935
936[[Throws:] [Nothing]]
937
938[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
939
940]
941[endsect]
942
943
944[section:unlock_upgrade_and_lock_shared `m.unlock_upgrade_and_lock_shared()`]
945
946[variablelist
947
948[[Precondition:] [The current thread has upgrade ownership of `m`.]]
949
950[[Effects:] [Atomically releases upgrade ownership of `m` by the current thread and acquires shared ownership of `m` without
951blocking.]]
952
953[[Postcondition:] [The current thread has shared ownership of `m`.]]
954
955[[Synchronization:] [This operation synchronizes with prior `unlock_shared()` and subsequent lock operations that obtain ownership of the same object.]]
956
957[[Throws:] [Nothing]]
958
959]
960[endsect]
961
962[endsect]
963
964[endsect]
965
966[section:lock_option Lock Options]
967
968  // #include <boost/thread/locks.hpp>
969  // #include <boost/thread/locks_options.hpp>
970
971  namespace boost
972  {
973    struct defer_lock_t {};
974    struct try_to_lock_t {};
975    struct adopt_lock_t {};
976    constexpr defer_lock_t defer_lock;
977    constexpr try_to_lock_t try_to_lock;
978    constexpr adopt_lock_t adopt_lock;
979
980[section:lock_tags Lock option tags]
981
982  #include <boost/thread/locks.hpp>
983  #include <boost/thread/locks_options.hpp>
984
985  struct defer_lock_t {};
986  struct try_to_lock_t {};
987  struct adopt_lock_t {};
988  const defer_lock_t defer_lock;
989  const try_to_lock_t try_to_lock;
990  const adopt_lock_t adopt_lock;
991
992These tags are used in scoped locks constructors to specify a specific behavior.
993
994*`defer_lock_t`: is used to construct the scoped lock without locking it.
995*`try_to_lock_t`: is used to construct the scoped lock trying to lock it.
996*`adopt_lock_t`: is used to construct the scoped lock without locking it but adopting ownership.
997
998[endsect]
999
1000[endsect]
1001
1002[section:lock_guard Lock Guard]
1003
1004  // #include <boost/thread/locks.hpp>
1005  // #include <boost/thread/lock_guard.hpp>
1006
1007  namespace boost
1008  {
1009
1010    template<typename Lockable>
1011    class lock_guard
1012  #if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
1013    template <typename Lockable>
1014    lock_guard<Lockable> make_lock_guard(Lockable& mtx); // EXTENSION
1015    template <typename Lockable>
1016    lock_guard<Lockable> make_lock_guard(Lockable& mtx, adopt_lock_t); // EXTENSION
1017  #endif
1018  }
1019
1020[section:lock_guard Class template `lock_guard`]
1021
1022    // #include <boost/thread/locks.hpp>
1023    // #include <boost/thread/lock_guard.hpp>
1024
1025    template<typename Lockable>
1026    class lock_guard
1027    {
1028    public:
1029        explicit lock_guard(Lockable& m_);
1030        lock_guard(Lockable& m_,boost::adopt_lock_t);
1031
1032        ~lock_guard();
1033    };
1034
1035__lock_guard__ is very simple: on construction it
1036acquires ownership of the implementation of the __lockable_concept__ supplied as
1037the constructor parameter. On destruction, the ownership is released. This
1038provides simple RAII-style locking of a __lockable_concept_type__ object, to facilitate exception-safe
1039locking and unlocking. In addition, the [link
1040thread.synchronization.lock_guard.lock_guard.constructor_adopt `lock_guard(Lockable &
1041m,boost::adopt_lock_t)` constructor] allows the __lock_guard__ object to
1042take ownership of a lock already held by the current thread.
1043
1044[section:constructor `lock_guard(Lockable & m)`]
1045
1046[variablelist
1047
1048[[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]]
1049
1050[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
1051
1052]
1053
1054[endsect]
1055
1056[section:constructor_adopt `lock_guard(Lockable & m,boost::adopt_lock_t)`]
1057
1058[variablelist
1059
1060[[Precondition:] [The current thread owns a lock on `m` equivalent to one
1061obtained by a call to [lock_ref_link `m.lock()`].]]
1062
1063[[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of
1064`m`.]]
1065
1066[[Throws:] [Nothing.]]
1067
1068]
1069
1070[endsect]
1071
1072[section:destructor `~lock_guard()`]
1073
1074[variablelist
1075
1076[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
1077object passed to the constructor.]]
1078
1079[[Throws:] [Nothing.]]
1080
1081]
1082
1083[endsect]
1084
1085[endsect]
1086
1087[section:make_lock_guard Non Member Function `make_lock_guard`]
1088
1089    template <typename Lockable>
1090    lock_guard<Lockable> make_lock_guard(Lockable& m); // EXTENSION
1091
1092
1093[variablelist
1094
1095[[Returns:] [a lock_guard as if initialized with `{m}`.]]
1096
1097[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
1098
1099]
1100
1101
1102[endsect]
1103[section:make_lock_guard_adopt Non Member Function `make_lock_guard`]
1104
1105    template <typename Lockable>
1106    lock_guard<Lockable> make_lock_guard(Lockable& m, adopt_lock_t); // EXTENSION
1107
1108
1109[variablelist
1110
1111[[Returns:] [a lock_guard as if initialized with `{m, adopt_lock}`.]]
1112
1113[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
1114
1115]
1116
1117
1118[endsect]
1119[endsect]
1120
1121
1122[section:with_lock_guard With Lock Guard]
1123
1124  // #include <boost/thread/with_lock_guard.hpp>
1125
1126  namespace boost
1127  {
1128    template <class Lockable, class Function, class... Args>
1129    auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
1130  }
1131
1132[section:with_lock_guard Non Member Function `with_lock_guard`]
1133
1134  template <class Lockable, class Function, class... Args>
1135  auto with_lock_guard(
1136      Lockable& m,
1137      Function&& func,
1138      Args&&... args
1139  ) -> decltype(func(boost::forward<Args>(args)...));
1140
1141[variablelist
1142
1143[[Precondition:] [`m` must be in unlocked state]]
1144[[Effects:] [call `func` in scope locked by `m`]]
1145[[Returns:] [Result of `func(args...)` call]]
1146[[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]]
1147[[Postcondition:] [`m` is in unlocked state]]
1148
1149[[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]]
1150[[] [Without rvalue references support calling class method with `boost::bind` must be const]]
1151[[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]]
1152
1153
1154]
1155
1156[endsect]
1157[endsect]
1158
1159[section:lock_concepts Lock Concepts]
1160[section:StrictLock StrictLock -- EXTENSION]
1161
1162  // #include <boost/thread/lock_concepts.hpp>
1163
1164  namespace boost
1165  {
1166
1167    template<typename Lock>
1168    class StrictLock;
1169  }
1170
1171
1172A StrictLock is a lock that ensures that the associated mutex is locked during the lifetime of the lock.
1173
1174A type `L` meets the StrictLock requirements if the following expressions are well-formed and have the specified semantics
1175
1176* `L::mutex_type`
1177* `is_strict_lock<L>`
1178* `cl.owns_lock(m);`
1179
1180and BasicLockable<L::mutex_type>
1181
1182where
1183
1184* `cl` denotes a value of type `L const&`,
1185* `m` denotes a value of type `L::mutex_type const*`,
1186
1187[section: mutex_type `L::mutex_type`]
1188
1189The type L::mutex_type denotes the mutex that is locked by this lock.
1190
1191[endsect] [/ mutex_type]
1192
1193[section:is_strict_lock_sur_parole `is_strict_lock_sur_parole<L>`]
1194
1195As the semantic "ensures that the associated mutex is locked during the lifetime of the lock. " can not be described by syntactic requirements a `is_strict_lock_sur_parole` trait must be specialized by the user defining the lock so that the following assertion is true:
1196
1197  is_strict_lock_sur_parole<L>::value == true
1198
1199[endsect] [/ is_strict_lock_sur_parole]
1200
1201[section:owns_lock `cl.owns_lock(m);`]
1202
1203[variablelist
1204
1205[[Return Type:] [`bool`]]
1206[[Returns:] [Whether the strict lock is locking the mutex `m`]]
1207
1208[[Throws:] [Nothing.]]
1209
1210]
1211
1212
1213[endsect] [/ owns_lock]
1214
1215[section Models]
1216
1217The following classes are models of `StrictLock`:
1218
1219* strict_lock: ensured by construction,
1220* nested_strict_lock: "sur parole" as the user could use adopt_lock_t on unique_lock constructor overload without having locked the mutex,
1221* __lock_guard__: "sur parole" as the user could use adopt_lock_t constructor overload without having locked the mutex.
1222
1223[endsect] [/ Models]
1224
1225[endsect] [/ Strict Lock]
1226
1227[endsect] [/ Lock Concepts]
1228
1229[section:locks Lock Types]
1230
1231  // #include <boost/thread/locks.hpp>
1232  // #include <boost/thread/lock_types.hpp>
1233
1234  namespace boost
1235  {
1236
1237    template<typename Lockable>
1238    class unique_lock;
1239    template<typename Mutex>
1240    void swap(unique_lock <Mutex>& lhs, unique_lock <Mutex>& rhs);
1241    template<typename Lockable>
1242    class shared_lock; // C++14
1243    template<typename Mutex>
1244    void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs); // C++14
1245    template<typename Lockable>
1246    class upgrade_lock; // EXTENSION
1247    template<typename Mutex>
1248    void swap(upgrade_lock <Mutex>& lhs, upgrade_lock <Mutex>& rhs); // EXTENSION
1249    template <class Mutex>
1250    class upgrade_to_unique_lock; // EXTENSION
1251  }
1252
1253
1254
1255[section:unique_lock Class template `unique_lock`]
1256
1257    // #include <boost/thread/locks.hpp>
1258    // #include <boost/thread/lock_types.hpp>
1259
1260    template<typename Lockable>
1261    class unique_lock
1262    {
1263    public:
1264        typedef Lockable mutex_type;
1265        unique_lock() noexcept;
1266        explicit unique_lock(Lockable& m_);
1267        unique_lock(Lockable& m_,adopt_lock_t);
1268        unique_lock(Lockable& m_,defer_lock_t) noexcept;
1269        unique_lock(Lockable& m_,try_to_lock_t);
1270
1271    #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
1272        unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t); // C++14
1273        template <class Clock, class Duration>
1274        unique_lock(shared_lock<mutex_type>&& sl,
1275                    const chrono::time_point<Clock, Duration>& abs_time); // C++14
1276        template <class Rep, class Period>
1277        unique_lock(shared_lock<mutex_type>&& sl,
1278                    const chrono::duration<Rep, Period>& rel_time); // C++14
1279    #endif
1280
1281        template <class Clock, class Duration>
1282        unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t);
1283        template <class Rep, class Period>
1284        unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d);
1285        ~unique_lock();
1286
1287        unique_lock(unique_lock const&) = delete;
1288        unique_lock& operator=(unique_lock const&) = delete;
1289        unique_lock(unique_lock<Lockable>&& other) noexcept;
1290        explicit unique_lock(upgrade_lock<Lockable>&& other) noexcept; // EXTENSION
1291
1292        unique_lock& operator=(unique_lock<Lockable>&& other) noexcept;
1293
1294        void swap(unique_lock& other) noexcept;
1295        Lockable* release() noexcept;
1296
1297        void lock();
1298        bool try_lock();
1299
1300        template <class Rep, class Period>
1301        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1302        template <class Clock, class Duration>
1303        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1304
1305        void unlock();
1306
1307        explicit operator bool() const noexcept;
1308        bool owns_lock() const noexcept;
1309
1310        mutex_type* mutex() const noexcept;
1311
1312    #if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
1313        unique_lock(Lockable& m_,system_time const& target_time);
1314        template<typename TimeDuration>
1315        bool timed_lock(TimeDuration const& relative_time);
1316        bool timed_lock(::boost::system_time const& absolute_time);
1317    #endif
1318
1319    };
1320
1321__unique_lock__ is more complex than __lock_guard__: not only does it provide for RAII-style locking, it also allows for deferring
1322acquiring the lock until the __lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking
1323fashion, or with a timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the
1324__lockable_concept_type__ object, or otherwise adopted a lock on the __lockable_concept_type__ object.
1325
1326Specializations of __unique_lock__ model the __TimedLockable concept if the supplied `Lockable` type itself models
1327__TimedLockable concept (e.g. `boost::unique_lock<boost::timed_mutex>`), or the __Lockable concept if the supplied `Lockable` type itself models
1328__Lockable concept (e.g. `boost::unique_lock<boost::mutex>`), or the __BasicLockable concept if the supplied `Lockable` type itself models
1329__BasicLockable concept.
1330
1331An instance of __unique_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1332pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1333is destroyed, then the destructor will invoke [unlock_ref_link `mutex()->unlock()`].
1334
1335The member functions of __unique_lock__ are not thread-safe. In particular, __unique_lock__ is intended to model the ownership of a
1336__lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock state
1337(including the destructor) must be called by the same thread that acquired ownership of the lock state.
1338
1339[section:defaultconstructor `unique_lock()`]
1340
1341[variablelist
1342
1343[[Effects:] [Creates a lock object with no associated mutex.]]
1344
1345[[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]]
1346
1347[[Throws:] [Nothing.]]
1348
1349]
1350
1351[endsect]
1352
1353[section:constructor `unique_lock(Lockable & m)`]
1354
1355[variablelist
1356
1357[[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]]
1358
1359[[Postcondition:] [__owns_lock_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]]
1360
1361[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
1362
1363]
1364
1365[endsect]
1366
1367[section:constructor_adopt `unique_lock(Lockable & m,boost::adopt_lock_t)`]
1368
1369[variablelist
1370
1371[[Precondition:] [The current thread owns an exclusive lock on `m`.]]
1372
1373[[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]]
1374
1375[[Postcondition:] [__owns_lock_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]]
1376
1377[[Throws:] [Nothing.]]
1378
1379]
1380
1381[endsect]
1382
1383[section:constructor_defer `unique_lock(Lockable & m,boost::defer_lock_t)`]
1384
1385[variablelist
1386
1387[[Effects:] [Stores a reference to `m`.]]
1388
1389[[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `&m`.]]
1390
1391[[Throws:] [Nothing.]]
1392
1393]
1394
1395[endsect]
1396
1397[section:constructor_try `unique_lock(Lockable & m,boost::try_to_lock_t)`]
1398
1399[variablelist
1400
1401[[Effects:] [Stores a reference to `m`. Invokes [try_lock_ref_link
1402`m.try_lock()`], and takes ownership of the lock state if the call returns
1403`true`.]]
1404
1405[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_ref__
1406returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1407returns `false`.]]
1408
1409[[Throws:] [Nothing.]]
1410
1411]
1412
1413[endsect]
1414
1415[section:constructor_sh_try `unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t)`]
1416
1417[variablelist
1418
1419[[Requires:] [The supplied `Mutex` type must implement `__try_unlock_shared_and_lock()`.]]
1420
1421[[Effects:] [Constructs an object of type __unique_lock. Let `pm` be the pointer to the mutex and `owns` the ownership state. Initializes `pm` with nullptr and `owns` with false.
1422If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
1423Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unlock_shared_and_lock()` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
1424
1425[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()->try_unlock_shared_and_lock()` returns `false`, `sl` is not modified.]]
1426
1427[[Throws:] [Nothing.]]
1428
1429[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
1430
1431]
1432
1433[endsect]
1434
1435
1436[section:constructor_sh_until `unique_lock(shared_lock<mutex_type>&&, const chrono::time_point<Clock, Duration>&)`]
1437
1438        template <class Clock, class Duration>
1439        unique_lock(shared_lock<mutex_type>&& sl,
1440                    const chrono::time_point<Clock, Duration>& abs_time);
1441
1442[variablelist
1443
1444[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_until(abs_time)`.]]
1445
1446[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
1447If `sl.__owns_lock_shared_ref__()` returns `false`, sets `pm` to the return value of `sl.release()`.
1448Else `sl.__owns_lock_shared_ref__()` returns `true`, and in this case if `sl.mutex()->__try_unlock_shared_and_lock_until(abs_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
1449
1450[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_until(abs_time)` returns `false`, `sl` is not modified.]]
1451
1452[[Throws:] [Nothing.]]
1453
1454[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
1455
1456]
1457
1458[endsect]
1459
1460[section:constructor_sh_for `unique_lock(shared_lock<mutex_type>&&, const chrono::duration<Rep, Period>&)`]
1461
1462        template <class Rep, class Period>
1463        unique_lock(shared_lock<mutex_type>&& sl,
1464                    const chrono::duration<Rep, Period>& rel_time)
1465
1466[variablelist
1467
1468[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_for(rel_time)`.]]
1469
1470[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
1471If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
1472Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
1473
1474[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `false`, `sl` is not modified.]]
1475
1476
1477[[Postcondition:] [.]]
1478
1479[[Throws:] [Nothing.]]
1480
1481[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
1482
1483]
1484
1485[endsect]
1486
1487
1488
1489
1490
1491[section:constructor_abs_time `unique_lock(Lockable & m,boost::system_time const& abs_time)`]
1492
1493[variablelist
1494
1495[[Effects:] [Stores a reference to `m`. Invokes [timed_lock_ref_link
1496`m.timed_lock(abs_time)`], and takes ownership of the lock state if the call
1497returns `true`.]]
1498
1499[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_ref__
1500returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1501returns `false`.]]
1502
1503[[Throws:] [Any exceptions thrown by the call to [timed_lock_ref_link `m.timed_lock(abs_time)`].]]
1504
1505]
1506
1507[endsect]
1508
1509[section:constructor_time_point `template <class Clock, class Duration> unique_lock(Lockable & m,const chrono::time_point<Clock, Duration>& abs_time)`]
1510
1511[variablelist
1512
1513[[Effects:] [Stores a reference to `m`. Invokes
1514`m.__try_lock_until(abs_time)`, and takes ownership of the lock state if the call
1515returns `true`.]]
1516
1517[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_until
1518returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1519returns `false`.]]
1520
1521[[Throws:] [Any exceptions thrown by the call to `m.__try_lock_until(abs_time)`.]]
1522
1523]
1524
1525[endsect]
1526
1527[section:constructor_duration `template <class Rep, class Period> unique_lock(Lockable & m,const chrono::duration<Rep, Period>& abs_time)`]
1528
1529
1530[variablelist
1531
1532[[Effects:] [Stores a reference to `m`. Invokes
1533`m.__try_lock_for(rel_time)`, and takes ownership of the lock state if the call
1534returns `true`.]]
1535
1536[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_for
1537returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1538returns `false`.]]
1539
1540[[Throws:] [Any exceptions thrown by the call to `m.__try_lock_for(rel_time)`.]]
1541
1542]
1543
1544[endsect]
1545
1546[section:destructor `~unique_lock()`]
1547
1548[variablelist
1549
1550[[Effects:] [Invokes __mutex_func_ref__`->`[unlock_ref_link `unlock()`] if
1551__owns_lock_ref__ returns `true`.]]
1552
1553[[Throws:] [Nothing.]]
1554
1555]
1556
1557[endsect]
1558
1559[section:owns_lock `bool owns_lock() const`]
1560
1561[variablelist
1562
1563[[Returns:] [`true` if the `*this` owns the lock on the __lockable_concept_type__
1564object associated with `*this`.]]
1565
1566[[Throws:] [Nothing.]]
1567
1568]
1569
1570[endsect]
1571
1572[section:mutex `Lockable* mutex() const noexcept`]
1573
1574[variablelist
1575
1576[[Returns:] [A pointer to the __lockable_concept_type__ object associated with
1577`*this`, or `NULL` if there is no such object.]]
1578
1579[[Throws:] [Nothing.]]
1580
1581]
1582
1583[endsect]
1584
1585[section:explicit_bool_conversion `explicit operator bool() const`]
1586
1587[variablelist
1588
1589[[Returns:] [`__owns_lock_ref__()`.]]
1590
1591[[Throws:] [Nothing.]]
1592
1593]
1594
1595[endsect]
1596
1597
1598[section:release `Lockable* release()`]
1599
1600[variablelist
1601
1602[[Effects:] [The association between `*this` and the __lockable_concept_type__ object is removed, without affecting the lock state
1603of the __lockable_concept_type__ object. If __owns_lock_ref__ would have returned `true`, it is the responsibility of the calling
1604code to ensure that the __lockable_concept_type__ is correctly unlocked.]]
1605
1606[[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this` at the point of the call, or `NULL` if there
1607is no such object.]]
1608
1609[[Throws:] [Nothing.]]
1610
1611[[Postcondition:] [`*this` is no longer associated with any __lockable_concept_type__ object. __mutex_func_ref__ returns `NULL` and
1612__owns_lock_ref__ returns `false`.]]
1613
1614]
1615
1616[endsect]
1617
1618[endsect]
1619
1620[section:shared_lock Class template `shared_lock` - C++14]
1621
1622    // #include <boost/thread/locks.hpp>
1623    // #include <boost/thread/lock_types.hpp>
1624
1625    template<typename Lockable>
1626    class shared_lock
1627    {
1628    public:
1629        typedef Lockable mutex_type;
1630
1631        // Shared locking
1632        shared_lock();
1633        explicit shared_lock(Lockable& m_);
1634        shared_lock(Lockable& m_,adopt_lock_t);
1635        shared_lock(Lockable& m_,defer_lock_t);
1636        shared_lock(Lockable& m_,try_to_lock_t);
1637        template <class Clock, class Duration>
1638        shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t);
1639        template <class Rep, class Period>
1640        shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d);
1641        ~shared_lock();
1642
1643        shared_lock(shared_lock const&) = delete;
1644        shared_lock& operator=(shared_lock const&) = delete;
1645
1646        shared_lock(shared_lock<Lockable> && other);
1647        shared_lock& operator=(shared_lock<Lockable> && other);
1648
1649        void lock();
1650        bool try_lock();
1651        template <class Rep, class Period>
1652        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1653        template <class Clock, class Duration>
1654        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1655        void unlock();
1656
1657        // Conversion from upgrade locking
1658        explicit shared_lock(upgrade_lock<Lockable> && other); // EXTENSION
1659
1660        // Conversion from exclusive locking
1661        explicit shared_lock(unique_lock<Lockable> && other);
1662
1663        // Setters
1664        void swap(shared_lock& other);
1665        mutex_type* release() noexcept;
1666
1667        // Getters
1668        explicit operator bool() const;
1669        bool owns_lock() const;
1670        mutex_type mutex() const;
1671
1672    #if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
1673        shared_lock(Lockable& m_,system_time const& target_time);
1674        bool timed_lock(boost::system_time const& target_time);
1675    #endif
1676    };
1677
1678Like __unique_lock__, __shared_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied
1679__lockable_concept_type__ object, locking an instance of __shared_lock__ acquires shared ownership.
1680
1681Like __unique_lock__, not only does it provide for RAII-style locking, it also allows for deferring acquiring the lock until the
1682__lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking fashion, or with a
1683timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__
1684object, or otherwise adopted a lock on the __lockable_concept_type__ object.
1685
1686An instance of __shared_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1687pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1688is destroyed, then the destructor will invoke [unlock_shared_ref_link `mutex()->unlock_shared()`].
1689
1690The member functions of __shared_lock__ are not thread-safe. In particular, __shared_lock__ is intended to model the shared
1691ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
1692state (including the destructor) must be called by the same thread that acquired ownership of the lock state.
1693
1694[section:defaultconstructor `shared_lock()`]
1695
1696[variablelist
1697
1698[[Effects:] [Creates a lock object with no associated mutex.]]
1699
1700[[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]]
1701
1702[[Throws:] [Nothing.]]
1703
1704]
1705
1706[endsect]
1707
1708[section:constructor `shared_lock(Lockable & m)`]
1709
1710[variablelist
1711
1712[[Effects:] [Stores a reference to `m`. Invokes [lock_shared_ref_link `m.lock_shared()`].]]
1713
1714[[Postcondition:] [__owns_lock_shared_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]]
1715
1716[[Throws:] [Any exception thrown by the call to [lock_shared_ref_link `m.lock_shared()`].]]
1717
1718]
1719
1720[endsect]
1721
1722[section:constructor_adopt `shared_lock(Lockable & m,boost::adopt_lock_t)`]
1723
1724[variablelist
1725
1726[[Precondition:] [The current thread owns an exclusive lock on `m`.]]
1727
1728[[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]]
1729
1730[[Postcondition:] [__owns_lock_shared_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]]
1731
1732[[Throws:] [Nothing.]]
1733
1734]
1735
1736[endsect]
1737
1738[section:constructor_defer `shared_lock(Lockable & m,boost::defer_lock_t)`]
1739
1740[variablelist
1741
1742[[Effects:] [Stores a reference to `m`.]]
1743
1744[[Postcondition:] [__owns_lock_shared_ref__ returns `false`. __mutex_func_ref__ returns `&m`.]]
1745
1746[[Throws:] [Nothing.]]
1747
1748]
1749
1750[endsect]
1751
1752[section:constructor_try `shared_lock(Lockable & m,boost::try_to_lock_t)`]
1753
1754[variablelist
1755
1756[[Effects:] [Stores a reference to `m`. Invokes [try_lock_shared_ref_link
1757`m.try_lock_shared()`], and takes ownership of the lock state if the call returns
1758`true`.]]
1759
1760[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_shared_ref__
1761returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__
1762returns `false`.]]
1763
1764[[Throws:] [Nothing.]]
1765
1766]
1767
1768[endsect]
1769
1770[section:constructor_abs_time `shared_lock(Lockable & m,boost::system_time const& abs_time)`]
1771
1772[variablelist
1773
1774[[Effects:] [Stores a reference to `m`. Invokes [timed_lock_shared_ref_link
1775`m.timed_lock(abs_time)`], and takes ownership of the lock state if the call
1776returns `true`.]]
1777
1778[[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_shared_ref__
1779returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__
1780returns `false`.]]
1781
1782[[Throws:] [Any exceptions thrown by the call to [timed_lock_shared_ref_link `m.timed_lock(abs_time)`].]]
1783
1784]
1785
1786[endsect]
1787
1788[section:destructor `~shared_lock()`]
1789
1790[variablelist
1791
1792[[Effects:] [Invokes __mutex_func_ref__`->`[unlock_shared_ref_link `unlock_shared()`] if
1793__owns_lock_shared_ref__ returns `true`.]]
1794
1795[[Throws:] [Nothing.]]
1796
1797]
1798
1799[endsect]
1800
1801[section:owns_lock `bool owns_lock() const`]
1802
1803[variablelist
1804
1805[[Returns:] [`true` if the `*this` owns the lock on the __lockable_concept_type__
1806object associated with `*this`.]]
1807
1808[[Throws:] [Nothing.]]
1809
1810]
1811
1812[endsect]
1813
1814[section:mutex `Lockable* mutex() const`]
1815
1816[variablelist
1817
1818[[Returns:] [A pointer to the __lockable_concept_type__ object associated with
1819`*this`, or `NULL` if there is no such object.]]
1820
1821[[Throws:] [Nothing.]]
1822
1823]
1824
1825[endsect]
1826
1827
1828[section:explicit_operator_bool `explicit operator bool() const`]
1829
1830[variablelist
1831
1832[[Returns:] [__owns_lock_shared_ref__.]]
1833
1834[[Throws:] [Nothing.]]
1835
1836]
1837
1838[endsect]
1839
1840[section:release `Lockable* release()`]
1841
1842[variablelist
1843
1844[[Effects:] [The association between `*this` and the __lockable_concept_type__ object is removed, without affecting the lock state
1845of the __lockable_concept_type__ object. If __owns_lock_shared_ref__ would have returned `true`, it is the responsibility of the calling
1846code to ensure that the __lockable_concept_type__ is correctly unlocked.]]
1847
1848[[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this` at the point of the call, or `NULL` if there
1849is no such object.]]
1850
1851[[Throws:] [Nothing.]]
1852
1853[[Postcondition:] [`*this` is no longer associated with any __lockable_concept_type__ object. __mutex_func_ref__ returns `NULL` and
1854__owns_lock_shared_ref__ returns `false`.]]
1855
1856]
1857
1858[endsect]
1859
1860[endsect]
1861
1862[section:upgrade_lock Class template `upgrade_lock` - EXTENSION]
1863
1864    // #include <boost/thread/locks.hpp>
1865    // #include <boost/thread/lock_types.hpp>
1866
1867    template<typename Lockable>
1868    class upgrade_lock
1869    {
1870    public:
1871        typedef Lockable mutex_type;
1872
1873        // Upgrade locking
1874
1875        upgrade_lock();
1876        explicit upgrade_lock(mutex_type& m_);
1877        upgrade_lock(mutex_type& m, defer_lock_t) noexcept;
1878        upgrade_lock(mutex_type& m, try_to_lock_t);
1879        upgrade_lock(mutex_type& m, adopt_lock_t);
1880        template <class Clock, class Duration>
1881        upgrade_lock(mutex_type& m,
1882                     const chrono::time_point<Clock, Duration>& abs_time);
1883        template <class Rep, class Period>
1884        upgrade_lock(mutex_type& m,
1885                     const chrono::duration<Rep, Period>& rel_time);
1886        ~upgrade_lock();
1887
1888        upgrade_lock(const upgrade_lock& other) = delete;
1889        upgrade_lock& operator=(const upgrade_lock<Lockable> & other) = delete;
1890
1891        upgrade_lock(upgrade_lock<Lockable> && other);
1892        upgrade_lock& operator=(upgrade_lock<Lockable> && other);
1893
1894        void lock();
1895        bool try_lock();
1896        template <class Rep, class Period>
1897        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1898        template <class Clock, class Duration>
1899        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1900        void unlock();
1901
1902    #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
1903       // Conversion from shared locking
1904        upgrade_lock(shared_lock<mutex_type>&& sl, try_to_lock_t);
1905        template <class Clock, class Duration>
1906        upgrade_lock(shared_lock<mutex_type>&& sl,
1907                       const chrono::time_point<Clock, Duration>& abs_time);
1908        template <class Rep, class Period>
1909        upgrade_lock(shared_lock<mutex_type>&& sl,
1910                       const chrono::duration<Rep, Period>& rel_time);
1911    #endif
1912
1913        // Conversion from exclusive locking
1914        explicit upgrade_lock(unique_lock<Lockable> && other);
1915
1916        // Setters
1917        void swap(upgrade_lock& other);
1918        mutex_type* release() noexcept;
1919
1920        // Getters
1921        explicit operator bool() const;
1922        bool owns_lock() const;
1923        mutex_type mutex() const;
1924    };
1925
1926Like __unique_lock__, __upgrade_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied
1927__lockable_concept_type__ object, locking an instance of __upgrade_lock__ acquires upgrade ownership.
1928
1929Like __unique_lock__, not only does it provide for RAII-style locking, it also allows for deferring acquiring the lock until the
1930__lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking fashion, or with a
1931timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__
1932object, or otherwise adopted a lock on the __lockable_concept_type__ object.
1933
1934An instance of __upgrade_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1935pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1936is destroyed, then the destructor will invoke [unlock_upgrade_ref_link `mutex()->unlock_upgrade()`].
1937
1938The member functions of __upgrade_lock__ are not thread-safe. In particular, __upgrade_lock__ is intended to model the upgrade
1939ownership of a __upgrade_lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
1940state (including the destructor) must be called by the same thread that acquired ownership of the lock state.
1941
1942[endsect]
1943
1944[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
1945
1946    // #include <boost/thread/locks.hpp>
1947    // #include <boost/thread/lock_types.hpp>
1948
1949    template <class Lockable>
1950    class upgrade_to_unique_lock
1951    {
1952    public:
1953        typedef Lockable mutex_type;
1954        explicit upgrade_to_unique_lock(upgrade_lock<Lockable>& m_);
1955        ~upgrade_to_unique_lock();
1956
1957        upgrade_to_unique_lock(upgrade_to_unique_lock const& other) = delete;
1958        upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Lockable> const& other) = delete;
1959
1960        upgrade_to_unique_lock(upgrade_to_unique_lock<Lockable> && other);
1961        upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Lockable> && other);
1962
1963        void swap(upgrade_to_unique_lock& other);
1964
1965        explicit operator bool() const;
1966        bool owns_lock() const;
1967        mutex_type* mutex() const;
1968
1969    };
1970
1971__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
1972reference to an instance of __upgrade_lock__, if that instance has upgrade ownership on some __lockable_concept_type__ object, that
1973ownership is upgraded to exclusive ownership. When the __upgrade_to_unique_lock__ instance is destroyed, the ownership of the
1974__lockable_concept_type__ is downgraded back to ['upgrade ownership].
1975
1976[endsect]
1977
1978[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
1979
1980    class MutexType::scoped_try_lock
1981    {
1982    private:
1983        MutexType::scoped_try_lock(MutexType::scoped_try_lock<MutexType>& other);
1984        MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock<MutexType>& other);
1985    public:
1986        MutexType::scoped_try_lock();
1987        explicit MutexType::scoped_try_lock(MutexType& m);
1988        MutexType::scoped_try_lock(MutexType& m_,adopt_lock_t);
1989        MutexType::scoped_try_lock(MutexType& m_,defer_lock_t);
1990        MutexType::scoped_try_lock(MutexType& m_,try_to_lock_t);
1991
1992        MutexType::scoped_try_lock(MutexType::scoped_try_lock<MutexType>&& other);
1993        MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock<MutexType>&& other);
1994
1995        void swap(MutexType::scoped_try_lock&& other);
1996
1997        void lock();
1998        bool try_lock();
1999        void unlock();
2000
2001        MutexType* mutex() const;
2002        MutexType* release();
2003
2004        explicit operator bool() const;
2005        bool owns_lock() const;
2006    };
2007
2008The member typedef `scoped_try_lock` is provided for each distinct
2009`MutexType` as a typedef to a class with the preceding definition. The
2010semantics of each constructor and member function are identical to
2011those of [unique_lock_link `boost::unique_lock<MutexType>`] for the same `MutexType`, except
2012that the constructor that takes a single reference to a mutex will
2013call [try_lock_ref_link `m.try_lock()`] rather than `m.lock()`.
2014
2015[endsect]
2016[endsect]
2017
2018[/
2019[section:other_mutex Other Mutex Types]
2020
2021[section: reverse_mutex Class template `reverse_mutex`]
2022
2023  //#include <boost/thread/reverse_mutex.hpp>
2024
2025  namespace boost
2026  {
2027    template<typename BasicLockable>
2028    class reverse_mutex
2029    {
2030    public:
2031        typedef BasicLockable mutex_type;
2032        reverse_mutex(reverse_mutex const&) = delete;
2033        reverse_mutex& operator=(reverse_mutex const&) = delete;
2034
2035        explicit reverse_mutex(mutex_type& m_);
2036        ~reverse_mutex();
2037
2038        void lock();
2039        void unlock();
2040    };
2041  }
2042
2043__reverse_mutex reverse the operations of a __BasicLockable, that unlocks the lockable when `lock()` is called and locks it when `unlock()` is called.
2044
2045[endsect]
2046[endsect]
2047
2048]
2049
2050[section:other_locks Other Lock Types - EXTENSION]
2051
2052[section:strict_locks Strict Locks]
2053
2054  // #include <boost/thread/locks.hpp>
2055  // #include <boost/thread/strict_lock.hpp>
2056
2057  namespace boost
2058  {
2059
2060    template<typename Lockable>
2061    class strict_lock;
2062    template <typename Lock>
2063    class nested_strict_lock;
2064    template <typename Lockable>
2065    struct is_strict_lock_sur_parole<strict_lock<Lockable> >;
2066    template <typename Lock>
2067    struct is_strict_lock_sur_parole<nested_strict_lock<Lock> >;
2068
2069  #if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
2070    template <typename Lockable>
2071    strict_lock<Lockable> make_strict_lock(Lockable& mtx);
2072  #endif
2073  #if ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK
2074    template <typename Lock>
2075    nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk);
2076  #endif
2077
2078  }
2079
2080[section:strict_lock Class template `strict_lock`]
2081
2082    // #include <boost/thread/locks.hpp>
2083    // #include <boost/thread/strict_lock.hpp>
2084
2085    template<typename BasicLockable>
2086    class strict_lock
2087    {
2088    public:
2089        typedef BasicLockable mutex_type;
2090        strict_lock(strict_lock const& m_) = delete;
2091        strict_lock& operator=(strict_lock const& m_) = delete;
2092        explicit strict_lock(mutex_type& m_);
2093        ~strict_lock();
2094
2095        bool owns_lock(mutex_type const* l) const noexcept;
2096    };
2097
2098__strict_lock is a model of __StrictLock.
2099
2100__strict_lock is the simplest __StrictLock: on construction it acquires ownership of the implementation of the __BasicLockable concept supplied as the constructor parameter. On destruction, the ownership is released. This provides simple RAII-style locking of a __BasicLockable object, to facilitate exception-safe locking and unlocking.
2101
2102[heading See also __lock_guard__]
2103
2104[section:constructor `strict_lock(Lockable & m)`]
2105
2106[variablelist
2107
2108[[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]]
2109
2110[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
2111
2112]
2113
2114[endsect]
2115
2116[section:destructor `~strict_lock()`]
2117
2118[variablelist
2119
2120[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
2121object passed to the constructor.]]
2122
2123[[Throws:] [Nothing.]]
2124
2125]
2126
2127[endsect]
2128
2129[endsect]
2130
2131
2132[section:nested_strict_lock Class template `nested_strict_lock`]
2133
2134    // #include <boost/thread/locks.hpp>
2135    // #include <boost/thread/strict_lock.hpp>
2136
2137    template<typename Lock>
2138    class nested_strict_lock
2139    {
2140    public:
2141        typedef BasicLockable mutex_type;
2142        nested_strict_lock(nested_strict_lock const& m_) = delete;
2143        nested_strict_lock& operator=(nested_strict_lock const& m_) = delete;
2144        explicit nested_strict_lock(Lock& lk),
2145        ~nested_strict_lock() noexcept;
2146
2147        bool owns_lock(mutex_type const* l) const noexcept;
2148    };
2149
2150__nested_strict_lock is a model of __StrictLock.
2151
2152A nested strict lock is a scoped lock guard ensuring a mutex is locked on its
2153scope, by taking ownership of a nesting lock, locking the mutex on construction if not already locked
2154and restoring the ownership to the nesting lock on destruction.
2155
2156
2157[heading See also __strict_lock, __unique_lock]
2158
2159[section:constructor `nested_strict_lock(Lock & lk)`]
2160
2161[variablelist
2162
2163[[Requires:] [`lk.mutex() != null_ptr`.]]
2164
2165[[Effects:] [Stores the reference to the lock parameter `lk` and takes ownership on it.
2166If the lock doesn't owns the mutex lock it.
2167]]
2168
2169[[Postcondition:] [`owns_lock(lk.mutex())`.]]
2170
2171[[Throws:] [
2172
2173- lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr
2174
2175- Any exception that @c lk.lock() can throw.
2176
2177
2178]]
2179
2180]
2181
2182[endsect]
2183
2184[section:destructor `~nested_strict_lock() noexcept`]
2185
2186[variablelist
2187
2188[[Effects:] [Restores ownership to the nesting lock.]]
2189
2190]
2191
2192[endsect]
2193
2194
2195[section:owns_lock `bool owns_lock(mutex_type const* l) const noexcept`]
2196
2197[variablelist
2198
2199[[Return:] [Whether if this lock is locking that mutex.]]
2200
2201]
2202
2203[endsect]
2204
2205[endsect]
2206
2207[section:make_strict_lock Non Member Function `make_strict_lock`]
2208
2209    template <typename Lockable>
2210    strict_lock<Lockable> make_strict_lock(Lockable& m); // EXTENSION
2211
2212
2213[variablelist
2214
2215[[Returns:] [a strict_lock as if initialized with `{m}`.]]
2216
2217[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
2218
2219]
2220
2221
2222[endsect]
2223
2224
2225[section:make_nested_strict_lock Non Member Function `make_nested_strict_lock`]
2226
2227  template <typename Lock>
2228  nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk); // EXTENSION
2229
2230
2231[variablelist
2232
2233[[Returns:] [a nested_strict_lock as if initialized with `{lk}`.]]
2234
2235[[Throws:] [Any exception thrown by the call to [lock_ref_link `lk.lock()`].]]
2236
2237]
2238
2239
2240[endsect]
2241
2242
2243
2244[endsect]
2245
2246[section:lock_ptrs Locking pointers]
2247
2248  // #include <boost/thread/synchroniezd_value.hpp>
2249  // #include <boost/thread/strict_lock_ptr.hpp>
2250
2251  namespace boost
2252  {
2253
2254    template<typename T, typename Lockable = mutex>
2255    class strict_lock_ptr;
2256    template<typename T, typename Lockable = mutex>
2257    class const_strict_lock_ptr;
2258  }
2259
2260
2261[/
2262    template<typename T, typename Lockable = mutex>
2263    class unique_lock_ptr;
2264    template<typename T, typename Lockable = mutex>
2265    class const_unique_lock_ptr;
2266
2267]
2268
2269[section:const_strict_lock_ptr Class template `const_strict_lock_ptr `]
2270
2271  // #include <boost/thread/synchroniezd_value.hpp>
2272  // #include <boost/thread/strict_lock_ptr.hpp>
2273
2274
2275  template <typename T, typename Lockable = mutex>
2276  class const_strict_lock_ptr
2277  {
2278  public:
2279    typedef T value_type;
2280    typedef Lockable mutex_type;
2281
2282    const_strict_lock_ptr(const_strict_lock_ptr const& m_) = delete;
2283    const_strict_lock_ptr& operator=(const_strict_lock_ptr const& m_) = delete;
2284
2285    const_strict_lock_ptr(T const& val, Lockable & mtx);
2286    const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag);
2287
2288    ~const_strict_lock_ptr();
2289
2290    const T* operator->() const;
2291    const T& operator*() const;
2292
2293  };
2294
2295
2296[section:constructor `const_strict_lock_ptr(T const&,Lockable&)`]
2297
2298
2299    const_strict_lock_ptr(T const& val, Lockable & m);
2300
2301[variablelist
2302
2303[[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]]
2304
2305[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
2306
2307]
2308
2309[endsect]
2310[section:constructor_adopt `const_strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`]
2311
2312    const_strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag);
2313
2314[variablelist
2315
2316[[Effects:] [Stores a reference to it and to the value type `val`.]]
2317
2318[[Throws:] [Nothing.]]
2319
2320]
2321
2322[endsect]
2323
2324
2325[section:destructor `~const_strict_lock_ptr()`]
2326
2327    ~const_strict_lock_ptr();
2328
2329[variablelist
2330
2331[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
2332object passed to the constructor.]]
2333
2334[[Throws:] [Nothing.]]
2335
2336]
2337
2338[endsect]
2339
2340[section:indir `operator->() const`]
2341
2342    const T* operator->() const;
2343
2344
2345[variablelist
2346
2347[[Return:] [return a constant pointer to the protected value.]]
2348
2349[[Throws:] [Nothing.]]
2350
2351]
2352
2353[endsect]
2354
2355[section:deref `operator*() const`]
2356
2357    const T& operator*() const;
2358
2359
2360[variablelist
2361
2362[[Return:] [return a constant reference to the protected value.]]
2363
2364[[Throws:] [Nothing.]]
2365
2366]
2367
2368[endsect]
2369
2370
2371[endsect] [/ const_strict_lock_ptr ]
2372
2373[section:strict_lock_ptr Class template `strict_lock_ptr`]
2374
2375  // #include <boost/thread/synchroniezd_value.hpp>
2376  // #include <boost/thread/strict_lock_ptr.hpp>
2377
2378  template <typename T, typename Lockable = mutex>
2379  class strict_lock_ptr : public const_strict_lock_ptr<T,Lockable>
2380  {
2381  public:
2382    strict_lock_ptr(strict_lock_ptr const& m_) = delete;
2383    strict_lock_ptr& operator=(strict_lock_ptr const& m_) = delete;
2384
2385    strict_lock_ptr(T & val, Lockable & mtx);
2386    strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag);
2387    ~strict_lock_ptr();
2388
2389    T* operator->();
2390    T& operator*();
2391
2392  };
2393
2394
2395[section:constructor `strict_lock_ptr(T const&,Lockable&)`]
2396
2397
2398    strict_lock_ptr(T const& val, Lockable & m);
2399
2400[variablelist
2401
2402[[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]]
2403
2404[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
2405
2406]
2407
2408[endsect]
2409[section:constructor_adopt `strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`]
2410
2411    strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag);
2412
2413[variablelist
2414
2415[[Effects:] [Stores a reference to it and to the value type `val`.]]
2416
2417[[Throws:] [Nothing.]]
2418
2419]
2420
2421[endsect]
2422
2423
2424[section:destructor `~strict_lock_ptr()`]
2425
2426    ~ strict_lock_ptr();
2427
2428[variablelist
2429
2430[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
2431object passed to the constructor.]]
2432
2433[[Throws:] [Nothing.]]
2434
2435]
2436
2437[endsect]
2438
2439[section:indir `operator->()`]
2440
2441    T* operator->();
2442
2443
2444[variablelist
2445
2446[[Return:] [return a pointer to the protected value.]]
2447
2448[[Throws:] [Nothing.]]
2449
2450]
2451
2452[endsect]
2453
2454[section:deref `operator*()`]
2455
2456    T& operator*();
2457
2458
2459[variablelist
2460
2461[[Return:] [return a reference to the protected value.]]
2462
2463[[Throws:] [Nothing.]]
2464
2465]
2466
2467[endsect]
2468
2469
2470[endsect] [/ strict_lock_ptr ]
2471
2472[endsect] [/ lock_ptrs ]
2473
2474
2475[section Externally Locked]
2476
2477  // #include <boost/thread/externally_locked.hpp>
2478  template <class T, typename MutexType = boost::mutex>
2479  class externally_locked;
2480  template <class T, typename MutexType>
2481  class externally_locked<T&, MutexType>;
2482
2483  template <typename T, typename MutexType>
2484  void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs);
2485
2486[section:externally_locked Template Class `externally_locked`]
2487
2488  // #include <boost/thread/externally_locked.hpp>
2489
2490  template <class T, typename MutexType>
2491  class externally_locked
2492  {
2493    //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
2494    BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
2495
2496  public:
2497    typedef MutexType mutex_type;
2498
2499    externally_locked(mutex_type& mtx, const T& obj);
2500    externally_locked(mutex_type& mtx,T&& obj);
2501    explicit externally_locked(mutex_type& mtx);
2502    externally_locked(externally_locked const& rhs);
2503    externally_locked(externally_locked&& rhs);
2504    externally_locked& operator=(externally_locked const& rhs);
2505    externally_locked& operator=(externally_locked&& rhs);
2506
2507    // observers
2508    T& get(strict_lock<mutex_type>& lk);
2509    const T& get(strict_lock<mutex_type>& lk) const;
2510
2511    template <class Lock>
2512    T& get(nested_strict_lock<Lock>& lk);
2513    template <class Lock>
2514    const T& get(nested_strict_lock<Lock>& lk) const;
2515
2516    template <class Lock>
2517    T& get(Lock& lk);
2518    template <class Lock>
2519    T const& get(Lock& lk) const;
2520
2521   mutex_type* mutex() const noexcept;
2522
2523    // modifiers
2524    void lock();
2525    void unlock();
2526    bool try_lock();
2527    void swap(externally_locked&);
2528  };
2529
2530`externally_locked` is a model of __Lockable, it cloaks an object of type `T`, and actually provides full
2531access to that object through the get and set member functions, provided you
2532pass a reference to a strict lock object.
2533
2534Only the specificities respect to __Lockable are described here.
2535
2536[///////////////////////////////]
2537[section:constructor1 `externally_locked(mutex_type&, const T&)`]
2538
2539    externally_locked(mutex_type& mtx, const T& obj);
2540
2541[variablelist
2542
2543[[Requires:] [T is a model of CopyConstructible.]]
2544
2545[[Effects:] [Constructs an externally locked object copying the cloaked type.]]
2546
2547[[Throws:] [Any exception thrown by the call to `T(obj)`.]]
2548
2549]
2550
2551[endsect]
2552[///////////////////////////////]
2553[section:constructor2 `externally_locked(mutex_type&, T&&)`]
2554
2555    externally_locked(mutex_type& mtx,T&& obj);
2556
2557[variablelist
2558
2559[[Requires:] [T is a model of Movable.]]
2560
2561[[Effects:] [Constructs an externally locked object by moving the cloaked type.]]
2562
2563[[Throws:] [Any exception thrown by the call to `T(obj)`.]]
2564
2565]
2566
2567[endsect]
2568[///////////////////////////////]
2569[section:constructor3 `externally_locked(mutex_type&)`]
2570
2571    externally_locked(mutex_type& mtx);
2572
2573[variablelist
2574
2575[[Requires:] [T is a model of DefaultConstructible.]]
2576
2577[[Effects:] [Constructs an externally locked object by default constructing the cloaked type.]]
2578
2579[[Throws:] [Any exception thrown by the call to `T()`.]]
2580
2581]
2582
2583[endsect]
2584[///////////////////////////////]
2585[section:constructor4 `externally_locked(externally_locked&&)`]
2586
2587    externally_locked(externally_locked&& rhs);
2588
2589[variablelist
2590
2591[[Requires:] [T is a model of Movable.]]
2592
2593[[Effects:] [Move constructs an externally locked object by moving the cloaked type and copying the mutex reference ]]
2594
2595[[Throws:] [Any exception thrown by the call to `T(T&&)`.]]
2596
2597]
2598
2599[endsect]
2600[///////////////////////////////]
2601[section:constructor5 `externally_locked(externally_locked&)`]
2602
2603    externally_locked(externally_locked& rhs);
2604
2605[variablelist
2606
2607[[Requires:] [T is a model of Copyable.]]
2608
2609[[Effects:] [Copy constructs an externally locked object by copying the cloaked type and copying the mutex reference ]]
2610
2611[[Throws:] [Any exception thrown by the call to `T(T&)`.]]
2612
2613]
2614
2615[endsect]
2616[///////////////////////////////]
2617[section:assign4 `externally_locked(externally_locked&&)`]
2618
2619    externally_locked& operator=(externally_locked&& rhs);
2620
2621[variablelist
2622
2623[[Requires:] [T is a model of Movable.]]
2624
2625[[Effects:] [Move assigns an externally locked object by moving the cloaked type and copying the mutex reference ]]
2626
2627[[Throws:] [Any exception thrown by the call to `T::operator=(T&&)`.]]
2628
2629]
2630
2631[endsect]
2632[///////////////////////////////]
2633[section:assign5 `externally_locked(externally_locked&)`]
2634
2635    externally_locked& operator=(externally_locked const& rhs);
2636
2637[variablelist
2638
2639[[Requires:] [T is a model of Copyable.]]
2640
2641[[Effects:] [Copy assigns an externally locked object by copying the cloaked type and copying the mutex reference ]]
2642
2643[[Throws:] [Any exception thrown by the call to `T::operator=(T&)`.]]
2644
2645]
2646
2647[endsect]
2648
2649[///////////////////////////////]
2650[section:get1 `get(strict_lock<mutex_type>&)`]
2651
2652    T& get(strict_lock<mutex_type>& lk);
2653    const T& get(strict_lock<mutex_type>& lk) const;
2654
2655[variablelist
2656
2657[[Requires:] [The `lk` parameter must be locking the associated mutex.]]
2658
2659[[Returns:] [A reference to the cloaked object ]]
2660
2661[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2662
2663]
2664
2665[endsect]
2666[///////////////////////////////]
2667[section:get2 `get(nested_strict_lock<Lock>&)`]
2668
2669    template <class Lock>
2670    T& get(nested_strict_lock<Lock>& lk);
2671    template <class Lock>
2672    const T& get(nested_strict_lock<Lock>& lk) const;
2673
2674[variablelist
2675
2676[[Requires:] [`is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
2677
2678[[Returns:] [A reference to the cloaked object ]]
2679
2680[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2681
2682]
2683
2684[endsect]
2685
2686[///////////////////////////////]
2687[section:get3 `get(Lock&)`]
2688
2689    template <class Lock>
2690    T& get(Lock& lk);
2691    template <class Lock>
2692    T const& get(Lock& lk) const;
2693
2694[variablelist
2695
2696[[Requires:] [`Lock` is a model of __StrictLock, `is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
2697
2698[[Returns:] [A reference to the cloaked object ]]
2699
2700[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2701
2702]
2703
2704[endsect]
2705
2706[endsect]
2707[section:externally_locked_ref Template Class `externally_locked<T&>`]
2708
2709  // #include <boost/thread/externally_locked.hpp>
2710
2711  template <class T, typename MutexType>
2712  class externally_locked<T&, MutexType>
2713  {
2714    //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
2715    BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
2716
2717  public:
2718    typedef MutexType mutex_type;
2719
2720    externally_locked(mutex_type& mtx, T& obj);
2721    explicit externally_locked(mutex_type& mtx);
2722    externally_locked(externally_locked const& rhs) noexcept;
2723    externally_locked(externally_locked&& rhs) noexcept;
2724    externally_locked& operator=(externally_locked const& rhs) noexcept;
2725    externally_locked& operator=(externally_locked&& rhs) noexcept;
2726
2727    // observers
2728    T& get(strict_lock<mutex_type>& lk);
2729    const T& get(strict_lock<mutex_type>& lk) const;
2730
2731    template <class Lock>
2732    T& get(nested_strict_lock<Lock>& lk);
2733    template <class Lock>
2734    const T& get(nested_strict_lock<Lock>& lk) const;
2735
2736    template <class Lock>
2737    T& get(Lock& lk);
2738    template <class Lock>
2739    T const& get(Lock& lk) const;
2740
2741   mutex_type* mutex() const noexcept;
2742
2743    // modifiers
2744    void lock();
2745    void unlock();
2746    bool try_lock();
2747    void swap(externally_locked&) noexcept;
2748  };
2749
2750`externally_locked` is a model of __Lockable, it cloaks an object of type `T`, and actually provides full
2751access to that object through the get and set member functions, provided you
2752pass a reference to a strict lock object.
2753
2754Only the specificities respect to __Lockable are described here.
2755
2756[///////////////////////////////]
2757[section:constructor1 `externally_locked<T&>(mutex_type&, T&)`]
2758
2759    externally_locked<T&>(mutex_type& mtx, T& obj) noexcept;
2760
2761[variablelist
2762
2763
2764[[Effects:] [Constructs an externally locked object copying the cloaked reference.]]
2765
2766]
2767
2768[endsect]
2769[///////////////////////////////]
2770[section:constructor4 `externally_locked<T&>(externally_locked&&)`]
2771
2772    externally_locked(externally_locked&& rhs) noexcept;
2773
2774[variablelist
2775
2776[[Effects:] [Moves an externally locked object by moving the cloaked type and copying the mutex reference ]]
2777
2778
2779]
2780
2781[endsect]
2782[///////////////////////////////]
2783[section:assign4 `externally_locked(externally_locked&&)`]
2784
2785    externally_locked& operator=(externally_locked&& rhs);
2786
2787[variablelist
2788
2789[[Effects:] [Move assigns an externally locked object by copying the cloaked reference and copying the mutex reference ]]
2790
2791]
2792
2793[endsect]
2794[///////////////////////////////]
2795[section:assign5 `externally_locked(externally_locked&)`]
2796
2797    externally_locked& operator=(externally_locked const& rhs);
2798
2799[variablelist
2800
2801[[Requires:] [T is a model of Copyable.]]
2802
2803[[Effects:] [Copy assigns an externally locked object by copying the cloaked reference and copying the mutex reference ]]
2804
2805[[Throws:] [Any exception thrown by the call to `T::operator=(T&)`.]]
2806
2807]
2808
2809[endsect]
2810
2811[///////////////////////////////]
2812[section:get1 `get(strict_lock<mutex_type>&)`]
2813
2814    T& get(strict_lock<mutex_type>& lk);
2815    const T& get(strict_lock<mutex_type>& lk) const;
2816
2817[variablelist
2818
2819[[Requires:] [The `lk` parameter must be locking the associated mutex.]]
2820
2821[[Returns:] [A reference to the cloaked object ]]
2822
2823[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2824
2825]
2826
2827[endsect]
2828[///////////////////////////////]
2829[section:get2 `get(nested_strict_lock<Lock>&)`]
2830
2831    template <class Lock>
2832    T& get(nested_strict_lock<Lock>& lk);
2833    template <class Lock>
2834    const T& get(nested_strict_lock<Lock>& lk) const;
2835
2836[variablelist
2837
2838[[Requires:] [`is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
2839
2840[[Returns:] [A reference to the cloaked object ]]
2841
2842[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2843
2844]
2845
2846[endsect]
2847
2848[///////////////////////////////]
2849[section:get3 `get(Lock&)`]
2850
2851    template <class Lock>
2852    T& get(Lock& lk);
2853    template <class Lock>
2854    T const& get(Lock& lk) const;
2855
2856[variablelist
2857
2858[[Requires:] [`Lock` is a model of __StrictLock, `is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
2859
2860[[Returns:] [A reference to the cloaked object ]]
2861
2862[[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]]
2863
2864]
2865
2866[endsect]
2867
2868[endsect]
2869
2870
2871[///////////////////////////////]
2872[section:swap `swap(externally_locked&, externally_locked&)`]
2873
2874  template <typename T, typename MutexType>
2875  void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs)
2876
2877[endsect]
2878
2879
2880[endsect]
2881
2882[section:shared_lock_guard Class template `shared_lock_guard`]
2883
2884  // #include <boost/thread/shared_lock_guard.hpp>
2885  namespace boost
2886  {
2887    template<typename SharedLockable>
2888    class shared_lock_guard
2889    {
2890    public:
2891        shared_lock_guard(shared_lock_guard const&) = delete;
2892        shared_lock_guard& operator=(shared_lock_guard const&) = delete;
2893
2894        explicit shared_lock_guard(SharedLockable& m_);
2895        shared_lock_guard(SharedLockable& m_,boost::adopt_lock_t);
2896
2897        ~shared_lock_guard();
2898    };
2899  }
2900
2901__shared_lock_guard is very simple: on construction it
2902acquires shared ownership of the implementation of the __shared_lockable_concept__ supplied as
2903the constructor parameter. On destruction, the ownership is released. This
2904provides simple RAII-style locking of a __shared_lockable_concept_type__ object, to facilitate exception-safe
2905shared locking and unlocking.
2906In addition, the `__shared_lock_guard_constructor_adopt(SharedLockable &m, boost::adopt_lock_t)` constructor allows the __shared_lock_guard object to
2907take shared ownership of a lock already held by the current thread.
2908
2909[section:constructor `shared_lock_guard(SharedLockable & m)`]
2910
2911[variablelist
2912
2913[[Effects:] [Stores a reference to `m`. Invokes `m.__lock_shared()`.]]
2914
2915[[Throws:] [Any exception thrown by the call to `m.__lock_shared()`.]]
2916
2917]
2918
2919[endsect]
2920
2921[section:constructor_adopt `shared_lock_guard(SharedLockable & m,boost::adopt_lock_t)`]
2922
2923[variablelist
2924
2925[[Precondition:] [The current thread owns a lock on `m` equivalent to one
2926obtained by a call to `m.__lock_shared()`.]]
2927
2928[[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of
2929`m`.]]
2930
2931[[Throws:] [Nothing.]]
2932
2933]
2934
2935[endsect]
2936
2937[section:destructor `~shared_lock_guard()`]
2938
2939[variablelist
2940
2941[[Effects:] [Invokes `m.__unlock_shared()` on the __shared_lockable_concept_type__ object passed to the constructor.]]
2942
2943[[Throws:] [Nothing.]]
2944
2945]
2946
2947[endsect]
2948
2949[endsect]
2950
2951[section:reverse_lock Class template `reverse_lock`]
2952
2953  // #include <boost/thread/reverse_lock.hpp>
2954  namespace boost
2955  {
2956
2957    template<typename Lock>
2958    class reverse_lock
2959    {
2960    public:
2961        reverse_lock(reverse_lock const&) = delete;
2962        reverse_lock& operator=(reverse_lock const&) = delete;
2963
2964        explicit reverse_lock(Lock& m_);
2965        ~reverse_lock();
2966    };
2967  }
2968
2969__reverse_lock reverse the operations of a lock: it provide for RAII-style, that unlocks the lock at construction time and lock it at destruction time. In addition, it transfer ownership temporarily, so that the mutex can not be locked using the Lock.
2970
2971An instance of __reverse_lock doesn't ['own] the lock never.
2972
2973
2974[section:constructor `reverse_lock(Lock & m)`]
2975
2976[variablelist
2977
2978[[Effects:] [Stores a reference to `m`. Invokes `m.__unlock()` if `m` owns his lock and then stores the mutex by calling `m.release()`.]]
2979
2980[[Postcondition:] [`!m.__owns_lock() && m.mutex()==0`.]]
2981
2982[[Throws:] [Any exception thrown by the call to `m.__unlock()`.]]
2983
2984]
2985
2986[endsect]
2987
2988
2989[section:destructor `~reverse_lock()`]
2990
2991[variablelist
2992
2993[[Effects:] [Let be mtx the stored mutex*. If not 0 Invokes `mtx->__lock()` and gives again the `mtx` to the `Lock` using the `adopt_lock_t` overload.]]
2994
2995[[Throws:] [Any exception thrown by `mtx->__lock()`.]]
2996
2997[[Remarks:] [Note that if `mtx->__lock()` throws an exception while unwinding the program will terminate, so don't use reverse_lock if an exception can be thrown.]]
2998
2999]
3000
3001[endsect]
3002
3003
3004[endsect] [/ reverse_lock<>]
3005
3006[endsect]
3007
3008
3009[section:lock_functions Lock functions]
3010
3011[section:lock_multiple Non-member function `lock(Lockable1,Lockable2,...)`]
3012
3013  // #include <boost/thread/locks.hpp>
3014  // #include <boost/thread/lock_algorithms.hpp>
3015  namespace boost
3016  {
3017
3018    template<typename Lockable1,typename Lockable2>
3019    void lock(Lockable1& l1,Lockable2& l2);
3020
3021    template<typename Lockable1,typename Lockable2,typename Lockable3>
3022    void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3);
3023
3024    template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4>
3025    void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4);
3026
3027    template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4,typename Lockable5>
3028    void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4,Lockable5& l5);
3029
3030  }
3031
3032[variablelist
3033
3034[[Effects:] [Locks the __lockable_concept_type__ objects supplied as
3035arguments in an unspecified and indeterminate order in a way that
3036avoids deadlock. It is safe to call this function concurrently from
3037multiple threads for any set of mutexes (or other lockable objects) in
3038any order without risk of deadlock. If any of the __lock_ref__
3039or __try_lock_ref__ operations on the supplied
3040__lockable_concept_type__ objects throws an exception any locks
3041acquired by the function will be released before the function exits.]]
3042
3043[[Throws:] [Any exceptions thrown by calling __lock_ref__ or
3044__try_lock_ref__ on the supplied __lockable_concept_type__ objects.]]
3045
3046[[Postcondition:] [All the supplied __lockable_concept_type__ objects
3047are locked by the calling thread.]]
3048
3049]
3050
3051[endsect]
3052
3053[section:lock_range Non-member function `lock(begin,end)` // EXTENSION]
3054
3055    template<typename ForwardIterator>
3056    void lock(ForwardIterator begin,ForwardIterator end);
3057
3058[variablelist
3059
3060[[Preconditions:] [The `value_type` of `ForwardIterator` must implement the __lockable_concept__]]
3061
3062[[Effects:] [Locks all the __lockable_concept_type__ objects in the
3063supplied range in an unspecified and indeterminate order in a way that
3064avoids deadlock. It is safe to call this function concurrently from
3065multiple threads for any set of mutexes (or other lockable objects) in
3066any order without risk of deadlock. If any of the __lock_ref__
3067or __try_lock_ref__ operations on the __lockable_concept_type__
3068objects in the supplied range throws an exception any locks acquired
3069by the function will be released before the function exits.]]
3070
3071[[Throws:] [Any exceptions thrown by calling __lock_ref__ or
3072__try_lock_ref__ on the supplied __lockable_concept_type__ objects.]]
3073
3074[[Postcondition:] [All the __lockable_concept_type__ objects in the
3075supplied range are locked by the calling thread.]]
3076
3077]
3078
3079[endsect]
3080
3081[section:try_lock_multiple Non-member function `try_lock(Lockable1,Lockable2,...)`]
3082
3083    template<typename Lockable1,typename Lockable2>
3084    int try_lock(Lockable1& l1,Lockable2& l2);
3085
3086    template<typename Lockable1,typename Lockable2,typename Lockable3>
3087    int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3);
3088
3089    template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4>
3090    int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4);
3091
3092    template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4,typename Lockable5>
3093    int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4,Lockable5& l5);
3094
3095[variablelist
3096
3097[[Effects:] [Calls __try_lock_ref__ on each of the
3098__lockable_concept_type__ objects supplied as arguments. If any of the
3099calls to __try_lock_ref__ returns `false` then all locks acquired are
3100released and the zero-based index of the failed lock is returned.
3101
3102If any of the __try_lock_ref__ operations on the supplied
3103__lockable_concept_type__ objects throws an exception any locks
3104acquired by the function will be released before the function exits.]]
3105
3106[[Returns:] [`-1` if all the supplied __lockable_concept_type__ objects
3107are now locked by the calling thread, the zero-based index of the
3108object which could not be locked otherwise.]]
3109
3110[[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the
3111supplied __lockable_concept_type__ objects.]]
3112
3113[[Postcondition:] [If the function returns `-1`, all the supplied
3114__lockable_concept_type__ objects are locked by the calling
3115thread. Otherwise any locks acquired by this function will have been
3116released.]]
3117
3118]
3119
3120[endsect]
3121
3122[section:try_lock_range Non-member function `try_lock(begin,end)` // EXTENSION]
3123
3124    template<typename ForwardIterator>
3125    ForwardIterator try_lock(ForwardIterator begin,ForwardIterator end);
3126
3127[variablelist
3128
3129[[Preconditions:] [The `value_type` of `ForwardIterator` must implement the __lockable_concept__]]
3130
3131[[Effects:] [Calls __try_lock_ref__ on each of the
3132__lockable_concept_type__ objects in the supplied range. If any of the
3133calls to __try_lock_ref__ returns `false` then all locks acquired are
3134released and an iterator referencing the failed lock is returned.
3135
3136If any of the __try_lock_ref__ operations on the supplied
3137__lockable_concept_type__ objects throws an exception any locks
3138acquired by the function will be released before the function exits.]]
3139
3140[[Returns:] [`end` if all the supplied __lockable_concept_type__
3141objects are now locked by the calling thread, an iterator referencing
3142the object which could not be locked otherwise.]]
3143
3144[[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the
3145supplied __lockable_concept_type__ objects.]]
3146
3147[[Postcondition:] [If the function returns `end` then all the
3148__lockable_concept_type__ objects in the supplied range are locked by
3149the calling thread, otherwise all locks acquired by the function have
3150been released.]]
3151
3152]
3153
3154[endsect]
3155[endsect]
3156
3157[section:lock_factories Lock Factories - EXTENSION]
3158
3159  namespace boost
3160  {
3161
3162    template <typename Lockable>
3163    unique_lock<Lockable> make_unique_lock(Lockable& mtx); // EXTENSION
3164
3165    template <typename Lockable>
3166    unique_lock<Lockable> make_unique_lock(Lockable& mtx, adopt_lock_t); // EXTENSION
3167    template <typename Lockable>
3168    unique_lock<Lockable> make_unique_lock(Lockable& mtx, defer_lock_t); // EXTENSION
3169    template <typename Lockable>
3170    unique_lock<Lockable> make_unique_lock(Lockable& mtx, try_to_lock_t); // EXTENSION
3171
3172  #if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
3173    template <typename ...Lockable>
3174    std::tuple<unique_lock<Lockable> ...> make_unique_locks(Lockable& ...mtx); // EXTENSION
3175  #endif
3176  }
3177
3178[section:make_unique_lock Non Member Function `make_unique_lock(Lockable&)`]
3179
3180  template <typename Lockable>
3181  unique_lock<Lockable> make_unique_lock(Lockable& mtx); // EXTENSION
3182
3183
3184[variablelist
3185
3186[[Returns:] [a __unique_lock as if initialized with `unique_lock<Lockable>(mtx)`.]]
3187
3188[[Throws:] [Any exception thrown by the call to `__unique_lock<Lockable>(mtx)`.]]
3189
3190]
3191
3192[endsect]
3193
3194[section:make_unique_lock_t Non Member Function `make_unique_lock(Lockable&,tag)`]
3195
3196  template <typename Lockable>
3197  unique_lock<Lockable> make_unique_lock(Lockable& mtx, adopt_lock_t tag); // EXTENSION
3198
3199  template <typename Lockable>
3200  unique_lock<Lockable> make_unique_lock(Lockable& mtx, defer_lock_t tag); // EXTENSION
3201
3202  template <typename Lockable>
3203  unique_lock<Lockable> make_unique_lock(Lockable& mtx, try_to_lock_t tag); // EXTENSION
3204
3205
3206[variablelist
3207
3208[[Returns:] [a __unique_lock as if initialized with `unique_lock<Lockable>(mtx, tag)`.]]
3209
3210[[Throws:] [Any exception thrown by the call to `__unique_lock<Lockable>(mtx, tag)`.]]
3211
3212]
3213
3214[endsect]
3215
3216
3217[section:make_unique_locks Non Member Function `make_unique_locks(Lockable& ...)`]
3218
3219  template <typename ...Lockable>
3220  std::tuple<unique_lock<Lockable> ...> make_unique_locks(Lockable& ...mtx); // EXTENSION
3221
3222[variablelist
3223
3224[[Effect:] [Locks all the mutexes.]]
3225
3226[[Returns:] [a std::tuple of unique __unique_lock owning each one of the mutex.]]
3227
3228[[Throws:] [Any exception thrown by `boost::lock(mtx...)`.]]
3229
3230]
3231
3232
3233[endsect]
3234[endsect]
3235
3236