thread/doc/mutex_concepts.qbk

3236 lines
101 KiB
Plaintext

[/
(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 <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
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 <boost/thread/lockable_traits.hpp>
namespace boost
{
namespace sync
{
template<typename L>
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 <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
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 <boost/thread/lockable_traits.hpp>
namespace boost
{
namespace sync
{
template<typename L>
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 <boost/thread/lockable_traits.hpp>
namespace boost
{
namespace sync
{
template<typename L>
class is_recursive_mutex_sur_parole: false_type; // EXTENSION
template<>
class is_recursive_mutex_sur_parole<recursive_mutex>: true_type; // EXTENSION
template<>
class is_recursive_mutex_sur_parole<timed_recursive_mutex>: 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 <boost/thread/lockable_traits.hpp>
namespace boost
{
namespace sync
{
template<typename L>
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 <boost/thread/lockable_traits.hpp>
namespace boost
{
namespace sync
{
template<typename L>
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 <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
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 <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
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 <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
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 <boost/thread/locks.hpp>
// #include <boost/thread/locks_options.hpp>
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 <boost/thread/locks.hpp>
#include <boost/thread/locks_options.hpp>
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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_guard.hpp>
namespace boost
{
template<typename Lockable>
class lock_guard
#if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
template <typename Lockable>
lock_guard<Lockable> make_lock_guard(Lockable& mtx); // EXTENSION
template <typename Lockable>
lock_guard<Lockable> make_lock_guard(Lockable& mtx, adopt_lock_t); // EXTENSION
#endif
}
[section:lock_guard Class template `lock_guard`]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_guard.hpp>
template<typename Lockable>
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 <typename Lockable>
lock_guard<Lockable> 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 <typename Lockable>
lock_guard<Lockable> 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 <boost/thread/with_lock_guard.hpp>
namespace boost
{
template <class Lockable, class Function, class... Args>
auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
}
[section:with_lock_guard Non Member Function `with_lock_guard`]
template <class Lockable, class Function, class... Args>
auto with_lock_guard(
Lockable& m,
Function&& func,
Args&&... args
) -> decltype(func(boost::forward<Args>(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 <boost/thread/lock_concepts.hpp>
namespace boost
{
template<typename Lock>
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<L>`
* `cl.owns_lock(m);`
and BasicLockable<L::mutex_type>
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<L>`]
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<L>::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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
namespace boost
{
template<typename Lockable>
class unique_lock;
template<typename Mutex>
void swap(unique_lock <Mutex>& lhs, unique_lock <Mutex>& rhs);
template<typename Lockable>
class shared_lock; // C++14
template<typename Mutex>
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs); // C++14
template<typename Lockable>
class upgrade_lock; // EXTENSION
template<typename Mutex>
void swap(upgrade_lock <Mutex>& lhs, upgrade_lock <Mutex>& rhs); // EXTENSION
template <class Mutex>
class upgrade_to_unique_lock; // EXTENSION
}
[section:unique_lock Class template `unique_lock`]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
template<typename Lockable>
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<mutex_type>&& sl, try_to_lock_t); // C++14
template <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time); // C++14
template <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time); // C++14
#endif
template <class Clock, class Duration>
unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t);
template <class Rep, class Period>
unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d);
~unique_lock();
unique_lock(unique_lock const&) = delete;
unique_lock& operator=(unique_lock const&) = delete;
unique_lock(unique_lock<Lockable>&& other) noexcept;
explicit unique_lock(upgrade_lock<Lockable>&& other) noexcept; // EXTENSION
unique_lock& operator=(unique_lock<Lockable>&& other) noexcept;
void swap(unique_lock& other) noexcept;
Lockable* release() noexcept;
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& 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<typename TimeDuration>
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<boost::timed_mutex>`), or the __Lockable concept if the supplied `Lockable` type itself models
__Lockable concept (e.g. `boost::unique_lock<boost::mutex>`), 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<mutex_type>&& 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<mutex_type>&&, const chrono::time_point<Clock, Duration>&)`]
template <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& 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<mutex_type>&&, const chrono::duration<Rep, Period>&)`]
template <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& 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 <class Clock, class Duration> unique_lock(Lockable & m,const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period> unique_lock(Lockable & m,const chrono::duration<Rep, Period>& 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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
template<typename Lockable>
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 <class Clock, class Duration>
shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t);
template <class Rep, class Period>
shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d);
~shared_lock();
shared_lock(shared_lock const&) = delete;
shared_lock& operator=(shared_lock const&) = delete;
shared_lock(shared_lock<Lockable> && other);
shared_lock& operator=(shared_lock<Lockable> && other);
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
// Conversion from upgrade locking
explicit shared_lock(upgrade_lock<Lockable> && other); // EXTENSION
// Conversion from exclusive locking
explicit shared_lock(unique_lock<Lockable> && 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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
template<typename Lockable>
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 <class Clock, class Duration>
upgrade_lock(mutex_type& m,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
upgrade_lock(mutex_type& m,
const chrono::duration<Rep, Period>& rel_time);
~upgrade_lock();
upgrade_lock(const upgrade_lock& other) = delete;
upgrade_lock& operator=(const upgrade_lock<Lockable> & other) = delete;
upgrade_lock(upgrade_lock<Lockable> && other);
upgrade_lock& operator=(upgrade_lock<Lockable> && other);
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
// Conversion from shared locking
upgrade_lock(shared_lock<mutex_type>&& sl, try_to_lock_t);
template <class Clock, class Duration>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time);
#endif
// Conversion from exclusive locking
explicit upgrade_lock(unique_lock<Lockable> && 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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
template <class Lockable>
class upgrade_to_unique_lock
{
public:
typedef Lockable mutex_type;
explicit upgrade_to_unique_lock(upgrade_lock<Lockable>& 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<Lockable> const& other) = delete;
upgrade_to_unique_lock(upgrade_to_unique_lock<Lockable> && other);
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Lockable> && 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<MutexType>& other);
MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock<MutexType>& 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<MutexType>&& other);
MutexType::scoped_try_lock& operator=(MutexType::scoped_try_lock<MutexType>&& 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<MutexType>`] 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 <boost/thread/reverse_mutex.hpp>
namespace boost
{
template<typename BasicLockable>
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 <boost/thread/locks.hpp>
// #include <boost/thread/strict_lock.hpp>
namespace boost
{
template<typename Lockable>
class strict_lock;
template <typename Lock>
class nested_strict_lock;
template <typename Lockable>
struct is_strict_lock_sur_parole<strict_lock<Lockable> >;
template <typename Lock>
struct is_strict_lock_sur_parole<nested_strict_lock<Lock> >;
#if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
template <typename Lockable>
strict_lock<Lockable> make_strict_lock(Lockable& mtx);
#endif
#if ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK
template <typename Lock>
nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk);
#endif
}
[section:strict_lock Class template `strict_lock`]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/strict_lock.hpp>
template<typename BasicLockable>
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 <boost/thread/locks.hpp>
// #include <boost/thread/strict_lock.hpp>
template<typename Lock>
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 <typename Lockable>
strict_lock<Lockable> 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 <typename Lock>
nested_strict_lock<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 <boost/thread/synchroniezd_value.hpp>
// #include <boost/thread/strict_lock_ptr.hpp>
namespace boost
{
template<typename T, typename Lockable = mutex>
class strict_lock_ptr;
template<typename T, typename Lockable = mutex>
class const_strict_lock_ptr;
}
[/
template<typename T, typename Lockable = mutex>
class unique_lock_ptr;
template<typename T, typename Lockable = mutex>
class const_unique_lock_ptr;
]
[section:const_strict_lock_ptr Class template `const_strict_lock_ptr `]
// #include <boost/thread/synchroniezd_value.hpp>
// #include <boost/thread/strict_lock_ptr.hpp>
template <typename T, typename Lockable = mutex>
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 <boost/thread/synchroniezd_value.hpp>
// #include <boost/thread/strict_lock_ptr.hpp>
template <typename T, typename Lockable = mutex>
class strict_lock_ptr : public const_strict_lock_ptr<T,Lockable>
{
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 <boost/thread/externally_locked.hpp>
template <class T, typename MutexType = boost::mutex>
class externally_locked;
template <class T, typename MutexType>
class externally_locked<T&, MutexType>;
template <typename T, typename MutexType>
void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs);
[section:externally_locked Template Class `externally_locked`]
// #include <boost/thread/externally_locked.hpp>
template <class T, typename MutexType>
class externally_locked
{
//BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
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<mutex_type>& lk);
const T& get(strict_lock<mutex_type>& lk) const;
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
template <class Lock>
const T& get(nested_strict_lock<Lock>& lk) const;
template <class Lock>
T& get(Lock& lk);
template <class Lock>
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<mutex_type>&)`]
T& get(strict_lock<mutex_type>& lk);
const T& get(strict_lock<mutex_type>& 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<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
template <class Lock>
const T& get(nested_strict_lock<Lock>& lk) const;
[variablelist
[[Requires:] [`is_same<mutex_type, typename Lock::mutex_type>` 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 <class Lock>
T& get(Lock& lk);
template <class Lock>
T const& get(Lock& lk) const;
[variablelist
[[Requires:] [`Lock` is a model of __StrictLock, `is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
[[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<T&>`]
// #include <boost/thread/externally_locked.hpp>
template <class T, typename MutexType>
class externally_locked<T&, MutexType>
{
//BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
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<mutex_type>& lk);
const T& get(strict_lock<mutex_type>& lk) const;
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
template <class Lock>
const T& get(nested_strict_lock<Lock>& lk) const;
template <class Lock>
T& get(Lock& lk);
template <class Lock>
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<T&>(mutex_type&, T&)`]
externally_locked<T&>(mutex_type& mtx, T& obj) noexcept;
[variablelist
[[Effects:] [Constructs an externally locked object copying the cloaked reference.]]
]
[endsect]
[///////////////////////////////]
[section:constructor4 `externally_locked<T&>(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<mutex_type>&)`]
T& get(strict_lock<mutex_type>& lk);
const T& get(strict_lock<mutex_type>& 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<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
template <class Lock>
const T& get(nested_strict_lock<Lock>& lk) const;
[variablelist
[[Requires:] [`is_same<mutex_type, typename Lock::mutex_type>` 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 <class Lock>
T& get(Lock& lk);
template <class Lock>
T const& get(Lock& lk) const;
[variablelist
[[Requires:] [`Lock` is a model of __StrictLock, `is_same<mutex_type, typename Lock::mutex_type>` and the `lk` parameter must be locking the associated mutex.]]
[[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 <typename T, typename MutexType>
void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs)
[endsect]
[endsect]
[section:shared_lock_guard Class template `shared_lock_guard`]
// #include <boost/thread/shared_lock_guard.hpp>
namespace boost
{
template<typename SharedLockable>
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 <boost/thread/reverse_lock.hpp>
namespace boost
{
template<typename Lock>
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 <boost/thread/locks.hpp>
// #include <boost/thread/lock_algorithms.hpp>
namespace boost
{
template<typename Lockable1,typename Lockable2>
void lock(Lockable1& l1,Lockable2& l2);
template<typename Lockable1,typename Lockable2,typename Lockable3>
void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3);
template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4>
void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4);
template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4,typename Lockable5>
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<typename ForwardIterator>
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<typename Lockable1,typename Lockable2>
int try_lock(Lockable1& l1,Lockable2& l2);
template<typename Lockable1,typename Lockable2,typename Lockable3>
int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3);
template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4>
int try_lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4);
template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4,typename Lockable5>
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<typename ForwardIterator>
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 <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx); // EXTENSION
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, adopt_lock_t); // EXTENSION
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, defer_lock_t); // EXTENSION
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, try_to_lock_t); // EXTENSION
#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
template <typename ...Lockable>
std::tuple<unique_lock<Lockable> ...> make_unique_locks(Lockable& ...mtx); // EXTENSION
#endif
}
[section:make_unique_lock Non Member Function `make_unique_lock(Lockable&)`]
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx); // EXTENSION
[variablelist
[[Returns:] [a __unique_lock as if initialized with `unique_lock<Lockable>(mtx)`.]]
[[Throws:] [Any exception thrown by the call to `__unique_lock<Lockable>(mtx)`.]]
]
[endsect]
[section:make_unique_lock_t Non Member Function `make_unique_lock(Lockable&,tag)`]
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, adopt_lock_t tag); // EXTENSION
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, defer_lock_t tag); // EXTENSION
template <typename Lockable>
unique_lock<Lockable> make_unique_lock(Lockable& mtx, try_to_lock_t tag); // EXTENSION
[variablelist
[[Returns:] [a __unique_lock as if initialized with `unique_lock<Lockable>(mtx, tag)`.]]
[[Throws:] [Any exception thrown by the call to `__unique_lock<Lockable>(mtx, tag)`.]]
]
[endsect]
[section:make_unique_locks Non Member Function `make_unique_locks(Lockable& ...)`]
template <typename ...Lockable>
std::tuple<unique_lock<Lockable> ...> 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]