Home | Libraries | People | FAQ | More |
Handling mutexes in C++ is an excellent tutorial. You need just replace std and ting by boost.
Mutex, Lock, Condition Variable Rationale adds rationale for the design decisions made for mutexes, locks and condition variables.
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
, TimedLockable
, SharedLockable
and UpgradeLockable
. Each mutex type
implements one or more of these concepts, as do the various lock types.
The BasicLockable
concept models exclusive
ownership. A type L
meets
the BasicLockable
requiremets if the
following expressions are well-formed and have the specified semantics
(m
denotes a value of type
L
):
Lock ownership acquired through a call to lock()
must be released through a call to unlock()
.
The current thread blocks until ownership can be obtained for the current thread.
The current thread owns m
.
void
.
boost::thread_resource_error
if an error
occurs.
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.
If an exception is thrown then a lock shall not have been acquired for the current thread.
The current thread owns m
.
Releases ownership by the current thread.
void
.
The current thread no longer owns m
.
Nothing.
A type L
meets the Lockable
requirements if it meets
the __BasicLocable 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()
must be released through a call to unlock()
.
Attempt to obtain ownership for the current thread without blocking.
bool
.
true
if ownership
was obtained for the current thread, false
otherwise.
If the call returns true
,
the current thread owns the m
.
Nothing.
The TimedLockable
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
.
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()
.
true
if ownership
was obtained for the current thread, false
otherwise.
If the call returns true
,
the current thread owns m
.
Nothing.
As-if
.
try_lock_until
(chrono::steady_clock::now() + rel_time)
The following expressions were required on version 2, but are now deprecated.
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
(rel_time)
m.timed_lock
(abs_time)
Lock ownership acquired through a call to timed_lock()
must be released through a call to unlock()
.
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()
.
true
if ownership
was obtained for the current thread, false
otherwise.
If the call returns true
,
the current thread owns m
.
boost::thread_resource_error
if an error
occurs.
The SharedLockable
concept is a refinement
of the TimedLockable
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()
,
try_lock_shared()
,
try_lock_shared_for
or try_lock_shared_until
must be
released through a call to unlock_shared()
.
The current thread blocks until shared ownership can be obtained for the current thread.
The current thread has shared ownership of m
.
boost::thread_resource_error
if an error
occurs.
Attempt to obtain shared ownership for the current thread without blocking.
true
if shared ownership
was obtained for the current thread, false
otherwise.
If the call returns true
,
the current thread has shared ownership of m
.
boost::thread_resource_error
if an error
occurs.
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()
.
true
if shared ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has shared ownership of m
.
boost::thread_resource_error
if an error
occurs.
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()
.
true
if shared ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has shared ownership of m
.
boost::thread_resource_error
if an error
occurs.
The current thread has shared ownership of m
.
Releases shared ownership of m
by the current thread.
The current thread no longer has shared ownership of m
.
Nothing
The following expressions were required on version 1, but are now deprecated.
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()
must be released through a call to unlock_shared()
.
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()
.
true
if shared ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has shared ownership of m
.
boost::thread_resource_error
if an error
occurs.
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.try_unlock_shared_and_lock()
m.try_unlock_shared_and_lock_for(rel_time)
m.try_unlock_shared_and_lock_until(abs_time)
m.unlock_and_lock_shared()
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)
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()
The UpgradeLockable
concept is a refinement
of the SharedLockable
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 SharedLockable
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()
,
just as if it had been acquired by a call to lock()
.
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 UpgradeLockable
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 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_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_CONVERSION 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()
must be released through a call to unlock_upgrade()
.
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.
The calling thread has no ownership of the mutex.
The current thread blocks until upgrade ownership can be obtained for the current thread.
The current thread has upgrade ownership of m
.
Prior
operations on the same object
synchronize with this operation.
unlock_upgrade
()
boost::thread_resource_error
if an error
occurs.
The current thread has upgrade ownership of m
.
Releases upgrade ownership of m
by the current thread.
The current thread no longer has upgrade ownership of m
.
This operation synchronizes with subsequent lock operations that obtain ownership on the same object.
Nothing
The calling thread has no ownership of the mutex.
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.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_lock_upgrade
()
operations on the same object
synchronize with this operation.
unlock_upgrade
()
Nothing
The calling thread has no ownership of the mutex.
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
). The function returns within
the timeout specified by try_lock_upgrade
()rel_time
only if it has obtained upgrade ownership of the mutex object.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_lock_upgrade_for
(rel_time)
operations on the same object
synchronize with this operation.
unlock_upgrade
()
Nothing
Available only if BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread has no ownership of the mutex.
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
). The function returns before
the absolute timeout specified by try_lock_upgrade
()abs_time
only if it has obtained upgrade ownership of the mutex object.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_lock_upgrade_until
(abs_time)
operations on the same object
synchronize with this operation.
unlock_upgrade
()
Nothing
Available only if BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread must hold a shared lock on the mutex.
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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_shared_and_lock
()
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a shared lock on the mutex.
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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_shared_and_lock_for
(rel_time)
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a shared lock on the mutex.
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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_shared_and_lock_until
(rel_time)
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold an exclusive lock on m
.
Atomically converts the ownership from exclusive to shared for the calling thread.
The current thread has shared ownership of m
.
This operation synchronizes with subsequent lock operations that obtain ownership of the same object.
Nothing
The calling thread shall hold a shared lock on the mutex.
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.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_unlock_shared_and_lock_upgrade
()
and subsequent lock operations
on the same object synchronize with this operation.
unlock_upgrade
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a shared lock on the mutex.
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
). The function shall return within
the timeout specified by try_unlock_shared_and_lock_upgrade
()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.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_unlock_shared_and_lock_upgrade_for
(rel_time)
and subsequent lock operations
on the same object synchronize with this operation.
unlock_upgrade
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a shared lock on the mutex.
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
). The function shall return before
the absolute timeout specified by try_unlock_shared_and_lock_upgrade
()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.
true
if upgrade ownership
was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has upgrade ownership of m
.
If
returns true, prior try_unlock_shared_and_lock_upgrade_until
(rel_time)
and subsequent lock operations
on the same object synchronize with this operation.
unlock_upgrade
()
Nothing
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The current thread has exclusive ownership of m
.
Atomically releases exclusive ownership of m
by the current thread and acquires upgrade ownership of m
without blocking.
The current thread has upgrade ownership of m
.
This operation synchronizes with subsequent lock operations that obtain ownership of the same object.
Nothing
The current thread has upgrade ownership of m
.
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.
The current thread has exclusive ownership of m
.
This operation synchronizes with prior
and subsequent lock operations
that obtain ownership of the same object.
unlock_shared()
()
Nothing
The calling thread shall hold a upgrade lock on the mutex.
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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_upgrade_and_lock
()
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a upgrade lock on the mutex.
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
). The function shall return within
the timeout specified by try_unlock_upgrade_and_lock
()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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_upgrade_and_lock_for
(rel_time)
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The calling thread shall hold a upgrade lock on the mutex.
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
). The function shall return before
the absolute timeout specified by try_unlock_upgrade_and_lock
()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.
true
if exclusive
ownership was acquired for the current thread, false
otherwise.
If the call returns true
,
the current thread has exclusive ownership of m
.
If
returns true, prior try_unlock_upgrade_and_lock_for
(rel_time)
and subsequent lock operations on the same object synchronize with
this operation.
unlock
()
Nothing
Available only if BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
The current thread has upgrade ownership of m
.
Atomically releases upgrade ownership of m
by the current thread and acquires shared ownership of m
without blocking.
The current thread has shared ownership of m
.
This operation synchronizes with prior unlock_shared()
and subsequent lock operations
that obtain ownership of the same object.
Nothing
#include <boost/thread/locks.hpp> 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; template<typename Lockable> class lock_guard 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; template<typename Mutex> void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs); template<typename Lockable> class upgrade_lock; template<typename Mutex> void swap(upgrade_lock <Mutex>& lhs, upgrade_lock <Mutex>& rhs); template <class Mutex> class upgrade_to_unique_lock;
#include <boost/thread/locks.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.
#include <boost/thread/locks.hpp> template<typename Lockable> class lock_guard { public: explicit lock_guard(Lockable& m_); lock_guard(Lockable& m_,boost::adopt_lock_t); ~lock_guard(); };
boost::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
object, to facilitate
exception-safe locking and unlocking. In addition, the lock_guard(Lockable &
m,boost::adopt_lock_t)
constructor allows the boost::lock_guard
object to take ownership
of a lock already held by the current thread.
The current thread owns a lock on m
equivalent to one obtained by a call to m.lock()
.
Stores a reference to m
.
Takes ownership of the lock state of m
.
Nothing.
Invokes m.unlock()
on the Lockable
object passed
to the constructor.
Nothing.
unique_lock()
unique_lock(Lockable &
m)
unique_lock(Lockable &
m,boost::adopt_lock_t)
unique_lock(Lockable &
m,boost::defer_lock_t)
unique_lock(Lockable &
m,boost::try_to_lock_t)
unique_lock(shared_lock<mutex_type>&&
sl,
try_to_lock_t)
unique_lock(shared_lock<mutex_type>&&,
const chrono::time_point<Clock, Duration>&)
unique_lock(shared_lock<mutex_type>&&,
const chrono::duration<Rep, Period>&)
unique_lock(Lockable &
m,boost::system_time const& abs_time)
template <class Clock, class Duration>
unique_lock(Lockable &
m,const chrono::time_point<Clock, Duration>& abs_time)
template <class Rep, class Period>
unique_lock(Lockable &
m,const chrono::duration<Rep, Period>& abs_time)
~unique_lock()
bool owns_lock() const
Lockable* mutex() const
explicit operator
bool()
const
Lockable* release()
#include <boost/thread/locks.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_CONVERSION unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t) template <class Clock, class Duration> unique_lock(shared_lock<mutex_type>&& sl, const chrono::time_point<Clock, Duration>& abs_time); template <class Rep, class Period> unique_lock(shared_lock<mutex_type>&& sl, const chrono::duration<Rep, Period>& rel_time) #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; 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; Lockable* mutex() const noexcept; #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || 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 };
boost::unique_lock
is more complex than
boost::lock_guard
:
not only does it provide for RAII-style locking, it also allows for deferring
acquiring the lock until the lock()
member function is called explicitly, or trying to acquire the lock in
a non-blocking fashion, or with a timeout. Consequently, unlock()
is only called in the destructor if the lock object has locked the Lockable
object, or otherwise
adopted a lock on the Lockable
object.
Specializations of boost::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 boost::unique_lock
is said to own
the lock state of a Lockable
m
if mutex()
returns a pointer to m
and owns_lock()
returns true
. If an object
that owns the lock state of a Lockable
object is destroyed,
then the destructor will invoke mutex()->unlock()
.
The member functions of boost::unique_lock
are not thread-safe.
In particular, boost::unique_lock
is intended to model
the ownership of a Lockable
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.
Creates a lock object with no associated mutex.
owns_lock()
returns false
. mutex()
returns NULL
.
Nothing.
Stores a reference to m
.
Invokes m.lock()
.
owns_lock()
returns true
. mutex()
returns &m
.
Any exception thrown by the call to m.lock()
.
The current thread owns an exclusive lock on m
.
Stores a reference to m
.
Takes ownership of the lock state of m
.
owns_lock()
returns true
. mutex()
returns &m
.
Nothing.
Stores a reference to m
.
owns_lock()
returns false
. mutex()
returns &m
.
Nothing.
Stores a reference to m
.
Invokes m.try_lock()
,
and takes ownership of the lock state if the call returns true
.
mutex()
returns &m
.
If the call to try_lock()
returned true
, then
owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Nothing.
The supplied Mutex
type must implement
.
try_unlock_shared_and_lock
()
Constructs an object of type __unique_lock. Let pm
be 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
.
If sl.owns_lock()
returns true
and
sl.mutex()->try_unlock_shared_and_lock()
returns false
, sl
is not modified.
Nothing.
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
template <class Clock, class Duration> unique_lock(shared_lock<mutex_type>&& sl, const chrono::time_point<Clock, Duration>& abs_time);
The supplied Mutex
type shall implement
.
try_unlock_shared_and_lock_until
(abs_time)
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()->
returns try_unlock_shared_and_lock_until
(abs_time)true
,
sets pm
to the
value returned by sl.release()
and sets owns
to true
.
If sl.owns_lock()
returns true
and
sl.mutex()->
returns try_unlock_shared_and_lock_until
(abs_time)false
,
sl
is not modified.
Nothing.
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
template <class Rep, class Period> unique_lock(shared_lock<mutex_type>&& sl, const chrono::duration<Rep, Period>& rel_time)
The supplied Mutex
type shall implement
.
try_unlock_shared_and_lock_for
(rel_time)
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()->
returns try_unlock_shared_and_lock_for
(rel_time)true
,
sets pm
to the
value returned by sl.release()
and sets owns
to true
.
If sl.owns_lock()
returns true
and
sl.mutex()->
returns try_unlock_shared_and_lock_for
(rel_time)false
,
sl
is not modified.
.
Nothing.
Available only if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
and BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
is defined on Windows platform
Stores a reference to m
.
Invokes m.timed_lock(abs_time)
,
and takes ownership of the lock state if the call returns true
.
mutex()
returns &m
.
If the call to timed_lock()
returned true
, then
owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Any exceptions thrown by the call to m.timed_lock(abs_time)
.
Stores a reference to m
.
Invokes m.
, and takes ownership of the lock
state if the call returns try_lock_until
(abs_time)true
.
mutex()
returns &m
.
If the call to try_lock_until
returned
true
, then owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Any exceptions thrown by the call to m.
.
try_lock_until
(abs_time)
Stores a reference to m
.
Invokes m.
,
and takes ownership of the lock state if the call returns try_lock_for
(rel_time)true
.
mutex()
returns &m
.
If the call to try_lock_for
returned
true
, then owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Any exceptions thrown by the call to m.
.
try_lock_for
(rel_time)
Invokes mutex()
->
unlock()
if owns_lock()
returns true
.
Nothing.
true
if the *this
owns the lock on the Lockable
object associated
with *this
.
Nothing.
A pointer to the Lockable
object associated
with *this
,
or NULL
if there
is no such object.
Nothing.
.
owns_lock()
()
Nothing.
The association between *this
and the Lockable
object is removed,
without affecting the lock state of the Lockable
object. If owns_lock()
would have returned true
,
it is the responsibility of the calling code to ensure that the
Lockable
is correctly
unlocked.
A pointer to the Lockable
object associated
with *this
at the point of the call, or NULL
if there is no such object.
Nothing.
*this
is no longer associated with any Lockable
object. mutex()
returns NULL
and
owns_lock()
returns false
.
shared_lock()
shared_lock(Lockable &
m)
shared_lock(Lockable &
m,boost::adopt_lock_t)
shared_lock(Lockable &
m,boost::defer_lock_t)
shared_lock(Lockable &
m,boost::try_to_lock_t)
shared_lock(Lockable &
m,boost::system_time const& abs_time)
~shared_lock()
bool owns_lock() const
Lockable* mutex() const
explicit operator
bool()
const
Lockable* release()
#include <boost/thread/locks.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); // 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_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || 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 boost::unique_lock
, boost::shared_lock
models the Lockable
concept, but rather than
acquiring unique ownership of the supplied Lockable
object, locking an instance
of boost::shared_lock
acquires shared ownership.
Like boost::unique_lock
, not only does it
provide for RAII-style locking, it also allows for deferring acquiring
the lock until the lock()
member function is called explicitly, or trying to acquire the lock in
a non-blocking fashion, or with a timeout. Consequently, unlock()
is only called in the destructor if the lock object has locked the Lockable
object, or otherwise
adopted a lock on the Lockable
object.
An instance of boost::shared_lock
is said to own
the lock state of a Lockable
m
if mutex()
returns a pointer to m
and owns_lock()
returns true
. If an object
that owns the lock state of a Lockable
object is destroyed,
then the destructor will invoke mutex()->unlock_shared()
.
The member functions of boost::shared_lock
are not thread-safe.
In particular, boost::shared_lock
is intended to model
the shared ownership of a Lockable
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.
Creates a lock object with no associated mutex.
owns_lock()
returns false
. mutex()
returns NULL
.
Nothing.
Stores a reference to m
.
Invokes m.lock_shared()
.
owns_lock()
returns true
. mutex()
returns &m
.
Any exception thrown by the call to m.lock_shared()
.
The current thread owns an exclusive lock on m
.
Stores a reference to m
.
Takes ownership of the lock state of m
.
owns_lock()
returns true
. mutex()
returns &m
.
Nothing.
Stores a reference to m
.
owns_lock()
returns false
. mutex()
returns &m
.
Nothing.
Stores a reference to m
.
Invokes m.try_lock_shared()
,
and takes ownership of the lock state if the call returns true
.
mutex()
returns &m
.
If the call to try_lock_shared()
returned true
, then
owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Nothing.
Stores a reference to m
.
Invokes m.timed_lock(abs_time)
,
and takes ownership of the lock state if the call returns true
.
mutex()
returns &m
.
If the call to timed_lock_shared()
returned true
, then
owns_lock()
returns true
, otherwise
owns_lock()
returns false
.
Any exceptions thrown by the call to m.timed_lock(abs_time)
.
Invokes mutex()
->
unlock_shared()
if owns_lock()
returns true
.
Nothing.
true
if the *this
owns the lock on the Lockable
object associated
with *this
.
Nothing.
A pointer to the Lockable
object associated
with *this
,
or NULL
if there
is no such object.
Nothing.
Nothing.
The association between *this
and the Lockable
object is removed,
without affecting the lock state of the Lockable
object. If owns_lock()
would have returned true
,
it is the responsibility of the calling code to ensure that the
Lockable
is correctly
unlocked.
A pointer to the Lockable
object associated
with *this
at the point of the call, or NULL
if there is no such object.
Nothing.
*this
is no longer associated with any Lockable
object. mutex()
returns NULL
and
owns_lock()
returns false
.
#include <boost/thread/locks.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_CONVERSION // 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 boost::unique_lock
, boost::upgrade_lock
models the Lockable
concept, but rather than
acquiring unique ownership of the supplied Lockable
object, locking an instance
of boost::upgrade_lock
acquires upgrade
ownership.
Like boost::unique_lock
, not only does it
provide for RAII-style locking, it also allows for deferring acquiring
the lock until the lock()
member function is called explicitly, or trying to acquire the lock in
a non-blocking fashion, or with a timeout. Consequently, unlock()
is only called in the destructor if the lock object has locked the Lockable
object, or otherwise
adopted a lock on the Lockable
object.
An instance of boost::upgrade_lock
is said to own
the lock state of a Lockable
m
if mutex()
returns a pointer to m
and owns_lock()
returns true
. If an object
that owns the lock state of a Lockable
object is destroyed,
then the destructor will invoke mutex()->unlock_upgrade()
.
The member functions of boost::upgrade_lock
are not thread-safe.
In particular, boost::upgrade_lock
is intended to model
the upgrade ownership of a UpgradeLockable
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.
#include <boost/thread/locks.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; };
boost::upgrade_to_unique_lock
allows
for a temporary upgrade of an boost::upgrade_lock
to exclusive ownership.
When constructed with a reference to an instance of boost::upgrade_lock
, if that instance
has upgrade ownership on some Lockable
object, that ownership
is upgraded to exclusive ownership. When the boost::upgrade_to_unique_lock
instance
is destroyed, the ownership of the Lockable
is downgraded back to
upgrade ownership.
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 boost::unique_lock<MutexType>
for the same MutexType
,
except that the constructor that takes a single reference to a mutex will
call m.try_lock()
rather than m.lock()
.
#include <boost/thread/shared_lock_guard.hpp> template<typename SharedLockable> class shared_lock_guard { public: 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
SharedLockable
concept supplied
as the constructor parameter. On destruction, the ownership is released.
This provides simple RAII-style locking of a SharedLockable
object, to facilitate
exception-safe shared locking and unlocking. In addition, the __shared_lock_guard_ca(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.
Stores a reference to m
.
Invokes m.
.
lock_shared()
()
Any exception thrown by the call to m.
.
lock_shared()
()
The current thread owns a lock on m
equivalent to one obtained by a call to m.
.
lock_shared()
()
Stores a reference to m
.
Takes ownership of the lock state of m
.
Nothing.
Invokes m.
on the unlock_shared()
()SharedLockable
object
passed to the constructor.
Nothing.
#include <boost/thread/reverse_lock.hpp> 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.
Let be mtx the stored mutex*. If not 0 Invokes mtx->
and gives again the lock
()mtx
to the Lock
using
the adopt_lock_t
overload.
Nothing.
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);
Locks the Lockable
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 with the same mutexes (or other lockable objects)
in different orders without risk of deadlock. If any of the lock()
or try_lock()
operations on the supplied Lockable
objects throws
an exception any locks acquired by the function will be released
before the function exits.
Any exceptions thrown by calling lock()
or try_lock()
on the supplied Lockable
objects.
All the supplied Lockable
objects are locked
by the calling thread.
template<typename ForwardIterator> void lock(ForwardIterator begin,ForwardIterator end);
The value_type
of
ForwardIterator
must
implement the Lockable
concept
Locks all the Lockable
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 with the same mutexes (or other lockable objects)
in different orders without risk of deadlock. If any of the lock()
or try_lock()
operations on the Lockable
objects in the
supplied range throws an exception any locks acquired by the function
will be released before the function exits.
Any exceptions thrown by calling lock()
or try_lock()
on the supplied Lockable
objects.
All the Lockable
objects in the
supplied range are locked by the calling thread.
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);
Calls try_lock()
on each of the Lockable
objects supplied
as arguments. If any of the calls to try_lock()
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()
operations on the supplied Lockable
objects throws
an exception any locks acquired by the function will be released
before the function exits.
-1
if all the supplied Lockable
objects are now
locked by the calling thread, the zero-based index of the object
which could not be locked otherwise.
Any exceptions thrown by calling try_lock()
on the supplied Lockable
objects.
If the function returns -1
, all the supplied Lockable
objects are locked
by the calling thread. Otherwise any locks acquired by this function
will have been released.
template<typename ForwardIterator> ForwardIterator try_lock(ForwardIterator begin,ForwardIterator end);
The value_type
of
ForwardIterator
must
implement the Lockable
concept
Calls try_lock()
on each of the Lockable
objects in the
supplied range. If any of the calls to try_lock()
returns false
then all
locks acquired are released and an iterator referencing the failed
lock is returned.
If any of the try_lock()
operations on the supplied Lockable
objects throws
an exception any locks acquired by the function will be released
before the function exits.
end
if all the supplied
Lockable
objects are now
locked by the calling thread, an iterator referencing the object
which could not be locked otherwise.
Any exceptions thrown by calling try_lock()
on the supplied Lockable
objects.
If the function returns end
then all the Lockable
objects in the
supplied range are locked by the calling thread, otherwise all locks
acquired by the function have been released.
#include <boost/thread/mutex.hpp> class mutex: boost::noncopyable { public: mutex(); ~mutex(); void lock(); bool try_lock(); void unlock(); typedef platform-specific-type native_handle_type; native_handle_type native_handle(); typedef unique_lock<mutex> scoped_lock; typedef unspecified-type scoped_try_lock; };
boost::mutex
implements the Lockable
concept to provide an
exclusive-ownership mutex. At most one thread can own the lock on a given
instance of boost::mutex
at any time. Multiple concurrent
calls to lock()
,
try_lock()
and unlock()
shall be permitted.
typedef platform-specific-type native_handle_type; native_handle_type native_handle();
Returns an instance of native_handle_type
that can be used with platform-specific APIs to manipulate the
underlying implementation. If no such instance exists, native_handle()
and native_handle_type
are not present.
Nothing.
#include <boost/thread/mutex.hpp> typedef mutex try_mutex;
boost::try_mutex
is a typedef
to boost::mutex
, provided for backwards
compatibility with previous releases of boost.
#include <boost/thread/mutex.hpp> class timed_mutex: boost::noncopyable { public: timed_mutex(); ~timed_mutex(); void lock(); void unlock(); 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>& t); typedef platform-specific-type native_handle_type; native_handle_type native_handle(); typedef unique_lock<timed_mutex> scoped_timed_lock; typedef unspecified-type scoped_try_lock; typedef scoped_timed_lock scoped_lock; #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO bool timed_lock(system_time const & abs_time); template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time); #endif };
boost::timed_mutex
implements the TimedLockable
concept to provide
an exclusive-ownership mutex. At most one thread can own the lock on a
given instance of boost::timed_mutex
at any time. Multiple
concurrent calls to lock()
,
try_lock()
,
timed_lock()
,
timed_lock()
and unlock()
shall be permitted.
typedef platform-specific-type native_handle_type; native_handle_type native_handle();
Returns an instance of native_handle_type
that can be used with platform-specific APIs to manipulate the
underlying implementation. If no such instance exists, native_handle()
and native_handle_type
are not present.
Nothing.
#include <boost/thread/recursive_mutex.hpp> class recursive_mutex: boost::noncopyable { public: recursive_mutex(); ~recursive_mutex(); void lock(); bool try_lock(); void unlock(); typedef platform-specific-type native_handle_type; native_handle_type native_handle(); typedef unique_lock<recursive_mutex> scoped_lock; typedef unspecified-type scoped_try_lock; };
boost::recursive_mutex
implements the
Lockable
concept to provide an
exclusive-ownership recursive mutex. At most one thread can own the lock
on a given instance of boost::recursive_mutex
at any time. Multiple
concurrent calls to lock()
,
try_lock()
and unlock()
shall be permitted. A thread that already has exclusive ownership of a
given boost::recursive_mutex
instance can call
lock()
or try_lock()
to acquire an additional level of ownership of the mutex. unlock()
must be called once for each level of ownership acquired by a single thread
before ownership can be acquired by another thread.
typedef platform-specific-type native_handle_type; native_handle_type native_handle();
Returns an instance of native_handle_type
that can be used with platform-specific APIs to manipulate the
underlying implementation. If no such instance exists, native_handle()
and native_handle_type
are not present.
Nothing.
#include <boost/thread/recursive_mutex.hpp> typedef recursive_mutex recursive_try_mutex;
boost::recursive_try_mutex
is a typedef
to boost::recursive_mutex
, provided for
backwards compatibility with previous releases of boost.
#include <boost/thread/recursive_mutex.hpp> class recursive_timed_mutex: boost::noncopyable { public: recursive_timed_mutex(); ~recursive_timed_mutex(); void lock(); bool try_lock(); void unlock(); 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>& t); typedef platform-specific-type native_handle_type; native_handle_type native_handle(); typedef unique_lock<recursive_timed_mutex> scoped_lock; typedef unspecified-type scoped_try_lock; typedef scoped_lock scoped_timed_lock; #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO bool timed_lock(system_time const & abs_time); template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time); #endif };
boost::recursive_timed_mutex
implements
the TimedLockable
concept to provide
an exclusive-ownership recursive mutex. At most one thread can own the
lock on a given instance of boost::recursive_timed_mutex
at any time.
Multiple concurrent calls to lock()
,
try_lock()
,
timed_lock()
,
timed_lock()
and unlock()
shall be permitted. A thread that already has exclusive ownership of a
given boost::recursive_timed_mutex
instance
can call lock()
,
timed_lock()
,
timed_lock()
or try_lock()
to acquire an additional level of ownership of the mutex. unlock()
must be called once for each level of ownership acquired by a single thread
before ownership can be acquired by another thread.
typedef platform-specific-type native_handle_type; native_handle_type native_handle();
Returns an instance of native_handle_type
that can be used with platform-specific APIs to manipulate the
underlying implementation. If no such instance exists, native_handle()
and native_handle_type
are not present.
Nothing.
#include <boost/thread/shared_mutex.hpp> class shared_mutex { public: shared_mutex(shared_mutex const&) = delete; shared_mutex& operator=(shared_mutex const&) = delete; shared_mutex(); ~shared_mutex(); void lock_shared(); bool try_lock_shared(); template <class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock_shared(); 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(); #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 // use upgrade_mutex instead. void lock_upgrade(); void unlock_upgrade(); void unlock_upgrade_and_lock(); void unlock_and_lock_upgrade(); void unlock_and_lock_shared(); void unlock_upgrade_and_lock_shared(); #endif #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO bool timed_lock_shared(system_time const& timeout); bool timed_lock(system_time const& timeout); #endif };
The class boost::shared_mutex
provides an implementation
of a multiple-reader / single-writer mutex. It implements the SharedLockable
concept.
Multiple concurrent calls to lock()
,
try_lock()
,
,
try_lock_for
()
,
try_lock_until
()timed_lock()
,
lock_shared()
,
,
try_lock_shared_for
()
,
try_lock_shared_until
()try_lock_shared()
and timed_lock_shared()
are permitted.
#include <boost/thread/shared_mutex.hpp> class upgrade_mutex { public: upgrade_mutex(upgrade_mutex const&) = delete; upgrade_mutex& operator=(upgrade_mutex const&) = delete; upgrade_mutex(); ~upgrade_mutex(); void lock_shared(); bool try_lock_shared(); template <class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock_shared(); 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(); void lock_upgrade(); template <class Rep, class Period> bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock_upgrade(); // Shared <-> Exclusive #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock(); template <class Rep, class Period> bool try_unlock_shared_and_lock_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_unlock_shared_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time); #endif void unlock_and_lock_shared(); // Shared <-> Upgrade #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock_upgrade(); template <class Rep, class Period> bool try_unlock_shared_and_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_unlock_shared_and_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time); #endif void unlock_upgrade_and_lock_shared(); // Upgrade <-> Exclusive void unlock_upgrade_and_lock(); #if defined(BOOST_THREAD_PLATFORM_PTHREAD) || defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN) bool try_unlock_upgrade_and_lock(); template <class Rep, class Period> bool try_unlock_upgrade_and_lock_for(const chrono::duration<Rep, Period>& rel_time); template <class Clock, class Duration> bool try_unlock_upgrade_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time); #endif void unlock_and_lock_upgrade(); };
The class boost::upgrade_mutex
provides an implementation
of a multiple-reader / single-writer mutex. It implements the UpgradeLockable
concept.
Multiple concurrent calls to lock()
,
try_lock()
,
,
try_lock_for
()
,
try_lock_until
()timed_lock()
,
lock_shared()
,
,
try_lock_shared_for
()
,
try_lock_shared_until
()try_lock_shared()
and timed_lock_shared()
are permitted.
namespace boost { enum class cv_status; { no_timeout, timeout }; class condition_variable; class condition_variable_any; }
The classes condition_variable
and condition_variable_any
provide a mechanism for one thread to wait for notification from another
thread that a particular condition has become true. The general usage pattern
is that one thread locks a mutex and then calls wait
on an instance of condition_variable
or condition_variable_any
.
When the thread is woken from the wait, then it checks to see if the appropriate
condition is now true, and continues if so. If the condition is not true,
then the thread then calls wait
again to resume waiting. In the simplest case, this condition is just a boolean
variable:
boost::condition_variable cond; boost::mutex mut; bool data_ready; void process_data(); void wait_for_data_to_process() { boost::unique_lock<boost::mutex> lock(mut); while(!data_ready) { cond.wait(lock); } process_data(); }
Notice that the lock
is passed
to wait
: wait
will atomically add the thread to the set of threads waiting on the condition
variable, and unlock the mutex. When the thread is woken, the mutex will
be locked again before the call to wait
returns. This allows other threads to acquire the mutex in order to update
the shared data, and ensures that the data associated with the condition
is correctly synchronized.
In the mean time, another thread sets the condition to true
,
and then calls either notify_one
or notify_all
on the condition
variable to wake one waiting thread or all the waiting threads respectively.
void retrieve_data(); void prepare_data(); void prepare_data_for_processing() { retrieve_data(); prepare_data(); { boost::lock_guard<boost::mutex> lock(mut); data_ready=true; } cond.notify_one(); }
Note that the same mutex is locked before the shared data is updated, but
that the mutex does not have to be locked across the call to notify_one
.
This example uses an object of type condition_variable
,
but would work just as well with an object of type condition_variable_any
:
condition_variable_any
is
more general, and will work with any kind of lock or mutex, whereas condition_variable
requires that the lock
passed to wait
is an instance
of boost::unique_lock<boost::mutex>
.
This enables condition_variable
to make optimizations in some cases, based on the knowledge of the mutex
type; condition_variable_any
typically has a more complex implementation than condition_variable
.
condition_variable()
~condition_variable()
void notify_one()
void notify_all()
void wait(boost::unique_lock<boost::mutex>& lock)
template<typename predicate_type> void wait(boost::unique_lock<boost::mutex>&
lock,
predicate_type pred)
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time
const&
abs_time)
template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>&
lock,duration_type const& rel_time)
template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>&
lock,
boost::system_time const& abs_time, predicate_type
pred)
template <class Clock, class Duration>
cv_status wait_until(boost::unique_lock<boost::mutex>& lock, const chrono::time_point<Clock, Duration>&
abs_time)
template <class Rep, class Period>
cv_status wait_for(boost::unique_lock<boost::mutex>& lock, const chrono::duration<Rep, Period>&
rel_time)
template <class Clock, class Duration, class Predicate> bool wait_until(boost::unique_lock<boost::mutex>&
lock,
const chrono::time_point<Clock, Duration>& abs_time, Predicate
pred)
template <class Rep, class Period, class Predicate> bool wait_for(boost::unique_lock<boost::mutex>&
lock,
const chrono::duration<Rep, Period>& rel_time, Predicate
pred)
#include <boost/thread/condition_variable.hpp> namespace boost { class condition_variable { public: condition_variable(); ~condition_variable(); void notify_one() noexcept; void notify_all() noexcept; void wait(boost::unique_lock<boost::mutex>& lock); template<typename predicate_type> void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate); template <class Clock, class Duration> typename cv_status::type wait_until( unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& t); template <class Clock, class Duration, class Predicate> bool wait_until( unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& t, Predicate pred); template <class Rep, class Period> typename cv_status::type wait_for( unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& d); template <class Rep, class Period, class Predicate> bool wait_for( unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& d, Predicate pred); #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time); template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time); template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate); template<typename duration_type,typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate); bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time); template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate); #endif }; }
Constructs an object of class condition_variable
.
boost::thread_resource_error
if an error
occurs.
All threads waiting on *this
have been notified by a call
to notify_one
or
notify_all
(though
the respective calls to wait
or timed_wait
need
not have returned).
Destroys the object.
Nothing.
If any threads are currently blocked waiting
on *this
in a call to wait
or timed_wait
,
unblocks one of those threads.
Nothing.
If any threads are currently blocked waiting
on *this
in a call to wait
or timed_wait
,
unblocks all of those threads.
Nothing.
lock
is locked
by the current thread, and either no other thread is currently
waiting on *this
,
or the execution of the mutex()
member function on the lock
objects supplied in the
calls to wait
or
timed_wait
in all
the threads currently waiting on *this
would return the same value
as lock->mutex()
for this call to wait
.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
As-if
while(!pred()) { wait(lock); }
lock
is locked
by the current thread, and either no other thread is currently
waiting on *this
,
or the execution of the mutex()
member function on the lock
objects supplied in the
calls to wait
or
timed_wait
in all
the threads currently waiting on *this
would return the same value
as lock->mutex()
for this call to wait
.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
when the time as reported by boost::get_system_time()
would be equal to or later than
the specified abs_time
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
false
if the call
is returning because the time specified by abs_time
was reached, true
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
lock
is locked
by the current thread, and either no other thread is currently
waiting on *this
,
or the execution of the mutex()
member function on the lock
objects supplied in the
calls to wait
or
timed_wait
in all
the threads currently waiting on *this
would return the same value
as lock->mutex()
for this call to wait
.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
after the period of time indicated by the rel_time
argument has elapsed, or spuriously. When the thread is unblocked
(for whatever reason), the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also reacquired by invoking lock.lock()
if the function exits with an exception.
false
if the call
is returning because the time period specified by rel_time
has elapsed, true
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Note | |
---|---|
The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases. |
As-if
while(!pred()) { if(!timed_wait(lock,abs_time)) { return pred(); } } return true;
lock
is locked
by the current thread, and either no other thread is currently
waiting on *this
,
or the execution of the mutex()
member function on the lock
objects supplied in the
calls to wait
or
wait_for
or wait_until
in all the threads
currently waiting on *this
would return the same value
as lock->mutex()
for this call to wait
.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
when the time as reported by Clock::now()
would be equal to or later than
the specified abs_time
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
cv_status::no_timeout
if the call is returning
because the time specified by abs_time
was reached, cv_status::timeout
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
lock
is locked
by the current thread, and either no other thread is currently
waiting on *this
,
or the execution of the mutex()
member function on the lock
objects supplied in the
calls to wait
or
wait_until
or
wait_for
in all
the threads currently waiting on *this
would return the same value
as lock->mutex()
for this call to wait
.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
after the period of time indicated by the rel_time
argument has elapsed, or spuriously. When the thread is unblocked
(for whatever reason), the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also reacquired by invoking lock.lock()
if the function exits with an exception.
cv_status::no_timeout
if the call is returning
because the time period specified by rel_time
has elapsed, cv_status::timeout
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Note | |
---|---|
The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases. |
As-if
while(!pred()) { if(!wait_until(lock,abs_time)) { return pred(); } } return true;
As-if
while(!pred()) { if(!wait_for(lock,rel_time)) { return pred(); } } return true;
condition_variable_any()
~condition_variable_any()
void notify_one()
void notify_all()
template<typename lock_type> void wait(lock_type&
lock)
template<typename lock_type,typename predicate_type>
void wait(lock_type& lock, predicate_type
pred)
template<typename lock_type> bool timed_wait(lock_type&
lock,boost::system_time const& abs_time)
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& lock,duration_type
const&
rel_time)
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock, boost::system_time
const&
abs_time,
predicate_type pred)
template <class lock_type, class Clock, class Duration> cv_status
wait_until(lock_type&
lock,
const chrono::time_point<Clock, Duration>& abs_time)
template <class lock_type, class Rep, class Period> cv_status
wait_for(lock_type&
lock,
const chrono::duration<Rep, Period>& rel_time)
template <class lock_type, class Clock, class Duration, class Predicate>
bool wait_until(lock_type& lock, const chrono::time_point<Clock, Duration>&
abs_time,
Predicate pred)
template <class lock_type, class Rep, class Period, class Predicate>
bool wait_until(lock_type& lock, const chrono::duration<Rep, Period>&
rel_time,
Predicate pred)
#include <boost/thread/condition_variable.hpp> namespace boost { class condition_variable_any { public: condition_variable_any(); ~condition_variable_any(); void notify_one(); void notify_all(); template<typename lock_type> void wait(lock_type& lock); template<typename lock_type,typename predicate_type> void wait(lock_type& lock,predicate_type predicate); template <class lock_type, class Clock, class Duration> cv_status wait_until( lock_type& lock, const chrono::time_point<Clock, Duration>& t); template <class lock_type, class Clock, class Duration, class Predicate> bool wait_until( lock_type& lock, const chrono::time_point<Clock, Duration>& t, Predicate pred); template <class lock_type, class Rep, class Period> cv_status wait_for( lock_type& lock, const chrono::duration<Rep, Period>& d); template <class lock_type, class Rep, class Period, class Predicate> bool wait_for( lock_type& lock, const chrono::duration<Rep, Period>& d, Predicate pred); #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time); template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time); template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate); template<typename lock_type,typename duration_type,typename predicate_type> bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate); template<typename lock_type> bool timed_wait(lock_type>& lock,boost::xtime const& abs_time); template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate); #endif }; }
Constructs an object of class condition_variable_any
.
boost::thread_resource_error
if an error
occurs.
All threads waiting on *this
have been notified by a call
to notify_one
or
notify_all
(though
the respective calls to wait
or timed_wait
need
not have returned).
Destroys the object.
Nothing.
If any threads are currently blocked waiting
on *this
in a call to wait
or timed_wait
,
unblocks one of those threads.
Nothing.
If any threads are currently blocked waiting
on *this
in a call to wait
or timed_wait
,
unblocks all of those threads.
Nothing.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
As-if
while(!pred()) { wait(lock); }
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
when the time as reported by boost::get_system_time()
would be equal to or later than
the specified abs_time
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
false
if the call
is returning because the time specified by abs_time
was reached, true
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
after the period of time indicated by the rel_time
argument has elapsed, or spuriously. When the thread is unblocked
(for whatever reason), the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also reacquired by invoking lock.lock()
if the function exits with an exception.
false
if the call
is returning because the time period specified by rel_time
has elapsed, true
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Note | |
---|---|
The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases. |
As-if
while(!pred()) { if(!timed_wait(lock,abs_time)) { return pred(); } } return true;
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
when the time as reported by Clock::now()
would be equal to or later than
the specified abs_time
,
or spuriously. When the thread is unblocked (for whatever reason),
the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also
reacquired by invoking lock.lock()
if the function exits with an
exception.
cv_status::timeout
if the call is returning
because the time specified by abs_time
was reached, cv_status::no_timeout
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Atomically call lock.unlock()
and blocks the current thread.
The thread will unblock when notified by a call to this->notify_one()
or this->notify_all()
,
after the period of time indicated by the rel_time
argument has elapsed, or spuriously. When the thread is unblocked
(for whatever reason), the lock is reacquired by invoking lock.lock()
before the call to wait
returns. The lock is also reacquired by invoking lock.lock()
if the function exits with an exception.
cv_status::timeout
if the call is returning
because the time specified by abs_time
was reached, cv_status::no_timeout
otherwise.
lock
is locked
by the current thread.
boost::thread_resource_error
if an error
occurs. boost::thread_interrupted
if the wait
was interrupted by a call to interrupt()
on the boost::thread
object associated
with the current thread of execution.
Note | |
---|---|
The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases. |
As-if
while(!pred())
{
if(!wait_until
(lock,abs_time))
{
return pred();
}
}
return true;
As-if
while(!pred())
{
if(!wait_for
(lock,rel_time))
{
return pred();
}
}
return true;
#include <boost/thread/condition.hpp> typedef condition_variable_any condition;
The typedef condition
is
provided for backwards compatibility with previous boost releases.
#include <boost/thread/once.hpp> namespace boost { struct once_flag; template<typename Callable> void call_once(once_flag& flag,Callable func); #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 void call_once(void (*func)(),once_flag& flag); #endif }
boost::call_once
provides a mechanism for ensuring
that an initialization routine is run exactly once without data races or
deadlocks.
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag { constexprr once_flag() noexcept; once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; #else typedef platform-specific-type once_flag; #define BOOST_ONCE_INIT platform-specific-initializer #endif
Objects of type boost::once_flag
shall be initialized with
BOOST_ONCE_INIT
if BOOST_THREAD_PROVIDES_ONCE_CXX11
is not defined
boost::once_flag f=BOOST_ONCE_INIT;
template<typename Callable> void call_once(once_flag& flag,Callable func);
Callable
is CopyConstructible
. Copying func
shall have no side effects,
and the effect of calling the copy shall be equivalent to calling
the original.
Calls to call_once
on the same once_flag
object are serialized. If there has been no prior effective call_once
on the same once_flag
object, the argument
func
(or a copy thereof)
is called as-if by invoking func()
, and the invocation of call_once
is effective if and only
if func()
returns without exception. If an exception is thrown, the exception
is propagated to the caller. If there has been a prior effective
call_once
on the
same once_flag
object,
the call_once
returns
without invoking func
.
The completion of an effective call_once
invocation on a once_flag
object, synchronizes with all subsequent call_once
invocations on the same once_flag
object.
thread_resource_error
when the effects cannot be achieved. or any exception propagated
from func
.
The function passed to call_once
must not also call call_once
passing the same once_flag
object. This may cause deadlock, or invoking the passed function
a second time. The alternative is to allow the second call to return
immediately, but that assumes the code knows it has been called recursively,
and can proceed even though the call to call_once
didn't actually call the function, in which case it could also avoid
calling call_once
recursively.
void call_once(void (*func)(),once_flag& flag);
This second overload is provided for backwards compatibility. The effects
of call_once(func,flag)
shall be the same as those of call_once(flag,func)
.
A barrier is a simple concept. Also known as a rendezvous,
it is a synchronization point between multiple threads. The barrier is configured
for a particular number of threads (n
),
and as threads reach the barrier they must wait until all n
threads have arrived. Once the n
-th
thread has reached the barrier, all the waiting threads can proceed, and
the barrier is reset.
#include <boost/thread/barrier.hpp> class barrier { public: barrier(unsigned int count); ~barrier(); bool wait(); };
Instances of boost::barrier
are not copyable or movable.
barrier(unsigned int count);
Construct a barrier for count
threads.
boost::thread_resource_error
if an error
occurs.
~barrier();
No threads are waiting on *this
.
Destroys *this
.
Nothing.
wait
bool wait();
Block until count
threads have called wait
on *this
.
When the count
-th
thread calls wait
,
all waiting threads are unblocked, and the barrier is reset.
true
for exactly one
thread from each batch of waiting threads, false
otherwise.
boost::thread_resource_error
if an error
occurs.
The futures library provides a means of handling synchronous future values, whether those values are generated by another thread, or on a single thread in response to external stimuli, or on-demand.
This is done through the provision of four class templates: boost::unique_future
and boost::shared_future
which are used to
retrieve the asynchronous results, and boost::promise
and boost::packaged_task
which are used to
generate the asynchronous results.
An instance of boost::unique_future
holds the one and
only reference to a result. Ownership can be transferred between instances
using the move constructor or move-assignment operator, but at most one
instance holds a reference to a given asynchronous result. When the result
is ready, it is returned from boost::unique_future<R>::get()
by rvalue-reference to allow the result to be moved or copied as appropriate
for the type.
On the other hand, many instances of boost::shared_future
may reference the
same result. Instances can be freely copied and assigned, and boost::shared_future<R>::get()
returns a const
reference
so that multiple calls to boost::shared_future<R>::get()
are safe. You can move an instance of boost::unique_future
into an instance
of boost::shared_future
, thus transferring
ownership of the associated asynchronous result, but not vice-versa.
You can wait for futures either individually or with one of the boost::wait_for_any()
and boost::wait_for_all()
functions.
You can set the value in a future with either a boost::promise
or a boost::packaged_task
. A boost::packaged_task
is a callable object
that wraps a function or callable object. When the packaged task is invoked,
it invokes the contained function in turn, and populates a future with
the return value. This is an answer to the perennial question: "how
do I return a value from a thread?": package the function you wish
to run as a boost::packaged_task
and pass the packaged
task to the thread constructor. The future retrieved from the packaged
task can then be used to obtain the return value. If the function throws
an exception, that is stored in the future in place of the return value.
int calculate_the_answer_to_life_the_universe_and_everything() { return 42; } boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything); boost::unique_future<int> fi=pt.get_future(); boost::thread task(boost::move(pt)); // launch task on a thread fi.wait(); // wait for it to finish assert(fi.is_ready()); assert(fi.has_value()); assert(!fi.has_exception()); assert(fi.get_state()==boost::future_state::ready); assert(fi.get()==42);
A boost::promise
is a bit more low level:
it just provides explicit functions to store a value or an exception in
the associated future. A promise can therefore be used where the value
may come from more than one possible source, or where a single operation
may produce multiple values.
boost::promise<int> pi; boost::unique_future<int> fi; fi=pi.get_future(); pi.set_value(42); assert(fi.is_ready()); assert(fi.has_value()); assert(!fi.has_exception()); assert(fi.get_state()==boost::future_state::ready); assert(fi.get()==42);
Both boost::promise
and boost::packaged_task
support wait
callbacks that are invoked when a thread blocks in a call to
wait()
or timed_wait()
on a future that is waiting for the result from the boost::promise
or boost::packaged_task
, in the thread that
is doing the waiting. These can be set using the set_wait_callback()
member function on the boost::promise
or boost::packaged_task
in question.
This allows lazy futures where the result is not actually
computed until it is needed by some thread. In the example below, the call
to f.get()
invokes the callback invoke_lazy_task
,
which runs the task to set the value. If you remove the call to f.get()
, the task is not ever run.
int calculate_the_answer_to_life_the_universe_and_everything() { return 42; } void invoke_lazy_task(boost::packaged_task<int>& task) { try { task(); } catch(boost::task_already_started&) {} } int main() { boost::packaged_task<int> task(calculate_the_answer_to_life_the_universe_and_everything); task.set_wait_callback(invoke_lazy_task); boost::unique_future<int> f(task.get_future()); assert(f.get()==42); }
state
future_errc
is_error_code_enum<future_errc>
make_error_code()
make_error_condition()
future_category()
future_error
future_status
unique_future
class templateshared_future
class templatepromise
class templatepackaged_task
class templatewait_for_any()
wait_for_all()
//#include <boost/thread/futures.hpp> namespace boost { #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 namespace future_state { enum state {uninitialized, waiting, ready, moved}; } #endif enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied, no_state }; namespace system { template <> struct is_error_code_enum<future_errc> : public true_type {}; error_code make_error_code(future_errc e); error_condition make_error_condition(future_errc e); } const system::error_category& future_category(); class future_error; template <typename R> class promise; template <typename R> void swap(promise<R>& x, promise<R>& y) noexcept; namespace container { template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc>:: true_type; } template <typename R> class future; template <typename R> class shared_future; template <typename R> class packaged_task; template <class R> void swap(packaged_task<R>&, packaged_task<R>&) noexcept; //template <class R, class Alloc> //struct uses_allocator<packaged_task <R>, Alloc>; // NOT YET IMPLEMENTED // template <class F, class... Args> // future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> // async(F&& f, Args&&... args); // NOT YET IMPLEMENTED // template <class F, class... Args> // future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> // async(launch policy, F&& f, Args&&... args); // NOT YET IMPLEMENTED template<typename Iterator> void wait_for_all(Iterator begin,Iterator end); // EXTENSION template<typename F1,typename... FS> void wait_for_all(F1& f1,Fs&... fs); // EXTENSION template<typename Iterator> Iterator wait_for_any(Iterator begin,Iterator end); template<typename F1,typename... Fs> unsigned wait_for_any(F1& f1,Fs&... fs);
namespace future_state { enum state {uninitialized, waiting, ready, moved}; }
enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied, no_state }
namespace system { template <> struct is_error_code_enum<future_errc> : public true_type {}; }
namespace system { error_code make_error_code(future_errc e); }
namespace system { error_condition make_error_condition(future_errc e); }
const system::error_category& future_category();
class future_error : public std::logic_error { public: future_error(system::error_code ec); const system::error_code& code() const no_except; };
enum class future_status { ready, timeout, deferred };
template <typename R> class unique_future { public: unique_future(unique_future & rhs);// = delete; unique_future& operator=(unique_future& rhs);// = delete; unique_future() noexcept; ~unique_future(); // move support unique_future(unique_future && other) noexcept; unique_future& operator=(unique_future && other) noexcept; shared_future<R> share(); void swap(unique_future& other) noexcept; // EXTENSION // retrieving the value R&& get(); // functions to check state bool valid() const; bool is_ready() const; // EXTENSION bool has_exception() const; // EXTENSION bool has_value() const; // EXTENSION // waiting for the result to be ready void wait() const; template <class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO template<typename Duration> bool timed_wait(Duration const& rel_time) const; bool timed_wait_until(boost::system_time const& abs_time) const; #endif #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 typedef future_state::state state; state get_state() const; #endif };
unique_future();
Constructs an uninitialized future.
this->is_ready
returns false
. this->get_state()
returns boost::future_state::uninitialized
.
Nothing.
unique_future(unique_future && other);
Constructs a new future, and transfers ownership of the asynchronous
result associated with other
to *this
.
this->get_state()
returns the value of other->get_state()
prior to the call. other->get_state()
returns boost::future_state::uninitialized
. If other
was associated with an
asynchronous result, that result is now associated with *this
.
other
is not
associated with any asynchronous result.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
unique_future& operator=(unique_future && other);
Transfers ownership of the asynchronous result associated with
other
to *this
.
this->get_state()
returns the value of other->get_state()
prior to the call. other->get_state()
returns boost::future_state::uninitialized
. If other
was associated with an
asynchronous result, that result is now associated with *this
.
other
is not
associated with any asynchronous result. If *this
was associated with an asynchronous
result prior to the call, that result no longer has an associated
boost::unique_future
instance.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
void swap(unique_future & other) no_except;
Swaps ownership of the asynchronous results associated with
other
and *this
.
this->get_state()
returns the value of other->get_state()
prior to the call. other->get_state()
returns the value of this->get_state()
prior to the call. If other
was associated with an
asynchronous result, that result is now associated with *this
,
otherwise *this
has no associated result. If *this
was associated with an asynchronous
result, that result is now associated with other
,
otherwise other
has no associated result.
Nothing.
R&& get(); R& unique_future<R&>::get(); void unique_future<void>::get();
If *this
is associated with an asynchronous result, waits until the result
is ready as-if by a call to boost::unique_future<R>::wait()
,
and retrieves the result (whether that is a value or an exception).
If the result type R
is a reference, returns the stored reference. If R
is void
,
there is no return value. Otherwise, returns an rvalue-reference
to the value stored in the asynchronous result.
this->is_ready()
returns true
. this->get_state()
returns boost::future_state::ready
.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
stored in the asynchronous result in place of a value.
get()
is an interruption point.
void wait();
If *this
is associated with an asynchronous result, waits until the result
is ready. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
this->is_ready()
returns true
. this->get_state()
returns boost::future_state::ready
.
wait()
is an interruption point.
template<typename Duration> bool timed_wait(Duration const& wait_duration);
If *this
is associated with an asynchronous result, waits until the result
is ready, or the time specified by wait_duration
has elapsed. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
true
if *this
is associated with an asynchronous result, and that result is
ready before the specified time has elapsed, false
otherwise.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
If this call returned true
,
then this->is_ready()
returns true
and
this->get_state()
returns boost::future_state::ready
.
timed_wait()
is an interruption point. Duration
must be a type that
meets the Boost.DateTime time duration requirements.
bool timed_wait(boost::system_time const& wait_timeout);
If *this
is associated with an asynchronous result, waits until the result
is ready, or the time point specified by wait_timeout
has passed. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
true
if *this
is associated with an asynchronous result, and that result is
ready before the specified time has passed, false
otherwise.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
If this call returned true
,
then this->is_ready()
returns true
and
this->get_state()
returns boost::future_state::ready
.
timed_wait()
is an interruption point.
bool is_ready();
Checks to see if the asynchronous result associated with *this
is set.
true
if *this
is associated with an asynchronous result, and that result is
ready for retrieval, false
otherwise.
Nothing.
bool has_value();
Checks to see if the asynchronous result associated with *this
is set with a value rather than an exception.
true
if *this
is associated with an asynchronous result, that result is ready
for retrieval, and the result is a stored value, false
otherwise.
Nothing.
bool has_exception();
Checks to see if the asynchronous result associated with *this
is set with an exception rather than a value.
true
if *this
is associated with an asynchronous result, that result is ready
for retrieval, and the result is a stored exception, false
otherwise.
Nothing.
future_state::state get_state();
Determine the state of the asynchronous result associated with
*this
,
if any.
boost::future_state::uninitialized
if *this
is not associated with an asynchronous result. boost::future_state::ready
if the asynchronous
result associated with *this
is ready for retrieval,
boost::future_state::waiting
otherwise.
Nothing.
template <typename R> class shared_future { public: typedef future_state::state state; // EXTENSION shared_future() noexcept; ~shared_future(); // copy support shared_future(shared_future const& other); shared_future& operator=(shared_future const& other); // move support shared_future(shared_future && other) noexcept; shared_future(unique_future<R> && other) noexcept; shared_future& operator=(shared_future && other) noexcept; shared_future& operator=(unique_future<R> && other) noexcept; void swap(shared_future& other); // retrieving the value R get(); // functions to check state, and wait for ready bool valid() const noexcept; bool is_ready() const noexcept; // EXTENSION bool has_exception() const noexcept; // EXTENSION bool has_value() const noexcept; // EXTENSION // waiting for the result to be ready void wait() const; template <class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO template<typename Duration> bool timed_wait(Duration const& rel_time) const; bool timed_wait_until(boost::system_time const& abs_time) const; #endif #if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 state get_state() const noexcept; #endif };
shared_future();
Constructs an uninitialized future.
this->is_ready
returns false
. this->get_state()
returns boost::future_state::uninitialized
.
Nothing.
const R& get();
If *this
is associated with an asynchronous result, waits until the result
is ready as-if by a call to boost::shared_future<R>::wait()
,
and returns a const
reference to the result.
If the result type R
is a reference, returns the stored reference. If R
is void
,
there is no return value. Otherwise, returns a const
reference to the value stored
in the asynchronous result.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted.
get()
is an interruption point.
void wait();
If *this
is associated with an asynchronous result, waits until the result
is ready. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
this->is_ready()
returns true
. this->get_state()
returns boost::future_state::ready
.
wait()
is an interruption point.
template<typename Duration> bool timed_wait(Duration const& wait_duration);
If *this
is associated with an asynchronous result, waits until the result
is ready, or the time specified by wait_duration
has elapsed. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
true
if *this
is associated with an asynchronous result, and that result is
ready before the specified time has elapsed, false
otherwise.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
If this call returned true
,
then this->is_ready()
returns true
and
this->get_state()
returns boost::future_state::ready
.
timed_wait()
is an interruption point. Duration
must be a type that
meets the Boost.DateTime time duration requirements.
bool timed_wait(boost::system_time const& wait_timeout);
If *this
is associated with an asynchronous result, waits until the result
is ready, or the time point specified by wait_timeout
has passed. If the result is not ready on entry, and the result
has a wait callback set, that callback is
invoked prior to waiting.
true
if *this
is associated with an asynchronous result, and that result is
ready before the specified time has passed, false
otherwise.
boost::future_uninitialized
if *this
is not associated with an asynchronous result. boost::thread_interrupted
if the result
associated with *this
is not ready at the point
of the call, and the current thread is interrupted. Any exception
thrown by the wait callback if such a callback
is called.
If this call returned true
,
then this->is_ready()
returns true
and
this->get_state()
returns boost::future_state::ready
.
timed_wait()
is an interruption point.
bool is_ready();
Checks to see if the asynchronous result associated with *this
is set.
true
if *this
is associated with an asynchronous result, and that result is
ready for retrieval, false
otherwise.
Nothing.
bool has_value();
Checks to see if the asynchronous result associated with *this
is set with a value rather than an exception.
true
if *this
is associated with an asynchronous result, that result is ready
for retrieval, and the result is a stored value, false
otherwise.
Nothing.
bool has_exception();
Checks to see if the asynchronous result associated with *this
is set with an exception rather than a value.
true
if *this
is associated with an asynchronous result, that result is ready
for retrieval, and the result is a stored exception, false
otherwise.
Nothing.
future_state::state get_state();
Determine the state of the asynchronous result associated with
*this
,
if any.
boost::future_state::uninitialized
if *this
is not associated with an asynchronous result. boost::future_state::ready
if the asynchronous
result associated with *this
is ready for retrieval,
boost::future_state::waiting
otherwise.
Nothing.
template <typename R> class promise { public: promise(); template <class Allocator> promise(allocator_arg_t, Allocator a); promise & operator=(const promise & rhs);// = delete; promise(const promise & rhs);// = delete; ~promise(); // Move support promise(promise && rhs) noexcept;; promise & operator=(promise&& rhs) noexcept;; void swap(promise& other) noexcept; // Result retrieval unique_future<R> get_future(); // Set the value void set_value(R& r); void set_value(R&& r); void set_exception(boost::exception_ptr e); // setting the result with deferred notification // void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED // void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED // void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED template<typename F> void set_wait_callback(F f); // EXTENSION };
promise();
Constructs a new boost::promise
with no associated
result.
Nothing.
template <class Allocator> promise(allocator_arg_t, Allocator a);
Constructs a new boost::promise
with no associated
result using the allocator a
.
Nothing.
Available only if BOOST_THREAD_FUTURE_USES_ALLOCATORS is defined.
promise(promise && other);
Constructs a new boost::promise
, and transfers
ownership of the result associated with other
to *this
,
leaving other
with no associated result.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
promise& operator=(promise && other);
Transfers ownership of the result associated with other
to *this
, leaving other
with no associated result. If there was already a result associated
with *this
,
and that result was not ready, sets any
futures associated with that result to ready
with a boost::broken_promise
exception as the result.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
~promise();
Destroys *this
.
If there was a result associated with *this
, and that result is not
ready, sets any futures associated with
that task to ready with a boost::broken_promise
exception as
the result.
Nothing.
unique_future<R> get_future();
If *this
was not associated with a result, allocate storage for a new
asynchronous result and associate it with *this
. Returns a boost::unique_future
associated
with the result associated with *this
.
boost::future_already_retrieved
if
the future associated with the task has already been retrieved.
std::bad_alloc
if any memory necessary
could not be allocated.
void set_value(R&& r); void set_value(const R& r); void promise<R&>::set_value(R& r); void promise<void>::set_value();
If *this
was not associated with a result, allocate storage for a new
asynchronous result and associate it with *this
. Store the value r
in the asynchronous result
associated with *this
. Any threads blocked waiting
for the asynchronous result are woken.
All futures waiting on the asynchronous result are ready
and boost::unique_future<R>::has_value()
or boost::shared_future<R>::has_value()
for those futures shall return true
.
boost::promise_already_satisfied
if
the result associated with *this
is already ready.
std::bad_alloc
if the memory required
for storage of the result cannot be allocated. Any exception
thrown by the copy or move-constructor of R
.
void set_exception(boost::exception_ptr e);
If *this
was not associated with a result, allocate storage for a new
asynchronous result and associate it with *this
. Store the exception e
in the asynchronous result
associated with *this
. Any threads blocked waiting
for the asynchronous result are woken.
All futures waiting on the asynchronous result are ready
and boost::unique_future<R>::has_exception()
or boost::shared_future<R>::has_exception()
for those futures shall return true
.
boost::promise_already_satisfied
if
the result associated with *this
is already ready.
std::bad_alloc
if the memory required
for storage of the result cannot be allocated.
template<typename F> void set_wait_callback(F f);
The expression f(t)
where t
is a lvalue of type boost::promise
shall be well-formed.
Invoking a copy of f
shall have the same effect as invoking f
Store a copy of f
with the asynchronous result associated with *this
as a wait callback.
This will replace any existing wait callback store alongside
that result. If a thread subsequently calls one of the wait functions
on a boost::unique_future
or boost::shared_future
associated
with this result, and the result is not ready,
f(*this)
shall be invoked.
std::bad_alloc
if memory cannot
be allocated for the required storage.
template<typename R // , class... ArgTypes // NOT YET IMPLEMENTED > class packaged_task { public: typedef R result_type; packaged_task(packaged_task&);// = delete; packaged_task& operator=(packaged_task&);// = delete; // construction and destruction packaged_task() noexcept; explicit packaged_task(R(*f)()); template <class F> explicit packaged_task(F&& f); template <class F, class Allocator> packaged_task(allocator_arg_t, Allocator a, F&& f); ~packaged_task() {} // move support packaged_task(packaged_task&& other) noexcept; packaged_task& operator=(packaged_task&& other) noexcept; void swap(packaged_task& other) noexcept; bool valid() const noexcept; // result retrieval unique_future<R> get_future(); // execution void operator()(); // void operator()(ArgTypes... ); // NOT YET IMPLEMENTED // void make_ready_at_thread_exit(ArgTypes...); // NOT YET IMPLEMENTED void reset(); template<typename F> void set_wait_callback(F f); // EXTENSION };
packaged_task(R(*f)()); template<typename F> packaged_task(F&&f);
f()
is a valid expression with a return type convertible to R
. Invoking a copy of f
shall behave the same as
invoking f
.
Constructs a new boost::packaged_task
with
boost::forward<F>(f)
stored as the associated task.
Any exceptions thrown by the copy (or move) constructor of f
. std::bad_alloc
if memory for the internal data structures could not be allocated.
The R(*f)()) overload to allow passing a function without needing
to use &
.
template <class Allocator> packaged_task(allocator_arg_t, Allocator a, R(*f)()); template <class F, class Allocator> packaged_task(allocator_arg_t, Allocator a, F&& f);
f()
is a valid expression with a return type convertible to R
. Invoking a copy of f
shall behave the same as
invoking f
.
Constructs a new __packaged_task with boost::forward<F>(f)
stored as the associated task
using the allocator a
.
Any exceptions thrown by the copy (or move) constructor of f
. std::bad_alloc
if memory for the internal data structures could not be allocated.
Available only if BOOST_THREAD_FUTURE_USES_ALLOCATORS is defined.
The R(*f)()) overload to allow passing a function without needing
to use &
.
packaged_task(packaged_task && other);
Constructs a new boost::packaged_task
, and transfers
ownership of the task associated with other
to *this
,
leaving other
with no associated task.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
packaged_task& operator=(packaged_task && other);
Transfers ownership of the task associated with other
to *this
, leaving other
with no associated task. If there was already a task associated
with *this
,
and that task has not been invoked, sets any futures associated
with that task to ready with a boost::broken_promise
exception as
the result.
Nothing.
If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.
~packaged_task();
Destroys *this
.
If there was a task associated with *this
, and that task has not been
invoked, sets any futures associated with that task to ready
with a boost::broken_promise
exception as the result.
Nothing.
unique_future<R> get_future();
Returns a boost::unique_future
associated
with the result of the task associated with *this
.
boost::task_moved
if ownership of
the task associated with *this
has been moved to another
instance of boost::packaged_task
. boost::future_already_retrieved
if
the future associated with the task has already been retrieved.
void operator()();
Invoke the task associated with *this
and store the result in the
corresponding future. If the task returns normally, the return
value is stored as the asynchronous result, otherwise the exception
thrown is stored. Any threads blocked waiting for the asynchronous
result associated with this task are woken.
All futures waiting on the asynchronous result are ready
boost::task_moved
if ownership of
the task associated with *this
has been moved to another
instance of boost::packaged_task
. boost::task_already_started
if the
task has already been invoked.
void reset();
Reset the state of the packaged_task so that it can be called again.
boost::task_moved
if ownership of
the task associated with *this
has been moved to another
instance of boost::packaged_task
.
template<typename F> void set_wait_callback(F f);
The expression f(t)
where t
is a lvalue of type boost::packaged_task
shall
be well-formed. Invoking a copy of f
shall have the same effect as invoking f
Store a copy of f
with the task associated with *this
as a wait callback.
This will replace any existing wait callback store alongside
that task. If a thread subsequently calls one of the wait functions
on a boost::unique_future
or boost::shared_future
associated
with this task, and the result of the task is not ready,
f(*this)
shall be invoked.
boost::task_moved
if ownership of
the task associated with *this
has been moved to another
instance of boost::packaged_task
.
template<typename Iterator> Iterator wait_for_any(Iterator begin,Iterator end); template<typename F1,typename F2> unsigned wait_for_any(F1& f1,F2& f2); template<typename F1,typename F2,typename F3> unsigned wait_for_any(F1& f1,F2& f2,F3& f3); template<typename F1,typename F2,typename F3,typename F4> unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4); template<typename F1,typename F2,typename F3,typename F4,typename F5> unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5);
The types Fn
shall
be specializations of boost::unique_future
or boost::shared_future
, and Iterator
shall be a forward iterator
with a value_type
which is a specialization of boost::unique_future
or boost::shared_future
.
Waits until at least one of the specified futures is ready.
The range-based overload returns an Iterator
identifying the first future in the range that was detected as
ready. The remaining overloads return the
zero-based index of the first future that was detected as ready
(first parameter => 0, second parameter => 1, etc.).
boost::thread_interrupted
if the current
thread is interrupted. Any exception thrown by the wait
callback associated with any of the futures being waited
for. std::bad_alloc
if memory could not
be allocated for the internal wait structures.
wait_for_any()
is an interruption point.
template<typename Iterator> void wait_for_all(Iterator begin,Iterator end); template<typename F1,typename F2> void wait_for_all(F1& f1,F2& f2); template<typename F1,typename F2,typename F3> void wait_for_all(F1& f1,F2& f2,F3& f3); template<typename F1,typename F2,typename F3,typename F4> void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4); template<typename F1,typename F2,typename F3,typename F4,typename F5> void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5);
The types Fn
shall
be specializations of boost::unique_future
or boost::shared_future
, and Iterator
shall be a forward iterator
with a value_type
which is a specialization of boost::unique_future
or boost::shared_future
.
Waits until all of the specified futures are ready.
Any exceptions thrown by a call to wait()
on the specified futures.
wait_for_all()
is an interruption point.