]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/doc/mutex_concepts.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / doc / mutex_concepts.qbk
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
11 A mutex object facilitates protection against data races and allows thread-safe synchronization of data between threads. A thread
12 obtains ownership of a mutex object by calling one of the lock functions and relinquishes ownership by calling the corresponding
13 unlock function. Mutexes may be either recursive or non-recursive, and may grant simultaneous ownership to one or many
14 threads. __boost_thread__ supplies recursive and non-recursive mutexes with exclusive ownership semantics, along with a shared
15 ownership (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
19 do 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
33 The __BasicLockable concept models exclusive ownership.
34 A 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
39 Lock 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
103 Some of the algorithms on mutexes use this trait via SFINAE.
104
105 This 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
121 A 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
125 Lock 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
140 failure, 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
165 Some of the algorithms on mutexes use this trait via SFINAE.
166
167 This 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
176 The 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
196 The trait `is_recursive_mutex_sur_parole` is `false_type` by default and is specialized for the provide `recursive_mutex` and `timed_recursive_mutex`.
197
198 It 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
214 This 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
229 This 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
246 The __timed_lockable_concept__ refines the __lockable_concept__ to add support for
247 timeouts when trying to acquire the lock.
248
249 A 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
262 Lock 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
271 reached. 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
299 DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated.
300
301 Use 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
315 Lock 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
322 reached. 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
356 The __shared_lockable_concept__ is a refinement of the __timed_lockable_concept__ that
357 allows for ['shared ownership] as well as ['exclusive ownership]. This is the
358 standard multiple-reader / single-write model: at most one thread can have
359 exclusive ownership, and if any thread does have exclusive ownership, no other threads
360 can have shared or exclusive ownership. Alternatively, many threads may have
361 shared ownership.
362
363 A 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
379 Lock 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
414 specified 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
419 ownership 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
431 specified 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
436 ownership 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
459 DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated.
460
461 Use 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
472 Lock 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
479 specified 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
484 ownership 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
506 The __upgrade_lockable_concept__ is a refinement of the __shared_lockable_concept__ that allows for ['upgradable ownership] as well
507 as ['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
509 ownership]. The thread with ['upgradable ownership] may at any time attempt to upgrade that ownership to ['exclusive ownership]. If
510 no other threads have shared ownership, the upgrade is completed immediately, and the thread now has ['exclusive ownership], which
511 must be relinquished by a call to __unlock_ref__, just as if it had been acquired by a call to __lock_ref__.
512
513 If a thread with ['upgradable ownership] tries to upgrade whilst other threads have ['shared ownership], the attempt will fail and
514 the thread will block until ['exclusive ownership] can be acquired.
515
516 Ownership 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
518 downgraded to plain shared ownership.
519
520 A type `L` meets the __UpgradeLockable requirements if it meets the __SharedLockable
521 requirements 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
545 If `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION 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
555 Lock ownership acquired through a call to __lock_upgrade_ref__ must be released through a call to __unlock_upgrade_ref__. If the
556 ownership type is changed through a call to one of the `unlock_xxx_and_lock_yyy()` functions, ownership must be released through a
557 call 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.
621 Attempts to obtain upgrade lock ownership for the calling thread within the relative timeout specified by `rel_time`.
622 If 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()`).
623 The 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.
645 If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_lock_upgrade()`).
646 The 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.
669 For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
670 If 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_CONVERSION` 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.
693 The function attempts to atomically convert the ownership from shared to exclusive for the calling thread within the relative timeout specified by `rel_time`.
694 If 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()`).
695 The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
696 For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion.
697 If 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_CONVERSION` 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`.
720 If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `try_unlock_shared_and_lock()`).
721 The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object.
722 For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion.
723 If 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_CONVERSION` 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.
762 For this conversion to be successful, there must be no thread holding upgrade ownership of this object.
763 If 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_CONVERSION` 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.
786 The function attempts to atomically convert the ownership from shared to upgrade for the calling thread within the relative timeout specified by `rel_time`.
787 If 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()`).
788 The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
789 For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion.
790 If 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_CONVERSION` 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`.
813 If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_unlock_shared_and_lock_upgrade()`).
814 The function shall return before the absolute timeout specified by `abs_time` only if it has obtained upgrade ownership of the mutex object.
815 For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion.
816 If 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_CONVERSION` 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`
838 without 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
857 any 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.
875 For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
876 If 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.
899 The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the relative timeout specified by `rel_time`.
900 If 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()`).
901 The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object.
902 For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion.
903 If 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`.
925 If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`).
926 The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object.
927 For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion.
928 If 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
951 blocking.]]
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
992 These 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
1036 acquires ownership of the implementation of the __lockable_concept__ supplied as
1037 the constructor parameter. On destruction, the ownership is released. This
1038 provides simple RAII-style locking of a __lockable_concept_type__ object, to facilitate exception-safe
1039 locking and unlocking. In addition, the [link
1040 thread.synchronization.lock_guard.lock_guard.constructor_adopt `lock_guard(Lockable &
1041 m,boost::adopt_lock_t)` constructor] allows the __lock_guard__ object to
1042 take 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
1061 obtained 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__
1077 object 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
1172 A StrictLock is a lock that ensures that the associated mutex is locked during the lifetime of the lock.
1173
1174 A 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
1180 and BasicLockable<L::mutex_type>
1181
1182 where
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
1189 The 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
1195 As 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
1217 The 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_CONVERSION
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
1322 acquiring the lock until the __lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking
1323 fashion, 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
1326 Specializations 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
1331 An instance of __unique_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1332 pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1333 is destroyed, then the destructor will invoke [unlock_ref_link `mutex()->unlock()`].
1334
1335 The 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__
1406 returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1407 returns `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.
1422 If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
1423 Else `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_CONVERSION` 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`.
1447 If `sl.__owns_lock_shared_ref__()` returns `false`, sets `pm` to the return value of `sl.release()`.
1448 Else `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_CONVERSION` 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`.
1471 If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
1472 Else `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_CONVERSION` 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
1497 returns `true`.]]
1498
1499 [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_ref__
1500 returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1501 returns `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
1515 returns `true`.]]
1516
1517 [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_until
1518 returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1519 returns `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
1534 returns `true`.]]
1535
1536 [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_for
1537 returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__
1538 returns `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__
1564 object 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
1603 of the __lockable_concept_type__ object. If __owns_lock_ref__ would have returned `true`, it is the responsibility of the calling
1604 code 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
1607 is 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
1678 Like __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
1681 Like __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
1683 timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__
1684 object, or otherwise adopted a lock on the __lockable_concept_type__ object.
1685
1686 An instance of __shared_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1687 pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1688 is destroyed, then the destructor will invoke [unlock_shared_ref_link `mutex()->unlock_shared()`].
1689
1690 The member functions of __shared_lock__ are not thread-safe. In particular, __shared_lock__ is intended to model the shared
1691 ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
1692 state (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__
1761 returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__
1762 returns `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
1776 returns `true`.]]
1777
1778 [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_shared_ref__
1779 returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__
1780 returns `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__
1806 object 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
1845 of the __lockable_concept_type__ object. If __owns_lock_shared_ref__ would have returned `true`, it is the responsibility of the calling
1846 code 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
1849 is 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_CONVERSION
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
1926 Like __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
1929 Like __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
1931 timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__
1932 object, or otherwise adopted a lock on the __lockable_concept_type__ object.
1933
1934 An instance of __upgrade_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a
1935 pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object
1936 is destroyed, then the destructor will invoke [unlock_upgrade_ref_link `mutex()->unlock_upgrade()`].
1937
1938 The member functions of __upgrade_lock__ are not thread-safe. In particular, __upgrade_lock__ is intended to model the upgrade
1939 ownership of a __upgrade_lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
1940 state (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
1972 reference to an instance of __upgrade_lock__, if that instance has upgrade ownership on some __lockable_concept_type__ object, that
1973 ownership 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
2008 The member typedef `scoped_try_lock` is provided for each distinct
2009 `MutexType` as a typedef to a class with the preceding definition. The
2010 semantics of each constructor and member function are identical to
2011 those of [unique_lock_link `boost::unique_lock<MutexType>`] for the same `MutexType`, except
2012 that the constructor that takes a single reference to a mutex will
2013 call [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__
2121 object 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
2152 A nested strict lock is a scoped lock guard ensuring a mutex is locked on its
2153 scope, by taking ownership of a nesting lock, locking the mutex on construction if not already locked
2154 and 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.
2166 If 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__
2332 object 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__
2431 object 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
2531 access to that object through the get and set member functions, provided you
2532 pass a reference to a strict lock object.
2533
2534 Only 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
2751 access to that object through the get and set member functions, provided you
2752 pass a reference to a strict lock object.
2753
2754 Only 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
2902 acquires shared ownership of the implementation of the __shared_lockable_concept__ supplied as
2903 the constructor parameter. On destruction, the ownership is released. This
2904 provides simple RAII-style locking of a __shared_lockable_concept_type__ object, to facilitate exception-safe
2905 shared locking and unlocking.
2906 In addition, the `__shared_lock_guard_constructor_adopt(SharedLockable &m, boost::adopt_lock_t)` constructor allows the __shared_lock_guard object to
2907 take 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
2926 obtained 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
2971 An 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
3035 arguments in an unspecified and indeterminate order in a way that
3036 avoids deadlock. It is safe to call this function concurrently from
3037 multiple threads with the same mutexes (or other lockable objects) in
3038 different orders without risk of deadlock. If any of the __lock_ref__
3039 or __try_lock_ref__ operations on the supplied
3040 __lockable_concept_type__ objects throws an exception any locks
3041 acquired 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
3047 are 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
3063 supplied range in an unspecified and indeterminate order in a way that
3064 avoids deadlock. It is safe to call this function concurrently from
3065 multiple threads with the same mutexes (or other lockable objects) in
3066 different orders without risk of deadlock. If any of the __lock_ref__
3067 or __try_lock_ref__ operations on the __lockable_concept_type__
3068 objects in the supplied range throws an exception any locks acquired
3069 by 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
3075 supplied 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
3099 calls to __try_lock_ref__ returns `false` then all locks acquired are
3100 released and the zero-based index of the failed lock is returned.
3101
3102 If any of the __try_lock_ref__ operations on the supplied
3103 __lockable_concept_type__ objects throws an exception any locks
3104 acquired by the function will be released before the function exits.]]
3105
3106 [[Returns:] [`-1` if all the supplied __lockable_concept_type__ objects
3107 are now locked by the calling thread, the zero-based index of the
3108 object which could not be locked otherwise.]]
3109
3110 [[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the
3111 supplied __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
3115 thread. Otherwise any locks acquired by this function will have been
3116 released.]]
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
3133 calls to __try_lock_ref__ returns `false` then all locks acquired are
3134 released and an iterator referencing the failed lock is returned.
3135
3136 If any of the __try_lock_ref__ operations on the supplied
3137 __lockable_concept_type__ objects throws an exception any locks
3138 acquired by the function will be released before the function exits.]]
3139
3140 [[Returns:] [`end` if all the supplied __lockable_concept_type__
3141 objects are now locked by the calling thread, an iterator referencing
3142 the object which could not be locked otherwise.]]
3143
3144 [[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the
3145 supplied __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
3149 the calling thread, otherwise all locks acquired by the function have
3150 been 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