...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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 Lockable
concept models exclusive
ownership. A type that implements the Lockable
concept shall provide
the following member functions:
Lock ownership acquired through a call to lock()
or try_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 *this
.
boost::thread_resource_error
if an error
occurs.
Attempt to obtain ownership for the current thread without blocking.
true
if ownership was
obtained for the current thread, false
otherwise.
If the call returns true
,
the current thread owns the *this
.
boost::thread_resource_error
if an error
occurs.
The current thread owns *this
.
Releases ownership by the current thread.
The current thread no longer owns *this
.
Nothing
The TimedLockable
concept refines
the Lockable
concept to add support
for timeouts when trying to acquire the lock.
A type that implements the TimedLockable
concept shall meet
the requirements of the Lockable
concept. In addition,
the following member functions must be provided:
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 *this
.
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.
For a type to implement the SharedLockable
concept, as well
as meeting the requirements of the TimedLockable
concept, it must
also provide the following member functions:
Lock ownership acquired through a call to lock_shared()
,
try_lock_shared()
or timed_lock_shared()
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 *this
.
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 *this
.
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 *this
.
boost::thread_resource_error
if an error
occurs.
The current thread has shared ownership of *this
.
Releases shared ownership of *this
by the current thread.
The current thread no longer has shared ownership of *this
.
Nothing
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.
For a type to implement the UpgradeLockable
concept, as well
as meeting the requirements of the SharedLockable
concept, it must
also provide the following member functions:
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 current thread blocks until upgrade ownership can be obtained for the current thread.
The current thread has upgrade ownership of *this
.
boost::thread_resource_error
if an error
occurs.
The current thread has upgrade ownership of *this
.
Releases upgrade ownership of *this
by the current thread.
The current thread no longer has upgrade ownership of *this
.
Nothing
The current thread has upgrade ownership of *this
.
Atomically releases upgrade ownership of *this
by the current thread and acquires
exclusive ownership of *this
. If any other threads have shared
ownership, blocks until exclusive ownership can be acquired.
The current thread has exclusive ownership of *this
.
Nothing
The current thread has upgrade ownership of *this
.
Atomically releases upgrade ownership of *this
by the current thread and acquires
shared ownership of *this
without blocking.
The current thread has shared ownership of *this
.
Nothing
The current thread has exclusive ownership of *this
.
Atomically releases exclusive ownership of *this
by the current thread and acquires
upgrade ownership of *this
without blocking.
The current thread has upgrade ownership of *this
.
Nothing
#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(Lockable &
m,boost::system_time const& abs_time)
~unique_lock()
bool owns_lock() const
Lockable*
mutex()
const
operator unspecified-bool-type() const
bool operator!() const
Lockable*
release()
#include <boost/thread/locks.hpp> template<typename Lockable> class unique_lock { public: unique_lock(); explicit unique_lock(Lockable& m_); unique_lock(Lockable& m_,adopt_lock_t); unique_lock(Lockable& m_,defer_lock_t); unique_lock(Lockable& m_,try_to_lock_t); unique_lock(Lockable& m_,system_time const& target_time); ~unique_lock(); unique_lock(detail::thread_move_t<unique_lock<Lockable> > other); unique_lock(detail::thread_move_t<upgrade_lock<Lockable> > other); operator detail::thread_move_t<unique_lock<Lockable> >(); detail::thread_move_t<unique_lock<Lockable> > move(); unique_lock& operator=(detail::thread_move_t<unique_lock<Lockable> > other); unique_lock& operator=(detail::thread_move_t<upgrade_lock<Lockable> > other); void swap(unique_lock& other); void swap(detail::thread_move_t<unique_lock<Lockable> > other); void lock(); bool try_lock(); template<typename TimeDuration> bool timed_lock(TimeDuration const& relative_time); bool timed_lock(::boost::system_time const& absolute_time); void unlock(); bool owns_lock() const; operator unspecified-bool-type() const; bool operator!() const; Lockable* mutex() const; Lockable* release(); };
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 otherwise (e.g.
boost::unique_lock<boost::mutex>
).
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.
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)
.
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.
If owns_lock()
would return true
, a
value that evaluates to true
in boolean contexts, otherwise a value that evaluates to false
in boolean contexts.
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
operator unspecified-bool-type() const
bool operator!() const
Lockable*
release()
#include <boost/thread/locks.hpp> template<typename Lockable> class shared_lock { public: 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); shared_lock(Lockable& m_,system_time const& target_time); shared_lock(detail::thread_move_t<shared_lock<Lockable> > other); shared_lock(detail::thread_move_t<unique_lock<Lockable> > other); shared_lock(detail::thread_move_t<upgrade_lock<Lockable> > other); ~shared_lock(); operator detail::thread_move_t<shared_lock<Lockable> >(); detail::thread_move_t<shared_lock<Lockable> > move(); shared_lock& operator=(detail::thread_move_t<shared_lock<Lockable> > other); shared_lock& operator=(detail::thread_move_t<unique_lock<Lockable> > other); shared_lock& operator=(detail::thread_move_t<upgrade_lock<Lockable> > other); void swap(shared_lock& other); void lock(); bool try_lock(); bool timed_lock(boost::system_time const& target_time); void unlock(); operator unspecified-bool-type() const; bool operator!() const; bool owns_lock() const; };
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.
If owns_lock()
would return true
, a
value that evaluates to true
in boolean contexts, otherwise a value that evaluates to false
in boolean contexts.
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
.
#include <boost/thread/locks.hpp> template<typename Lockable> class upgrade_lock { public: explicit upgrade_lock(Lockable& m_); upgrade_lock(detail::thread_move_t<upgrade_lock<Lockable> > other); upgrade_lock(detail::thread_move_t<unique_lock<Lockable> > other); ~upgrade_lock(); operator detail::thread_move_t<upgrade_lock<Lockable> >(); detail::thread_move_t<upgrade_lock<Lockable> > move(); upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Lockable> > other); upgrade_lock& operator=(detail::thread_move_t<unique_lock<Lockable> > other); void swap(upgrade_lock& other); void lock(); void unlock(); operator unspecified-bool-type() const; bool operator!() const; bool owns_lock() 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 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.
#include <boost/thread/locks.hpp> template <class Lockable> class upgrade_to_unique_lock { public: explicit upgrade_to_unique_lock(upgrade_lock<Lockable>& m_); ~upgrade_to_unique_lock(); upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Lockable> > other); upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Lockable> > other); void swap(upgrade_to_unique_lock& other); operator unspecified-bool-type() const; bool operator!() 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(); bool owns_lock() const; MutexType* mutex() const; MutexType* release(); bool operator!() const; typedef unspecified-bool-type bool_type; operator bool_type() 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()
.
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(); bool timed_lock(system_time const & abs_time); template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time); 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; };
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(); bool timed_lock(system_time const & abs_time); template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time); 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; };
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(); void lock_shared(); bool try_lock_shared(); bool timed_lock_shared(system_time const& timeout); void unlock_shared(); void lock(); bool try_lock(); bool timed_lock(system_time const& timeout); void unlock(); 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(); };
The class boost::shared_mutex
provides an implementation
of a multiple-reader / single-writer mutex. It implements the UpgradeLockable
concept.
Multiple concurrent calls to lock()
,
try_lock()
,
timed_lock()
,
lock_shared()
,
try_lock_shared()
and timed_lock_shared()
shall be permitted.
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)
#include <boost/thread/condition_variable.hpp> namespace boost { class condition_variable { public: 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 predicate); 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); // backwards compatibility 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); }; }
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;
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)
#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<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); // backwards compatibility 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); }; }
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;
#include <boost/thread/condition.hpp> typedef condition_variable_any condition;
The typedef condition
is
provided for backwards compatibility with previous boost releases.
boost::call_once
provides a mechanism for ensuring
that an initialization routine is run exactly once without data races or
deadlocks.
#include <boost/thread/once.hpp> typedef platform-specific-type once_flag; #define BOOST_ONCE_INIT platform-specific-initializer
Objects of type boost::once_flag
shall be initialized with
BOOST_ONCE_INIT
:
boost::once_flag f=BOOST_ONCE_INIT;
#include <boost/thread/once.hpp> 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
.
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.