[/ (C) Copyright 2007-8 Anthony Williams. (C) Copyright 2011-12 Vicente J. Botet Escriba. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ] [section:mutex_concepts Mutex Concepts] A mutex object facilitates protection against data races and allows thread-safe synchronization of data between threads. A thread obtains ownership of a mutex object by calling one of the lock functions and relinquishes ownership by calling the corresponding unlock function. Mutexes may be either recursive or non-recursive, and may grant simultaneous ownership to one or many threads. __boost_thread__ supplies recursive and non-recursive mutexes with exclusive ownership semantics, along with a shared ownership (multiple-reader / single-writer) mutex. __boost_thread__ supports four basic concepts for lockable objects: __lockable_concept_type__, __timed_lockable_concept_type__, __shared_lockable_concept_type__ and __upgrade_lockable_concept_type__. Each mutex type implements one or more of these concepts, as do the various lock types. [section:basic_lockable `BasicLockable` Concept] // #include namespace boost { template class BasicLockable; // EXTENSION } The __BasicLockable concept models exclusive ownership. A type `L` meets the __BasicLockable requirements if the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`): * `m.__lock();` * `m.__unlock();` Lock ownership acquired through a call to __lock_ref__ must be released through a call to __unlock_ref__. [section:lock `m.lock();`] [variablelist [[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]] [[Effects:] [The current thread blocks until ownership can be obtained for the current thread.]] [[Synchronization:] [Prior `unlock()` operations on the same object synchronizes with this operation. ]] [[Postcondition:] [The current thread owns `m`.]] [[Return type:] [`void`.]] [[Throws:] [__lock_error__ if an error occurs.]] [[Error Conditions:] [ [*operation_not_permitted]: if the thread does not have the privilege to perform the operation. [*resource_deadlock_would_occur]: if the implementation detects that a deadlock would occur. [*device_or_resource_busy]: if the mutex is already locked and blocking is not possible. ]] [[Thread safety:] [If an exception is thrown then a lock shall not have been acquired for the current thread.]] ] [endsect] [section:unlock `m.unlock();`] [variablelist [[Requires:] [The current thread owns `m`.]] [[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership on the same object.]] [[Effects:] [Releases a lock on `m` by the current thread.]] [[Return type:] [`void`.]] [[Throws:] [Nothing.]] ] [endsect] [section:is_basic_lockable `is_basic_lockable` trait -- EXTENSION] // #include namespace boost { namespace sync { template class is_basic_lockable;// EXTENSION } } Some of the algorithms on mutexes use this trait via SFINAE. This trait is true_type if the parameter L meets the __Lockable requirements. [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.] [endsect] [endsect] [section:lockable `Lockable` Concept] // #include namespace boost { template class Lockable; } A type `L` meets the __Lockable requirements if it meets the __BasicLockable requirements and the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`): * `m.__try_lock()` Lock ownership acquired through a call to __try_lock_ref__ must be released through a call to __unlock_ref__. [section:try_lock `m.try_lock()`] [variablelist [[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]] [[Effects:] [Attempt to obtain ownership for the current thread without blocking.]] [[Synchronization:] [If `try_lock()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]] [[Note:] [Since `lock()` does not synchronize with a failed subsequent `try_lock()`, the visibility rules are weak enough that little would be known about the state after a failure, even in the absence of spurious failures.]] [[Return type:] [`bool`.]] [[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread owns the `m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:is_lockable `is_lockable` trait -- EXTENSION] // #include namespace boost { namespace sync { template class is_lockable;// EXTENSION } } Some of the algorithms on mutexes use this trait via SFINAE. This trait is true_type if the parameter L meets the __Lockable requirements. [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.] [endsect] [endsect] [section:recursive Recursive Lockable Concept] The user could require that the mutex passed to an algorithm is a recursive one. Whether a lockable is recursive or not can not be checked using template meta-programming. This is the motivation for the following trait. [section:is_recursive_mutex_sur_parole `is_recursive_mutex_sur_parole` trait -- EXTENSION] // #include namespace boost { namespace sync { template class is_recursive_mutex_sur_parole: false_type; // EXTENSION template<> class is_recursive_mutex_sur_parole: true_type; // EXTENSION template<> class is_recursive_mutex_sur_parole: true_type; // EXTENSION } } The trait `is_recursive_mutex_sur_parole` is `false_type` by default and is specialized for the provide `recursive_mutex` and `timed_recursive_mutex`. It should be specialized by the user providing other model of recursive lockable. [endsect] [section:is_recursive_basic_lockable `is_recursive_basic_lockable` trait -- EXTENSION] // #include namespace boost { namespace sync { template class is_recursive_basic_lockable;// EXTENSION } } This traits is true_type if is_basic_lockable and is_recursive_mutex_sur_parole. [endsect] [section:is_recursive_lockable `is_recursive_lockable` trait -- EXTENSION] // #include namespace boost { namespace sync { template class is_recursive_lockable;// EXTENSION } } This traits is true_type if is_lockable and is_recursive_mutex_sur_parole. [endsect] [endsect] [section:timed_lockable `TimedLockable` Concept] // #include namespace boost { template class TimedLockable; // EXTENSION } The __timed_lockable_concept__ refines the __lockable_concept__ to add support for timeouts when trying to acquire the lock. A type `L` meets the __TimedLockable requirements if it meets the __Lockable requirements and the following expressions are well-formed and have the specified semantics. [*Variables:] * `m` denotes a value of type `L`, * `rel_time` denotes a value of an instantiation of `chrono::duration`, and * `abs_time` denotes a value of an instantiation of `chrono::time_point`: [*Expressions:] * `m.__try_lock_for(rel_time)` * `m.__try_lock_until(abs_time)` Lock ownership acquired through a call to __try_lock_for or __try_lock_until must be released through a call to __unlock. [section:try_lock_until `m.try_lock_until(abs_time)`] [variablelist [[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]] [[Effects:] [Attempt to obtain ownership for the current thread. Blocks until ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as __try_lock_ref__.]] [[Synchronization:] [If `try_lock_until()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]] [[Return type:] [`bool`.]] [[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread owns `m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:try_lock_for `m.try_lock_for(rel_time)`] [variablelist [[Requires:] [The calling thread doesn't owns the mutex if the mutex is not recursive.]] [[Effects:] [As-if `__try_lock_until(chrono::steady_clock::now() + rel_time)`.]] [[Synchronization:] [If `try_lock_for()` returns true, prior `unlock()` operations on the same object synchronize with this operation.]] ] [endsect] [warning DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated. Use instead __try_lock_for, __try_lock_until. ] [*Variables:] * `rel_time` denotes a value of an instantiation of an unspecified `DurationType` arithmetic compatible with `boost::system_time`, and * `abs_time` denotes a value of an instantiation of `boost::system_time`: [*Expressions:] * `m.__timed_lock_duration(rel_time)` * `m.__timed_lock(abs_time)` Lock ownership acquired through a call to __timed_lock_ref__ must be released through a call to __unlock_ref__. [section:timed_lock `m.timed_lock(abs_time)`] [variablelist [[Effects:] [Attempt to obtain ownership for the current thread. Blocks until ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as __try_lock_ref__.]] [[Returns:] [`true` if ownership was obtained for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread owns `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:timed_lock_duration `m.timed_lock(rel_time)`] [variablelist [[Effects:] [As-if [timed_lock_ref_link `timed_lock(boost::get_system_time()+rel_time)`].]] ] [endsect] [endsect] [section:shared_lockable `SharedLockable` Concept -- C++14] // #include namespace boost { template class SharedLockable; // C++14 } The __shared_lockable_concept__ is a refinement of the __timed_lockable_concept__ that allows for ['shared ownership] as well as ['exclusive ownership]. This is the standard multiple-reader / single-write model: at most one thread can have exclusive ownership, and if any thread does have exclusive ownership, no other threads can have shared or exclusive ownership. Alternatively, many threads may have shared ownership. A type `L` meets the __SharedLockable requirements if it meets the __TimedLockable requirements and the following expressions are well-formed and have the specified semantics. [*Variables:] * `m` denotes a value of type `L`, * `rel_time` denotes a value of an instantiation of `chrono::duration`, and * `abs_time` denotes a value of an instantiation of `chrono::time_point`: [*Expressions:] * `m.__lock_shared();` * `m.__try_lock_shared()` * `m.__try_lock_shared_for(rel_time)` * `m.__try_lock_shared_until(abs_time)` * `m.__unlock_shared();` Lock ownership acquired through a call to __lock_shared_ref__, __try_lock_shared_ref__, __try_lock_shared_for or __try_lock_shared_until must be released through a call to __unlock_shared_ref__. [section:lock_shared `m.lock_shared()`] [variablelist [[Effects:] [The current thread blocks until shared ownership can be obtained for the current thread.]] [[Postcondition:] [The current thread has shared ownership of `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:try_lock_shared `m.try_lock_shared()`] [variablelist [[Effects:] [Attempt to obtain shared ownership for the current thread without blocking.]] [[Returns:] [`true` if shared ownership was obtained for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has shared ownership of `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:try_lock_shared_for `m.try_lock_shared_for(rel_time)`] [variablelist [[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the specified duration is elapsed. If the specified duration is already elapsed, behaves as __try_lock_shared_ref__.]] [[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has shared ownership of `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:try_lock_shared_until `m.try_lock_shared_until(abs_time))`] [variablelist [[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as __try_lock_shared_ref__.]] [[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has shared ownership of `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:unlock_shared `m.unlock_shared()`] [variablelist [[Precondition:] [The current thread has shared ownership of `m`.]] [[Effects:] [Releases shared ownership of `m` by the current thread.]] [[Postcondition:] [The current thread no longer has shared ownership of `m`.]] [[Throws:] [Nothing]] ] [endsect] [warning DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated. Use instead __try_lock_shared_for, __try_lock_shared_until. ] [*Variables:] * `abs_time` denotes a value of an instantiation of `boost::system_time`: [*Expressions:] * `m.timed_lock_shared(abs_time);` Lock ownership acquired through a call to __timed_lock_shared_ref__ must be released through a call to __unlock_shared_ref__. [section:timed_lock_shared `m.timed_lock_shared(abs_time)`] [variablelist [[Effects:] [Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as __try_lock_shared_ref__.]] [[Returns:] [`true` if shared ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has shared ownership of `m`.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [endsect] [section:upgrade_lockable `UpgradeLockable` Concept -- EXTENSION] // #include namespace boost { template class UpgradeLockable; // EXTENSION } The __upgrade_lockable_concept__ is a refinement of the __shared_lockable_concept__ that allows for ['upgradable ownership] as well as ['shared ownership] and ['exclusive ownership]. This is an extension to the multiple-reader / single-write model provided by the __shared_lockable_concept__: a single thread may have ['upgradable ownership] at the same time as others have ['shared ownership]. The thread with ['upgradable ownership] may at any time attempt to upgrade that ownership to ['exclusive ownership]. If no other threads have shared ownership, the upgrade is completed immediately, and the thread now has ['exclusive ownership], which must be relinquished by a call to __unlock_ref__, just as if it had been acquired by a call to __lock_ref__. If a thread with ['upgradable ownership] tries to upgrade whilst other threads have ['shared ownership], the attempt will fail and the thread will block until ['exclusive ownership] can be acquired. Ownership can also be ['downgraded] as well as ['upgraded]: exclusive ownership of an implementation of the __upgrade_lockable_concept__ can be downgraded to upgradable ownership or shared ownership, and upgradable ownership can be downgraded to plain shared ownership. A type `L` meets the __UpgradeLockable requirements if it meets the __SharedLockable requirements and the following expressions are well-formed and have the specified semantics. [*Variables:] * `m` denotes a value of type `L`, * `rel_time` denotes a value of an instantiation of `chrono::duration`, and * `abs_time` denotes a value of an instantiation of `chrono::time_point`: [*Expressions:] * `m.__lock_upgrade();` * `m.__unlock_upgrade()` * `m.__try_lock_upgrade()` * `m.__try_lock_upgrade_for(rel_time)` * `m.__try_lock_upgrade_until(abs_time)` * `m.__unlock_and_lock_shared()` * `m.__unlock_and_lock_upgrade();` * `m.__unlock_upgrade_and_lock();` * `m.__try_unlock_upgrade_and_lock()` * `m.__try_unlock_upgrade_and_lock_for(rel_time)` * `m.__try_unlock_upgrade_and_lock_until(abs_time)` * `m.__unlock_upgrade_and_lock_shared();` If `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS is defined the following expressions are also required: * `m.__try_unlock_shared_and_lock();` * `m.__try_unlock_shared_and_lock_for(rel_time);` * `m.__try_unlock_shared_and_lock_until(abs_time);` * `m.__try_unlock_shared_and_lock_upgrade();` * `m.__try_unlock_shared_and_lock_upgrade_for(rel_time);` * `m.__try_unlock_shared_and_lock_upgrade_until(abs_time);` Lock ownership acquired through a call to __lock_upgrade_ref__ must be released through a call to __unlock_upgrade_ref__. If the ownership type is changed through a call to one of the `unlock_xxx_and_lock_yyy()` functions, ownership must be released through a call to the unlock function corresponding to the new level of ownership. [section:lock_upgrade `m.lock_upgrade()`] [variablelist [[Precondition:] [The calling thread has no ownership of the mutex. ]] [[Effects:] [The current thread blocks until upgrade ownership can be obtained for the current thread.]] [[Postcondition:] [The current thread has upgrade ownership of `m`.]] [[Synchronization:] [Prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]] [[Throws:] [__lock_error__ if an error occurs.]] ] [endsect] [section:unlock_upgrade `m.unlock_upgrade()`] [variablelist [[Precondition:] [The current thread has upgrade ownership of `m`.]] [[Effects:] [Releases upgrade ownership of `m` by the current thread.]] [[Postcondition:] [The current thread no longer has upgrade ownership of `m`.]] [[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership on the same object.]] [[Throws:] [Nothing]] ] [endsect] [section:try_lock_upgrade `m.try_lock_upgrade()`] [variablelist [[Precondition:] [The calling thread has no ownership of the mutex. ]] [[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.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[Synchronization:] [If `__try_lock_upgrade()` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]] [[Throws:] [Nothing]] ] [endsect] [section:try_lock_upgrade_for `m.try_lock_upgrade_for(rel_time)`] [variablelist [[Precondition:] [The calling thread has no ownership of the mutex. ]] [[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. Attempts to obtain upgrade lock ownership for the calling thread within the relative timeout specified by `rel_time`. If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain ownership without blocking (as if by calling `__try_lock_upgrade()`). The function returns within the timeout specified by `rel_time` only if it has obtained upgrade ownership of the mutex object.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[Synchronization:] [If `__try_lock_upgrade_for(rel_time)` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]] [[Throws:] [Nothing]] [[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]] ] [endsect] [section:try_lock_upgrade_until `m.try_lock_upgrade_until(abs_time)`] [variablelist [[Precondition:] [The calling thread has no ownership of the mutex. ]] [[Effects:] [The function attempts to obtain upgrade ownership of the mutex. If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_lock_upgrade()`). The function returns before the absolute timeout specified by `abs_time` only if it has obtained upgrade ownership of the mutex object.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[Synchronization:] [If `__try_lock_upgrade_until(abs_time)` returns true, prior `__unlock_upgrade()` operations on the same object synchronize with this operation.]] [[Throws:] [Nothing]] [[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]] ] [endsect] [section:try_unlock_shared_and_lock `m.try_unlock_shared_and_lock()`] [variablelist [[Precondition:] [The calling thread must hold a shared lock on the mutex.]] [[Effects:] [The function attempts to atomically convert the ownership from shared to exclusive for the calling thread without blocking. For this conversion to be successful, this thread must be the only thread holding any ownership of the lock. If the conversion is not successful, the shared ownership of m is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[Synchronization:] [If `__try_unlock_shared_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:try_unlock_shared_and_lock_for `m.try_unlock_shared_and_lock_for(rel_time)`] [variablelist [[Precondition:] [The calling thread shall hold a shared lock on the mutex.]] [[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. The function attempts to atomically convert the ownership from shared to exclusive for the calling thread within the relative timeout specified by `rel_time`. If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain exclusive ownership without blocking (as if by calling `try_unlock_shared_and_lock()`). The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object. For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion. If the conversion is not successful, the shared ownership of the mutex is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:try_unlock_shared_and_lock_until `m.try_unlock_shared_and_lock_until(abs_time)`] [variablelist [[Precondition:] [The calling thread shall hold a shared lock on the mutex.]] [[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`. If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `try_unlock_shared_and_lock()`). The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object. For this conversion to be successful, this thread must be the only thread holding any ownership of the lock at the moment of conversion. If the conversion is not successful, the shared ownership of the mutex is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:unlock_and_lock_shared `m.unlock_and_lock_shared()`] [variablelist [[Precondition:] [The calling thread shall hold an exclusive lock on `m`.]] [[Effects:] [Atomically converts the ownership from exclusive to shared for the calling thread.]] [[Postcondition:] [The current thread has shared ownership of `m`.]] [[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership of the same object.]] [[Throws:] [Nothing]] ] [endsect] [section:try_unlock_shared_and_lock_upgrade `m.try_unlock_shared_and_lock_upgrade()`] [variablelist [[Precondition:] [The calling thread shall hold a shared lock on the mutex.]] [[Effects:] [The function attempts to atomically convert the ownership from shared to upgrade for the calling thread without blocking. For this conversion to be successful, there must be no thread holding upgrade ownership of this object. If the conversion is not successful, the shared ownership of the mutex is retained.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:try_unlock_shared_and_lock_upgrade_for `m.try_unlock_shared_and_lock_upgrade_for(rel_time)`] [variablelist [[Precondition:] [The calling thread shall hold a shared lock on the mutex.]] [[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. The function attempts to atomically convert the ownership from shared to upgrade for the calling thread within the relative timeout specified by `rel_time`. If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_unlock_shared_and_lock_upgrade()`). The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object. For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion. If the conversion is not successful, the shared ownership of m is retained.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:try_unlock_shared_and_lock_upgrade_until `m.try_unlock_shared_and_lock_upgrade_until(abs_time)`] [variablelist [[Precondition:] [The calling thread shall hold a shared lock on the mutex.]] [[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`. If `abs_time` has already passed, the function attempts to obtain upgrade ownership without blocking (as if by calling `__try_unlock_shared_and_lock_upgrade()`). The function shall return before the absolute timeout specified by `abs_time` only if it has obtained upgrade ownership of the mutex object. For this conversion to be successful, there must be no thread holding upgrade ownership of this object at the moment of conversion. If the conversion is not successful, the shared ownership of the mutex is retained.]] [[Returns:] [`true` if upgrade ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has upgrade ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[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]] ] [endsect] [section:unlock_and_lock_upgrade `m.unlock_and_lock_upgrade()`] [variablelist [[Precondition:] [The current thread has exclusive ownership of `m`.]] [[Effects:] [Atomically releases exclusive ownership of `m` by the current thread and acquires upgrade ownership of `m` without blocking.]] [[Postcondition:] [The current thread has upgrade ownership of `m`.]] [[Synchronization:] [This operation synchronizes with subsequent lock operations that obtain ownership of the same object.]] [[Throws:] [Nothing]] ] [endsect] [section:unlock_upgrade_and_lock `m.unlock_upgrade_and_lock()`] [variablelist [[Precondition:] [The current thread has upgrade ownership of `m`.]] [[Effects:] [Atomically releases upgrade ownership of `m` by the current thread and acquires exclusive ownership of `m`. If any other threads have shared ownership, blocks until exclusive ownership can be acquired.]] [[Postcondition:] [The current thread has exclusive ownership of `m`.]] [[Synchronization:] [This operation synchronizes with prior `__unlock_shared()` and subsequent lock operations that obtain ownership of the same object.]] [[Throws:] [Nothing]] ] [endsect] [section:try_unlock_upgrade_and_lock `m.try_unlock_upgrade_and_lock()`] [variablelist [[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]] [[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread without blocking. For this conversion to be successful, this thread must be the only thread holding any ownership of the lock. If the conversion is not successful, the upgrade ownership of m is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[Synchronization:] [If `__try_unlock_upgrade_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]] [[Throws:] [Nothing]] [[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]] ] [endsect] [section:try_unlock_upgrade_and_lock_for `m.try_unlock_upgrade_and_lock_for(rel_time)`] [variablelist [[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]] [[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. The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the relative timeout specified by `rel_time`. If the time specified by `rel_time` is less than or equal to `rel_time.zero()`, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`). The function shall return within the timeout specified by `rel_time` only if it has obtained exclusive ownership of the mutex object. For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion. If the conversion is not successful, the upgrade ownership of m is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]] ] [endsect] [section:try_unlock_upgrade_and_lock_until `m.try_unlock_upgrade_and_lock_until(abs_time)`] [variablelist [[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]] [[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`. If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`). The function shall return before the absolute timeout specified by `abs_time` only if it has obtained exclusive ownership of the mutex object. For this conversion to be successful, this thread shall be the only thread holding any ownership of the lock at the moment of conversion. If the conversion is not successful, the upgrade ownership of m is retained.]] [[Returns:] [`true` if exclusive ownership was acquired for the current thread, `false` otherwise.]] [[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]] [[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. ]] [[Throws:] [Nothing]] [[Notes:] [Available only if `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]] ] [endsect] [section:unlock_upgrade_and_lock_shared `m.unlock_upgrade_and_lock_shared()`] [variablelist [[Precondition:] [The current thread has upgrade ownership of `m`.]] [[Effects:] [Atomically releases upgrade ownership of `m` by the current thread and acquires shared ownership of `m` without blocking.]] [[Postcondition:] [The current thread has shared ownership of `m`.]] [[Synchronization:] [This operation synchronizes with prior `unlock_shared()` and subsequent lock operations that obtain ownership of the same object.]] [[Throws:] [Nothing]] ] [endsect] [endsect] [endsect] [section:lock_option Lock Options] // #include // #include namespace boost { struct defer_lock_t {}; struct try_to_lock_t {}; struct adopt_lock_t {}; constexpr defer_lock_t defer_lock; constexpr try_to_lock_t try_to_lock; constexpr adopt_lock_t adopt_lock; [section:lock_tags Lock option tags] #include #include struct defer_lock_t {}; struct try_to_lock_t {}; struct adopt_lock_t {}; const defer_lock_t defer_lock; const try_to_lock_t try_to_lock; const adopt_lock_t adopt_lock; These tags are used in scoped locks constructors to specify a specific behavior. *`defer_lock_t`: is used to construct the scoped lock without locking it. *`try_to_lock_t`: is used to construct the scoped lock trying to lock it. *`adopt_lock_t`: is used to construct the scoped lock without locking it but adopting ownership. [endsect] [endsect] [section:lock_guard Lock Guard] // #include // #include namespace boost { template class lock_guard #if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD template lock_guard make_lock_guard(Lockable& mtx); // EXTENSION template lock_guard make_lock_guard(Lockable& mtx, adopt_lock_t); // EXTENSION #endif } [section:lock_guard Class template `lock_guard`] // #include // #include template class lock_guard { public: explicit lock_guard(Lockable& m_); lock_guard(Lockable& m_,boost::adopt_lock_t); ~lock_guard(); }; __lock_guard__ is very simple: on construction it acquires ownership of the implementation of the __lockable_concept__ supplied as the constructor parameter. On destruction, the ownership is released. This provides simple RAII-style locking of a __lockable_concept_type__ object, to facilitate exception-safe locking and unlocking. In addition, the [link thread.synchronization.lock_guard.lock_guard.constructor_adopt `lock_guard(Lockable & m,boost::adopt_lock_t)` constructor] allows the __lock_guard__ object to take ownership of a lock already held by the current thread. [section:constructor `lock_guard(Lockable & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:constructor_adopt `lock_guard(Lockable & m,boost::adopt_lock_t)`] [variablelist [[Precondition:] [The current thread owns a lock on `m` equivalent to one obtained by a call to [lock_ref_link `m.lock()`].]] [[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:destructor `~lock_guard()`] [variablelist [[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__ object passed to the constructor.]] [[Throws:] [Nothing.]] ] [endsect] [endsect] [section:make_lock_guard Non Member Function `make_lock_guard`] template lock_guard make_lock_guard(Lockable& m); // EXTENSION [variablelist [[Returns:] [a lock_guard as if initialized with `{m}`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:make_lock_guard_adopt Non Member Function `make_lock_guard`] template lock_guard make_lock_guard(Lockable& m, adopt_lock_t); // EXTENSION [variablelist [[Returns:] [a lock_guard as if initialized with `{m, adopt_lock}`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [endsect] [section:with_lock_guard With Lock Guard] // #include namespace boost { template auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward(args)...)); } [section:with_lock_guard Non Member Function `with_lock_guard`] template auto with_lock_guard( Lockable& m, Function&& func, Args&&... args ) -> decltype(func(boost::forward(args)...)); [variablelist [[Precondition:] [`m` must be in unlocked state]] [[Effects:] [call `func` in scope locked by `m`]] [[Returns:] [Result of `func(args...)` call]] [[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]] [[Postcondition:] [`m` is in unlocked state]] [[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]] [[] [Without rvalue references support calling class method with `boost::bind` must be const]] [[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]] ] [endsect] [endsect] [section:lock_concepts Lock Concepts] [section:StrictLock StrictLock -- EXTENSION] // #include namespace boost { template class StrictLock; } A StrictLock is a lock that ensures that the associated mutex is locked during the lifetime of the lock. A type `L` meets the StrictLock requirements if the following expressions are well-formed and have the specified semantics * `L::mutex_type` * `is_strict_lock` * `cl.owns_lock(m);` and BasicLockable where * `cl` denotes a value of type `L const&`, * `m` denotes a value of type `L::mutex_type const*`, [section: mutex_type `L::mutex_type`] The type L::mutex_type denotes the mutex that is locked by this lock. [endsect] [/ mutex_type] [section:is_strict_lock_sur_parole `is_strict_lock_sur_parole`] As the semantic "ensures that the associated mutex is locked during the lifetime of the lock. " can not be described by syntactic requirements a `is_strict_lock_sur_parole` trait must be specialized by the user defining the lock so that the following assertion is true: is_strict_lock_sur_parole::value == true [endsect] [/ is_strict_lock_sur_parole] [section:owns_lock `cl.owns_lock(m);`] [variablelist [[Return Type:] [`bool`]] [[Returns:] [Whether the strict lock is locking the mutex `m`]] [[Throws:] [Nothing.]] ] [endsect] [/ owns_lock] [section Models] The following classes are models of `StrictLock`: * strict_lock: ensured by construction, * nested_strict_lock: "sur parole" as the user could use adopt_lock_t on unique_lock constructor overload without having locked the mutex, * __lock_guard__: "sur parole" as the user could use adopt_lock_t constructor overload without having locked the mutex. [endsect] [/ Models] [endsect] [/ Strict Lock] [endsect] [/ Lock Concepts] [section:locks Lock Types] // #include // #include namespace boost { template class unique_lock; template void swap(unique_lock & lhs, unique_lock & rhs); template class shared_lock; // C++14 template void swap(shared_lock& lhs,shared_lock& rhs); // C++14 template class upgrade_lock; // EXTENSION template void swap(upgrade_lock & lhs, upgrade_lock & rhs); // EXTENSION template class upgrade_to_unique_lock; // EXTENSION } [section:unique_lock Class template `unique_lock`] // #include // #include template class unique_lock { public: typedef Lockable mutex_type; unique_lock() noexcept; explicit unique_lock(Lockable& m_); unique_lock(Lockable& m_,adopt_lock_t); unique_lock(Lockable& m_,defer_lock_t) noexcept; unique_lock(Lockable& m_,try_to_lock_t); #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS unique_lock(shared_lock&& sl, try_to_lock_t); // C++14 template unique_lock(shared_lock&& sl, const chrono::time_point& abs_time); // C++14 template unique_lock(shared_lock&& sl, const chrono::duration& rel_time); // C++14 #endif template unique_lock(Mutex& mtx, const chrono::time_point& t); template unique_lock(Mutex& mtx, const chrono::duration& d); ~unique_lock(); unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; unique_lock(unique_lock&& other) noexcept; explicit unique_lock(upgrade_lock&& other) noexcept; // EXTENSION unique_lock& operator=(unique_lock&& other) noexcept; void swap(unique_lock& other) noexcept; Lockable* release() noexcept; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); explicit operator bool() const noexcept; bool owns_lock() const noexcept; mutex_type* mutex() const noexcept; #if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO unique_lock(Lockable& m_,system_time const& target_time); template bool timed_lock(TimeDuration const& relative_time); bool timed_lock(::boost::system_time const& absolute_time); #endif }; __unique_lock__ is more complex than __lock_guard__: not only does it provide for RAII-style locking, it also allows for deferring acquiring the lock until the __lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking fashion, or with a timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__ object, or otherwise adopted a lock on the __lockable_concept_type__ object. Specializations of __unique_lock__ model the __TimedLockable concept if the supplied `Lockable` type itself models __TimedLockable concept (e.g. `boost::unique_lock`), or the __Lockable concept if the supplied `Lockable` type itself models __Lockable concept (e.g. `boost::unique_lock`), or the __BasicLockable concept if the supplied `Lockable` type itself models __BasicLockable concept. An instance of __unique_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object is destroyed, then the destructor will invoke [unlock_ref_link `mutex()->unlock()`]. The member functions of __unique_lock__ are not thread-safe. In particular, __unique_lock__ is intended to model the ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock state (including the destructor) must be called by the same thread that acquired ownership of the lock state. [section:defaultconstructor `unique_lock()`] [variablelist [[Effects:] [Creates a lock object with no associated mutex.]] [[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor `unique_lock(Lockable & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]] [[Postcondition:] [__owns_lock_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:constructor_adopt `unique_lock(Lockable & m,boost::adopt_lock_t)`] [variablelist [[Precondition:] [The current thread owns an exclusive lock on `m`.]] [[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]] [[Postcondition:] [__owns_lock_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_defer `unique_lock(Lockable & m,boost::defer_lock_t)`] [variablelist [[Effects:] [Stores a reference to `m`.]] [[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_try `unique_lock(Lockable & m,boost::try_to_lock_t)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [try_lock_ref_link `m.try_lock()`], and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_ref__ returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__ returns `false`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_sh_try `unique_lock(shared_lock&& sl, try_to_lock_t)`] [variablelist [[Requires:] [The supplied `Mutex` type must implement `__try_unlock_shared_and_lock()`.]] [[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. If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`. Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unlock_shared_and_lock()` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]] [[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()->try_unlock_shared_and_lock()` returns `false`, `sl` is not modified.]] [[Throws:] [Nothing.]] [[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]] ] [endsect] [section:constructor_sh_until `unique_lock(shared_lock&&, const chrono::time_point&)`] template unique_lock(shared_lock&& sl, const chrono::time_point& abs_time); [variablelist [[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_until(abs_time)`.]] [[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`. If `sl.__owns_lock_shared_ref__()` returns `false`, sets `pm` to the return value of `sl.release()`. Else `sl.__owns_lock_shared_ref__()` returns `true`, and in this case if `sl.mutex()->__try_unlock_shared_and_lock_until(abs_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]] [[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_until(abs_time)` returns `false`, `sl` is not modified.]] [[Throws:] [Nothing.]] [[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]] ] [endsect] [section:constructor_sh_for `unique_lock(shared_lock&&, const chrono::duration&)`] template unique_lock(shared_lock&& sl, const chrono::duration& rel_time) [variablelist [[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_for(rel_time)`.]] [[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`. If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`. Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]] [[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `false`, `sl` is not modified.]] [[Postcondition:] [.]] [[Throws:] [Nothing.]] [[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]] ] [endsect] [section:constructor_abs_time `unique_lock(Lockable & m,boost::system_time const& abs_time)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [timed_lock_ref_link `m.timed_lock(abs_time)`], and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_ref__ returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__ returns `false`.]] [[Throws:] [Any exceptions thrown by the call to [timed_lock_ref_link `m.timed_lock(abs_time)`].]] ] [endsect] [section:constructor_time_point `template unique_lock(Lockable & m,const chrono::time_point& abs_time)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes `m.__try_lock_until(abs_time)`, and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_until returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__ returns `false`.]] [[Throws:] [Any exceptions thrown by the call to `m.__try_lock_until(abs_time)`.]] ] [endsect] [section:constructor_duration `template unique_lock(Lockable & m,const chrono::duration& abs_time)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes `m.__try_lock_for(rel_time)`, and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_for returned `true`, then __owns_lock_ref__ returns `true`, otherwise __owns_lock_ref__ returns `false`.]] [[Throws:] [Any exceptions thrown by the call to `m.__try_lock_for(rel_time)`.]] ] [endsect] [section:destructor `~unique_lock()`] [variablelist [[Effects:] [Invokes __mutex_func_ref__`->`[unlock_ref_link `unlock()`] if __owns_lock_ref__ returns `true`.]] [[Throws:] [Nothing.]] ] [endsect] [section:owns_lock `bool owns_lock() const`] [variablelist [[Returns:] [`true` if the `*this` owns the lock on the __lockable_concept_type__ object associated with `*this`.]] [[Throws:] [Nothing.]] ] [endsect] [section:mutex `Lockable* mutex() const noexcept`] [variablelist [[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this`, or `NULL` if there is no such object.]] [[Throws:] [Nothing.]] ] [endsect] [section:explicit_bool_conversion `explicit operator bool() const`] [variablelist [[Returns:] [`__owns_lock_ref__()`.]] [[Throws:] [Nothing.]] ] [endsect] [section:release `Lockable* release()`] [variablelist [[Effects:] [The association between `*this` and the __lockable_concept_type__ object is removed, without affecting the lock state of the __lockable_concept_type__ object. If __owns_lock_ref__ would have returned `true`, it is the responsibility of the calling code to ensure that the __lockable_concept_type__ is correctly unlocked.]] [[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this` at the point of the call, or `NULL` if there is no such object.]] [[Throws:] [Nothing.]] [[Postcondition:] [`*this` is no longer associated with any __lockable_concept_type__ object. __mutex_func_ref__ returns `NULL` and __owns_lock_ref__ returns `false`.]] ] [endsect] [endsect] [section:shared_lock Class template `shared_lock` - C++14] // #include // #include template class shared_lock { public: typedef Lockable mutex_type; // Shared locking shared_lock(); explicit shared_lock(Lockable& m_); shared_lock(Lockable& m_,adopt_lock_t); shared_lock(Lockable& m_,defer_lock_t); shared_lock(Lockable& m_,try_to_lock_t); template shared_lock(Mutex& mtx, const chrono::time_point& t); template shared_lock(Mutex& mtx, const chrono::duration& d); ~shared_lock(); shared_lock(shared_lock const&) = delete; shared_lock& operator=(shared_lock const&) = delete; shared_lock(shared_lock && other); shared_lock& operator=(shared_lock && other); void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); // Conversion from upgrade locking explicit shared_lock(upgrade_lock && other); // EXTENSION // Conversion from exclusive locking explicit shared_lock(unique_lock && other); // Setters void swap(shared_lock& other); mutex_type* release() noexcept; // Getters explicit operator bool() const; bool owns_lock() const; mutex_type mutex() const; #if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO shared_lock(Lockable& m_,system_time const& target_time); bool timed_lock(boost::system_time const& target_time); #endif }; Like __unique_lock__, __shared_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied __lockable_concept_type__ object, locking an instance of __shared_lock__ acquires shared ownership. Like __unique_lock__, not only does it provide for RAII-style locking, it also allows for deferring acquiring the lock until the __lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking fashion, or with a timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__ object, or otherwise adopted a lock on the __lockable_concept_type__ object. An instance of __shared_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object is destroyed, then the destructor will invoke [unlock_shared_ref_link `mutex()->unlock_shared()`]. The member functions of __shared_lock__ are not thread-safe. In particular, __shared_lock__ is intended to model the shared ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock state (including the destructor) must be called by the same thread that acquired ownership of the lock state. [section:defaultconstructor `shared_lock()`] [variablelist [[Effects:] [Creates a lock object with no associated mutex.]] [[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor `shared_lock(Lockable & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [lock_shared_ref_link `m.lock_shared()`].]] [[Postcondition:] [__owns_lock_shared_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Any exception thrown by the call to [lock_shared_ref_link `m.lock_shared()`].]] ] [endsect] [section:constructor_adopt `shared_lock(Lockable & m,boost::adopt_lock_t)`] [variablelist [[Precondition:] [The current thread owns an exclusive lock on `m`.]] [[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]] [[Postcondition:] [__owns_lock_shared_ref__ returns `true`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_defer `shared_lock(Lockable & m,boost::defer_lock_t)`] [variablelist [[Effects:] [Stores a reference to `m`.]] [[Postcondition:] [__owns_lock_shared_ref__ returns `false`. __mutex_func_ref__ returns `&m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_try `shared_lock(Lockable & m,boost::try_to_lock_t)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [try_lock_shared_ref_link `m.try_lock_shared()`], and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __try_lock_shared_ref__ returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__ returns `false`.]] [[Throws:] [Nothing.]] ] [endsect] [section:constructor_abs_time `shared_lock(Lockable & m,boost::system_time const& abs_time)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [timed_lock_shared_ref_link `m.timed_lock(abs_time)`], and takes ownership of the lock state if the call returns `true`.]] [[Postcondition:] [__mutex_func_ref__ returns `&m`. If the call to __timed_lock_shared_ref__ returned `true`, then __owns_lock_shared_ref__ returns `true`, otherwise __owns_lock_shared_ref__ returns `false`.]] [[Throws:] [Any exceptions thrown by the call to [timed_lock_shared_ref_link `m.timed_lock(abs_time)`].]] ] [endsect] [section:destructor `~shared_lock()`] [variablelist [[Effects:] [Invokes __mutex_func_ref__`->`[unlock_shared_ref_link `unlock_shared()`] if __owns_lock_shared_ref__ returns `true`.]] [[Throws:] [Nothing.]] ] [endsect] [section:owns_lock `bool owns_lock() const`] [variablelist [[Returns:] [`true` if the `*this` owns the lock on the __lockable_concept_type__ object associated with `*this`.]] [[Throws:] [Nothing.]] ] [endsect] [section:mutex `Lockable* mutex() const`] [variablelist [[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this`, or `NULL` if there is no such object.]] [[Throws:] [Nothing.]] ] [endsect] [section:explicit_operator_bool `explicit operator bool() const`] [variablelist [[Returns:] [__owns_lock_shared_ref__.]] [[Throws:] [Nothing.]] ] [endsect] [section:release `Lockable* release()`] [variablelist [[Effects:] [The association between `*this` and the __lockable_concept_type__ object is removed, without affecting the lock state of the __lockable_concept_type__ object. If __owns_lock_shared_ref__ would have returned `true`, it is the responsibility of the calling code to ensure that the __lockable_concept_type__ is correctly unlocked.]] [[Returns:] [A pointer to the __lockable_concept_type__ object associated with `*this` at the point of the call, or `NULL` if there is no such object.]] [[Throws:] [Nothing.]] [[Postcondition:] [`*this` is no longer associated with any __lockable_concept_type__ object. __mutex_func_ref__ returns `NULL` and __owns_lock_shared_ref__ returns `false`.]] ] [endsect] [endsect] [section:upgrade_lock Class template `upgrade_lock` - EXTENSION] // #include // #include template class upgrade_lock { public: typedef Lockable mutex_type; // Upgrade locking upgrade_lock(); explicit upgrade_lock(mutex_type& m_); upgrade_lock(mutex_type& m, defer_lock_t) noexcept; upgrade_lock(mutex_type& m, try_to_lock_t); upgrade_lock(mutex_type& m, adopt_lock_t); template upgrade_lock(mutex_type& m, const chrono::time_point& abs_time); template upgrade_lock(mutex_type& m, const chrono::duration& rel_time); ~upgrade_lock(); upgrade_lock(const upgrade_lock& other) = delete; upgrade_lock& operator=(const upgrade_lock & other) = delete; upgrade_lock(upgrade_lock && other); upgrade_lock& operator=(upgrade_lock && other); void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS // Conversion from shared locking upgrade_lock(shared_lock&& sl, try_to_lock_t); template upgrade_lock(shared_lock&& sl, const chrono::time_point& abs_time); template upgrade_lock(shared_lock&& sl, const chrono::duration& rel_time); #endif // Conversion from exclusive locking explicit upgrade_lock(unique_lock && other); // Setters void swap(upgrade_lock& other); mutex_type* release() noexcept; // Getters explicit operator bool() const; bool owns_lock() const; mutex_type mutex() const; }; Like __unique_lock__, __upgrade_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied __lockable_concept_type__ object, locking an instance of __upgrade_lock__ acquires upgrade ownership. Like __unique_lock__, not only does it provide for RAII-style locking, it also allows for deferring acquiring the lock until the __lock_ref__ member function is called explicitly, or trying to acquire the lock in a non-blocking fashion, or with a timeout. Consequently, __unlock_ref__ is only called in the destructor if the lock object has locked the __lockable_concept_type__ object, or otherwise adopted a lock on the __lockable_concept_type__ object. An instance of __upgrade_lock__ is said to ['own] the lock state of a __lockable_concept_type__ `m` if __mutex_func_ref__ returns a pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] the lock state of a __lockable_concept_type__ object is destroyed, then the destructor will invoke [unlock_upgrade_ref_link `mutex()->unlock_upgrade()`]. The member functions of __upgrade_lock__ are not thread-safe. In particular, __upgrade_lock__ is intended to model the upgrade ownership of a __upgrade_lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock state (including the destructor) must be called by the same thread that acquired ownership of the lock state. [endsect] [section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION] // #include // #include template class upgrade_to_unique_lock { public: typedef Lockable mutex_type; explicit upgrade_to_unique_lock(upgrade_lock& m_); ~upgrade_to_unique_lock(); upgrade_to_unique_lock(upgrade_to_unique_lock const& other) = delete; upgrade_to_unique_lock& operator=(upgrade_to_unique_lock const& other) = delete; upgrade_to_unique_lock(upgrade_to_unique_lock && other); upgrade_to_unique_lock& operator=(upgrade_to_unique_lock && other); void swap(upgrade_to_unique_lock& other); explicit operator bool() const; bool owns_lock() const; mutex_type* mutex() const; }; __upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a reference to an instance of __upgrade_lock__, if that instance has upgrade ownership on some __lockable_concept_type__ object, that ownership is upgraded to exclusive ownership. When the __upgrade_to_unique_lock__ instance is destroyed, the ownership of the __lockable_concept_type__ is downgraded back to ['upgrade ownership]. [endsect] [section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED] class MutexType::scoped_try_lock { private: MutexType::scoped_try_lock(MutexType::scoped_try_lock& other); MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock& other); public: MutexType::scoped_try_lock(); explicit MutexType::scoped_try_lock(MutexType& m); MutexType::scoped_try_lock(MutexType& m_,adopt_lock_t); MutexType::scoped_try_lock(MutexType& m_,defer_lock_t); MutexType::scoped_try_lock(MutexType& m_,try_to_lock_t); MutexType::scoped_try_lock(MutexType::scoped_try_lock&& other); MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock&& other); void swap(MutexType::scoped_try_lock&& other); void lock(); bool try_lock(); void unlock(); MutexType* mutex() const; MutexType* release(); explicit operator bool() const; bool owns_lock() const; }; The member typedef `scoped_try_lock` is provided for each distinct `MutexType` as a typedef to a class with the preceding definition. The semantics of each constructor and member function are identical to those of [unique_lock_link `boost::unique_lock`] for the same `MutexType`, except that the constructor that takes a single reference to a mutex will call [try_lock_ref_link `m.try_lock()`] rather than `m.lock()`. [endsect] [endsect] [/ [section:other_mutex Other Mutex Types] [section: reverse_mutex Class template `reverse_mutex`] //#include namespace boost { template class reverse_mutex { public: typedef BasicLockable mutex_type; reverse_mutex(reverse_mutex const&) = delete; reverse_mutex& operator=(reverse_mutex const&) = delete; explicit reverse_mutex(mutex_type& m_); ~reverse_mutex(); void lock(); void unlock(); }; } __reverse_mutex reverse the operations of a __BasicLockable, that unlocks the lockable when `lock()` is called and locks it when `unlock()` is called. [endsect] [endsect] ] [section:other_locks Other Lock Types - EXTENSION] [section:strict_locks Strict Locks] // #include // #include namespace boost { template class strict_lock; template class nested_strict_lock; template struct is_strict_lock_sur_parole >; template struct is_strict_lock_sur_parole >; #if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK template strict_lock make_strict_lock(Lockable& mtx); #endif #if ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK template nested_strict_lock make_nested_strict_lock(Lock& lk); #endif } [section:strict_lock Class template `strict_lock`] // #include // #include template class strict_lock { public: typedef BasicLockable mutex_type; strict_lock(strict_lock const& m_) = delete; strict_lock& operator=(strict_lock const& m_) = delete; explicit strict_lock(mutex_type& m_); ~strict_lock(); bool owns_lock(mutex_type const* l) const noexcept; }; __strict_lock is a model of __StrictLock. __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. [heading See also __lock_guard__] [section:constructor `strict_lock(Lockable & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:destructor `~strict_lock()`] [variablelist [[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__ object passed to the constructor.]] [[Throws:] [Nothing.]] ] [endsect] [endsect] [section:nested_strict_lock Class template `nested_strict_lock`] // #include // #include template class nested_strict_lock { public: typedef BasicLockable mutex_type; nested_strict_lock(nested_strict_lock const& m_) = delete; nested_strict_lock& operator=(nested_strict_lock const& m_) = delete; explicit nested_strict_lock(Lock& lk), ~nested_strict_lock() noexcept; bool owns_lock(mutex_type const* l) const noexcept; }; __nested_strict_lock is a model of __StrictLock. A nested strict lock is a scoped lock guard ensuring a mutex is locked on its scope, by taking ownership of a nesting lock, locking the mutex on construction if not already locked and restoring the ownership to the nesting lock on destruction. [heading See also __strict_lock, __unique_lock] [section:constructor `nested_strict_lock(Lock & lk)`] [variablelist [[Requires:] [`lk.mutex() != null_ptr`.]] [[Effects:] [Stores the reference to the lock parameter `lk` and takes ownership on it. If the lock doesn't owns the mutex lock it. ]] [[Postcondition:] [`owns_lock(lk.mutex())`.]] [[Throws:] [ - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr - Any exception that @c lk.lock() can throw. ]] ] [endsect] [section:destructor `~nested_strict_lock() noexcept`] [variablelist [[Effects:] [Restores ownership to the nesting lock.]] ] [endsect] [section:owns_lock `bool owns_lock(mutex_type const* l) const noexcept`] [variablelist [[Return:] [Whether if this lock is locking that mutex.]] ] [endsect] [endsect] [section:make_strict_lock Non Member Function `make_strict_lock`] template strict_lock make_strict_lock(Lockable& m); // EXTENSION [variablelist [[Returns:] [a strict_lock as if initialized with `{m}`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:make_nested_strict_lock Non Member Function `make_nested_strict_lock`] template nested_strict_lock make_nested_strict_lock(Lock& lk); // EXTENSION [variablelist [[Returns:] [a nested_strict_lock as if initialized with `{lk}`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `lk.lock()`].]] ] [endsect] [endsect] [section:lock_ptrs Locking pointers] // #include // #include namespace boost { template class strict_lock_ptr; template class const_strict_lock_ptr; } [/ template class unique_lock_ptr; template class const_unique_lock_ptr; ] [section:const_strict_lock_ptr Class template `const_strict_lock_ptr `] // #include // #include template class const_strict_lock_ptr { public: typedef T value_type; typedef Lockable mutex_type; const_strict_lock_ptr(const_strict_lock_ptr const& m_) = delete; const_strict_lock_ptr& operator=(const_strict_lock_ptr const& m_) = delete; const_strict_lock_ptr(T const& val, Lockable & mtx); const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag); ~const_strict_lock_ptr(); const T* operator->() const; const T& operator*() const; }; [section:constructor `const_strict_lock_ptr(T const&,Lockable&)`] const_strict_lock_ptr(T const& val, Lockable & m); [variablelist [[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:constructor_adopt `const_strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`] const_strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag); [variablelist [[Effects:] [Stores a reference to it and to the value type `val`.]] [[Throws:] [Nothing.]] ] [endsect] [section:destructor `~const_strict_lock_ptr()`] ~const_strict_lock_ptr(); [variablelist [[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__ object passed to the constructor.]] [[Throws:] [Nothing.]] ] [endsect] [section:indir `operator->() const`] const T* operator->() const; [variablelist [[Return:] [return a constant pointer to the protected value.]] [[Throws:] [Nothing.]] ] [endsect] [section:deref `operator*() const`] const T& operator*() const; [variablelist [[Return:] [return a constant reference to the protected value.]] [[Throws:] [Nothing.]] ] [endsect] [endsect] [/ const_strict_lock_ptr ] [section:strict_lock_ptr Class template `strict_lock_ptr`] // #include // #include template class strict_lock_ptr : public const_strict_lock_ptr { public: strict_lock_ptr(strict_lock_ptr const& m_) = delete; strict_lock_ptr& operator=(strict_lock_ptr const& m_) = delete; strict_lock_ptr(T & val, Lockable & mtx); strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag); ~strict_lock_ptr(); T* operator->(); T& operator*(); }; [section:constructor `strict_lock_ptr(T const&,Lockable&)`] strict_lock_ptr(T const& val, Lockable & m); [variablelist [[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]] [[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] ] [endsect] [section:constructor_adopt `strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`] strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag); [variablelist [[Effects:] [Stores a reference to it and to the value type `val`.]] [[Throws:] [Nothing.]] ] [endsect] [section:destructor `~strict_lock_ptr()`] ~ strict_lock_ptr(); [variablelist [[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__ object passed to the constructor.]] [[Throws:] [Nothing.]] ] [endsect] [section:indir `operator->()`] T* operator->(); [variablelist [[Return:] [return a pointer to the protected value.]] [[Throws:] [Nothing.]] ] [endsect] [section:deref `operator*()`] T& operator*(); [variablelist [[Return:] [return a reference to the protected value.]] [[Throws:] [Nothing.]] ] [endsect] [endsect] [/ strict_lock_ptr ] [endsect] [/ lock_ptrs ] [section Externally Locked] // #include template class externally_locked; template class externally_locked; template void swap(externally_locked & lhs, externally_locked & rhs); [section:externally_locked Template Class `externally_locked`] // #include template class externally_locked { //BOOST_CONCEPT_ASSERT(( CopyConstructible )); BOOST_CONCEPT_ASSERT(( BasicLockable )); public: typedef MutexType mutex_type; externally_locked(mutex_type& mtx, const T& obj); externally_locked(mutex_type& mtx,T&& obj); explicit externally_locked(mutex_type& mtx); externally_locked(externally_locked const& rhs); externally_locked(externally_locked&& rhs); externally_locked& operator=(externally_locked const& rhs); externally_locked& operator=(externally_locked&& rhs); // observers T& get(strict_lock& lk); const T& get(strict_lock& lk) const; template T& get(nested_strict_lock& lk); template const T& get(nested_strict_lock& lk) const; template T& get(Lock& lk); template T const& get(Lock& lk) const; mutex_type* mutex() const noexcept; // modifiers void lock(); void unlock(); bool try_lock(); void swap(externally_locked&); }; `externally_locked` is a model of __Lockable, it cloaks an object of type `T`, and actually provides full access to that object through the get and set member functions, provided you pass a reference to a strict lock object. Only the specificities respect to __Lockable are described here. [///////////////////////////////] [section:constructor1 `externally_locked(mutex_type&, const T&)`] externally_locked(mutex_type& mtx, const T& obj); [variablelist [[Requires:] [T is a model of CopyConstructible.]] [[Effects:] [Constructs an externally locked object copying the cloaked type.]] [[Throws:] [Any exception thrown by the call to `T(obj)`.]] ] [endsect] [///////////////////////////////] [section:constructor2 `externally_locked(mutex_type&, T&&)`] externally_locked(mutex_type& mtx,T&& obj); [variablelist [[Requires:] [T is a model of Movable.]] [[Effects:] [Constructs an externally locked object by moving the cloaked type.]] [[Throws:] [Any exception thrown by the call to `T(obj)`.]] ] [endsect] [///////////////////////////////] [section:constructor3 `externally_locked(mutex_type&)`] externally_locked(mutex_type& mtx); [variablelist [[Requires:] [T is a model of DefaultConstructible.]] [[Effects:] [Constructs an externally locked object by default constructing the cloaked type.]] [[Throws:] [Any exception thrown by the call to `T()`.]] ] [endsect] [///////////////////////////////] [section:constructor4 `externally_locked(externally_locked&&)`] externally_locked(externally_locked&& rhs); [variablelist [[Requires:] [T is a model of Movable.]] [[Effects:] [Move constructs an externally locked object by moving the cloaked type and copying the mutex reference ]] [[Throws:] [Any exception thrown by the call to `T(T&&)`.]] ] [endsect] [///////////////////////////////] [section:constructor5 `externally_locked(externally_locked&)`] externally_locked(externally_locked& rhs); [variablelist [[Requires:] [T is a model of Copyable.]] [[Effects:] [Copy constructs an externally locked object by copying the cloaked type and copying the mutex reference ]] [[Throws:] [Any exception thrown by the call to `T(T&)`.]] ] [endsect] [///////////////////////////////] [section:assign4 `externally_locked(externally_locked&&)`] externally_locked& operator=(externally_locked&& rhs); [variablelist [[Requires:] [T is a model of Movable.]] [[Effects:] [Move assigns an externally locked object by moving the cloaked type and copying the mutex reference ]] [[Throws:] [Any exception thrown by the call to `T::operator=(T&&)`.]] ] [endsect] [///////////////////////////////] [section:assign5 `externally_locked(externally_locked&)`] externally_locked& operator=(externally_locked const& rhs); [variablelist [[Requires:] [T is a model of Copyable.]] [[Effects:] [Copy assigns an externally locked object by copying the cloaked type and copying the mutex reference ]] [[Throws:] [Any exception thrown by the call to `T::operator=(T&)`.]] ] [endsect] [///////////////////////////////] [section:get1 `get(strict_lock&)`] T& get(strict_lock& lk); const T& get(strict_lock& lk) const; [variablelist [[Requires:] [The `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [///////////////////////////////] [section:get2 `get(nested_strict_lock&)`] template T& get(nested_strict_lock& lk); template const T& get(nested_strict_lock& lk) const; [variablelist [[Requires:] [`is_same` and the `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [///////////////////////////////] [section:get3 `get(Lock&)`] template T& get(Lock& lk); template T const& get(Lock& lk) const; [variablelist [[Requires:] [`Lock` is a model of __StrictLock, `is_same` and the `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [endsect] [section:externally_locked_ref Template Class `externally_locked`] // #include template class externally_locked { //BOOST_CONCEPT_ASSERT(( CopyConstructible )); BOOST_CONCEPT_ASSERT(( BasicLockable )); public: typedef MutexType mutex_type; externally_locked(mutex_type& mtx, T& obj); explicit externally_locked(mutex_type& mtx); externally_locked(externally_locked const& rhs) noexcept; externally_locked(externally_locked&& rhs) noexcept; externally_locked& operator=(externally_locked const& rhs) noexcept; externally_locked& operator=(externally_locked&& rhs) noexcept; // observers T& get(strict_lock& lk); const T& get(strict_lock& lk) const; template T& get(nested_strict_lock& lk); template const T& get(nested_strict_lock& lk) const; template T& get(Lock& lk); template T const& get(Lock& lk) const; mutex_type* mutex() const noexcept; // modifiers void lock(); void unlock(); bool try_lock(); void swap(externally_locked&) noexcept; }; `externally_locked` is a model of __Lockable, it cloaks an object of type `T`, and actually provides full access to that object through the get and set member functions, provided you pass a reference to a strict lock object. Only the specificities respect to __Lockable are described here. [///////////////////////////////] [section:constructor1 `externally_locked(mutex_type&, T&)`] externally_locked(mutex_type& mtx, T& obj) noexcept; [variablelist [[Effects:] [Constructs an externally locked object copying the cloaked reference.]] ] [endsect] [///////////////////////////////] [section:constructor4 `externally_locked(externally_locked&&)`] externally_locked(externally_locked&& rhs) noexcept; [variablelist [[Effects:] [Moves an externally locked object by moving the cloaked type and copying the mutex reference ]] ] [endsect] [///////////////////////////////] [section:assign4 `externally_locked(externally_locked&&)`] externally_locked& operator=(externally_locked&& rhs); [variablelist [[Effects:] [Move assigns an externally locked object by copying the cloaked reference and copying the mutex reference ]] ] [endsect] [///////////////////////////////] [section:assign5 `externally_locked(externally_locked&)`] externally_locked& operator=(externally_locked const& rhs); [variablelist [[Requires:] [T is a model of Copyable.]] [[Effects:] [Copy assigns an externally locked object by copying the cloaked reference and copying the mutex reference ]] [[Throws:] [Any exception thrown by the call to `T::operator=(T&)`.]] ] [endsect] [///////////////////////////////] [section:get1 `get(strict_lock&)`] T& get(strict_lock& lk); const T& get(strict_lock& lk) const; [variablelist [[Requires:] [The `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [///////////////////////////////] [section:get2 `get(nested_strict_lock&)`] template T& get(nested_strict_lock& lk); template const T& get(nested_strict_lock& lk) const; [variablelist [[Requires:] [`is_same` and the `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [///////////////////////////////] [section:get3 `get(Lock&)`] template T& get(Lock& lk); template T const& get(Lock& lk) const; [variablelist [[Requires:] [`Lock` is a model of __StrictLock, `is_same` and the `lk` parameter must be locking the associated mutex.]] [[Returns:] [A reference to the cloaked object ]] [[Throws:] [__lock_error__ if `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined and the run-time preconditions are not satisfied .]] ] [endsect] [endsect] [///////////////////////////////] [section:swap `swap(externally_locked&, externally_locked&)`] template void swap(externally_locked & lhs, externally_locked & rhs) [endsect] [endsect] [section:shared_lock_guard Class template `shared_lock_guard`] // #include namespace boost { template class shared_lock_guard { public: shared_lock_guard(shared_lock_guard const&) = delete; shared_lock_guard& operator=(shared_lock_guard const&) = delete; explicit shared_lock_guard(SharedLockable& m_); shared_lock_guard(SharedLockable& m_,boost::adopt_lock_t); ~shared_lock_guard(); }; } __shared_lock_guard is very simple: on construction it acquires shared ownership of the implementation of the __shared_lockable_concept__ supplied as the constructor parameter. On destruction, the ownership is released. This provides simple RAII-style locking of a __shared_lockable_concept_type__ object, to facilitate exception-safe shared locking and unlocking. In addition, the `__shared_lock_guard_constructor_adopt(SharedLockable &m, boost::adopt_lock_t)` constructor allows the __shared_lock_guard object to take shared ownership of a lock already held by the current thread. [section:constructor `shared_lock_guard(SharedLockable & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes `m.__lock_shared()`.]] [[Throws:] [Any exception thrown by the call to `m.__lock_shared()`.]] ] [endsect] [section:constructor_adopt `shared_lock_guard(SharedLockable & m,boost::adopt_lock_t)`] [variablelist [[Precondition:] [The current thread owns a lock on `m` equivalent to one obtained by a call to `m.__lock_shared()`.]] [[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of `m`.]] [[Throws:] [Nothing.]] ] [endsect] [section:destructor `~shared_lock_guard()`] [variablelist [[Effects:] [Invokes `m.__unlock_shared()` on the __shared_lockable_concept_type__ object passed to the constructor.]] [[Throws:] [Nothing.]] ] [endsect] [endsect] [section:reverse_lock Class template `reverse_lock`] // #include namespace boost { template class reverse_lock { public: reverse_lock(reverse_lock const&) = delete; reverse_lock& operator=(reverse_lock const&) = delete; explicit reverse_lock(Lock& m_); ~reverse_lock(); }; } __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. An instance of __reverse_lock doesn't ['own] the lock never. [section:constructor `reverse_lock(Lock & m)`] [variablelist [[Effects:] [Stores a reference to `m`. Invokes `m.__unlock()` if `m` owns his lock and then stores the mutex by calling `m.release()`.]] [[Postcondition:] [`!m.__owns_lock() && m.mutex()==0`.]] [[Throws:] [Any exception thrown by the call to `m.__unlock()`.]] ] [endsect] [section:destructor `~reverse_lock()`] [variablelist [[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.]] [[Throws:] [Any exception thrown by `mtx->__lock()`.]] [[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.]] ] [endsect] [endsect] [/ reverse_lock<>] [endsect] [section:lock_functions Lock functions] [section:lock_multiple Non-member function `lock(Lockable1,Lockable2,...)`] // #include // #include namespace boost { template void lock(Lockable1& l1,Lockable2& l2); template void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3); template void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4); template void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4,Lockable5& l5); } [variablelist [[Effects:] [Locks the __lockable_concept_type__ objects supplied as arguments in an unspecified and indeterminate order in a way that avoids deadlock. It is safe to call this function concurrently from multiple threads for any set of mutexes (or other lockable objects) in any order without risk of deadlock. If any of the __lock_ref__ or __try_lock_ref__ operations on the supplied __lockable_concept_type__ objects throws an exception any locks acquired by the function will be released before the function exits.]] [[Throws:] [Any exceptions thrown by calling __lock_ref__ or __try_lock_ref__ on the supplied __lockable_concept_type__ objects.]] [[Postcondition:] [All the supplied __lockable_concept_type__ objects are locked by the calling thread.]] ] [endsect] [section:lock_range Non-member function `lock(begin,end)` // EXTENSION] template void lock(ForwardIterator begin,ForwardIterator end); [variablelist [[Preconditions:] [The `value_type` of `ForwardIterator` must implement the __lockable_concept__]] [[Effects:] [Locks all the __lockable_concept_type__ objects in the supplied range in an unspecified and indeterminate order in a way that avoids deadlock. It is safe to call this function concurrently from multiple threads for any set of mutexes (or other lockable objects) in any order without risk of deadlock. If any of the __lock_ref__ or __try_lock_ref__ operations on the __lockable_concept_type__ objects in the supplied range throws an exception any locks acquired by the function will be released before the function exits.]] [[Throws:] [Any exceptions thrown by calling __lock_ref__ or __try_lock_ref__ on the supplied __lockable_concept_type__ objects.]] [[Postcondition:] [All the __lockable_concept_type__ objects in the supplied range are locked by the calling thread.]] ] [endsect] [section:try_lock_multiple Non-member function `try_lock(Lockable1,Lockable2,...)`] template int try_lock(Lockable1& l1,Lockable2& l2); template int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3); template int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4); template int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4,Lockable5& l5); [variablelist [[Effects:] [Calls __try_lock_ref__ on each of the __lockable_concept_type__ objects supplied as arguments. If any of the calls to __try_lock_ref__ returns `false` then all locks acquired are released and the zero-based index of the failed lock is returned. If any of the __try_lock_ref__ operations on the supplied __lockable_concept_type__ objects throws an exception any locks acquired by the function will be released before the function exits.]] [[Returns:] [`-1` if all the supplied __lockable_concept_type__ objects are now locked by the calling thread, the zero-based index of the object which could not be locked otherwise.]] [[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the supplied __lockable_concept_type__ objects.]] [[Postcondition:] [If the function returns `-1`, all the supplied __lockable_concept_type__ objects are locked by the calling thread. Otherwise any locks acquired by this function will have been released.]] ] [endsect] [section:try_lock_range Non-member function `try_lock(begin,end)` // EXTENSION] template ForwardIterator try_lock(ForwardIterator begin,ForwardIterator end); [variablelist [[Preconditions:] [The `value_type` of `ForwardIterator` must implement the __lockable_concept__]] [[Effects:] [Calls __try_lock_ref__ on each of the __lockable_concept_type__ objects in the supplied range. If any of the calls to __try_lock_ref__ returns `false` then all locks acquired are released and an iterator referencing the failed lock is returned. If any of the __try_lock_ref__ operations on the supplied __lockable_concept_type__ objects throws an exception any locks acquired by the function will be released before the function exits.]] [[Returns:] [`end` if all the supplied __lockable_concept_type__ objects are now locked by the calling thread, an iterator referencing the object which could not be locked otherwise.]] [[Throws:] [Any exceptions thrown by calling __try_lock_ref__ on the supplied __lockable_concept_type__ objects.]] [[Postcondition:] [If the function returns `end` then all the __lockable_concept_type__ objects in the supplied range are locked by the calling thread, otherwise all locks acquired by the function have been released.]] ] [endsect] [endsect] [section:lock_factories Lock Factories - EXTENSION] namespace boost { template unique_lock make_unique_lock(Lockable& mtx); // EXTENSION template unique_lock make_unique_lock(Lockable& mtx, adopt_lock_t); // EXTENSION template unique_lock make_unique_lock(Lockable& mtx, defer_lock_t); // EXTENSION template unique_lock make_unique_lock(Lockable& mtx, try_to_lock_t); // EXTENSION #if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS) template std::tuple ...> make_unique_locks(Lockable& ...mtx); // EXTENSION #endif } [section:make_unique_lock Non Member Function `make_unique_lock(Lockable&)`] template unique_lock make_unique_lock(Lockable& mtx); // EXTENSION [variablelist [[Returns:] [a __unique_lock as if initialized with `unique_lock(mtx)`.]] [[Throws:] [Any exception thrown by the call to `__unique_lock(mtx)`.]] ] [endsect] [section:make_unique_lock_t Non Member Function `make_unique_lock(Lockable&,tag)`] template unique_lock make_unique_lock(Lockable& mtx, adopt_lock_t tag); // EXTENSION template unique_lock make_unique_lock(Lockable& mtx, defer_lock_t tag); // EXTENSION template unique_lock make_unique_lock(Lockable& mtx, try_to_lock_t tag); // EXTENSION [variablelist [[Returns:] [a __unique_lock as if initialized with `unique_lock(mtx, tag)`.]] [[Throws:] [Any exception thrown by the call to `__unique_lock(mtx, tag)`.]] ] [endsect] [section:make_unique_locks Non Member Function `make_unique_locks(Lockable& ...)`] template std::tuple ...> make_unique_locks(Lockable& ...mtx); // EXTENSION [variablelist [[Effect:] [Locks all the mutexes.]] [[Returns:] [a std::tuple of unique __unique_lock owning each one of the mutex.]] [[Throws:] [Any exception thrown by `boost::lock(mtx...)`.]] ] [endsect] [endsect]