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