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().
- Effects:
The current thread blocks until ownership can be obtained for the current thread.
- Postcondition:
The current thread owns
*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Effects:
Attempt to obtain ownership for the current thread without blocking.
- Returns:
trueif ownership was obtained for the current thread,falseotherwise.- Postcondition:
If the call returns
true, the current thread owns the*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Precondition:
The current thread owns
*this.- Effects:
Releases ownership by the current thread.
- Postcondition:
The current thread no longer owns
*this.- Throws:
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().
- Effects:
Attempt to obtain ownership for the current thread. Blocks until ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as
try_lock().- Returns:
trueif ownership was obtained for the current thread,falseotherwise.- Postcondition:
If the call returns
true, the current thread owns*this.- Throws:
boost::thread_resource_errorif 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().
- Effects:
The current thread blocks until shared ownership can be obtained for the current thread.
- Postcondition:
The current thread has shared ownership of
*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Effects:
Attempt to obtain shared ownership for the current thread without blocking.
- Returns:
trueif shared ownership was obtained for the current thread,falseotherwise.- Postcondition:
If the call returns
true, the current thread has shared ownership of*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Effects:
Attempt to obtain shared ownership for the current thread. Blocks until shared ownership can be obtained, or the specified time is reached. If the specified time has already passed, behaves as
try_lock_shared().- Returns:
trueif shared ownership was acquired for the current thread,falseotherwise.- Postcondition:
If the call returns
true, the current thread has shared ownership of*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Precondition:
The current thread has shared ownership of
*this.- Effects:
Releases shared ownership of
*thisby the current thread.- Postcondition:
The current thread no longer has shared ownership of
*this.- Throws:
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.
- Effects:
The current thread blocks until upgrade ownership can be obtained for the current thread.
- Postcondition:
The current thread has upgrade ownership of
*this.- Throws:
boost::thread_resource_errorif an error occurs.
- Precondition:
The current thread has upgrade ownership of
*this.- Effects:
Releases upgrade ownership of
*thisby the current thread.- Postcondition:
The current thread no longer has upgrade ownership of
*this.- Throws:
Nothing
- Precondition:
The current thread has upgrade ownership of
*this.- Effects:
Atomically releases upgrade ownership of
*thisby the current thread and acquires exclusive ownership of*this. If any other threads have shared ownership, blocks until exclusive ownership can be acquired.- Postcondition:
The current thread has exclusive ownership of
*this.- Throws:
Nothing
- Precondition:
The current thread has upgrade ownership of
*this.- Effects:
Atomically releases upgrade ownership of
*thisby the current thread and acquires shared ownership of*thiswithout blocking.- Postcondition:
The current thread has shared ownership of
*this.- Throws:
Nothing
- Precondition:
The current thread has exclusive ownership of
*this.- Effects:
Atomically releases exclusive ownership of
*thisby the current thread and acquires upgrade ownership of*thiswithout blocking.- Postcondition:
The current thread has upgrade ownership of
*this.- Throws:
Nothing
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.
- Precondition:
The current thread owns a lock on
mequivalent to one obtained by a call tom.lock().- Effects:
Stores a reference to
m. Takes ownership of the lock state ofm.- Throws:
Nothing.
- Effects:
Invokes
m.unlock()on theLockableobject passed to the constructor.- Throws:
Nothing.
-
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()
template<typename Lockable> class unique_lock { public: 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.
- Effects:
Stores a reference to
m. Invokesm.lock().- Postcondition:
owns_lock()returnstrue.mutex()returns&m.- Throws:
Any exception thrown by the call to
m.lock().
- Precondition:
The current thread owns an exclusive lock on
m.- Effects:
Stores a reference to
m. Takes ownership of the lock state ofm.- Postcondition:
owns_lock()returnstrue.mutex()returns&m.- Throws:
Nothing.
- Effects:
Stores a reference to
m.- Postcondition:
owns_lock()returnsfalse.mutex()returns&m.- Throws:
Nothing.
- Effects:
Stores a reference to
m. Invokesm.try_lock(), and takes ownership of the lock state if the call returnstrue.- Postcondition:
mutex()returns&m. If the call totry_lock()returnedtrue, thenowns_lock()returnstrue, otherwiseowns_lock()returnsfalse.- Throws:
Nothing.
- Effects:
Stores a reference to
m. Invokesm.timed_lock(abs_time), and takes ownership of the lock state if the call returnstrue.- Postcondition:
mutex()returns&m. If the call totimed_lock()returnedtrue, thenowns_lock()returnstrue, otherwiseowns_lock()returnsfalse.- Throws:
Any exceptions thrown by the call to
m.timed_lock(abs_time).
- Effects:
Invokes
mutex()->unlock()ifowns_lock()returnstrue.- Throws:
Nothing.
- Returns:
trueif the*thisowns the lock on theLockableobject associated with*this.- Throws:
Nothing.
- Returns:
A pointer to the
Lockableobject associated with*this, orNULLif there is no such object.- Throws:
Nothing.
- Returns:
If
owns_lock()would returntrue, a value that evaluates totruein boolean contexts, otherwise a value that evaluates tofalsein boolean contexts.- Throws:
Nothing.
- Returns:
!owns_lock().- Throws:
Nothing.
- Effects:
The association between
*thisand theLockableobject is removed, without affecting the lock state of theLockableobject. Ifowns_lock()would have returnedtrue, it is the responsibility of the calling code to ensure that theLockableis correctly unlocked.- Returns:
A pointer to the
Lockableobject associated with*thisat the point of the call, orNULLif there is no such object.- Throws:
Nothing.
- Postcondition:
*thisis no longer associated with anyLockableobject.mutex()returnsNULLandowns_lock()returnsfalse.
-
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()
template<typename Lockable> class shared_lock { public: 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.
- Effects:
Stores a reference to
m. Invokesm.lock_shared().- Postcondition:
owns_lock()returnstrue.mutex()returns&m.- Throws:
Any exception thrown by the call to
m.lock_shared().
- Precondition:
The current thread owns an exclusive lock on
m.- Effects:
Stores a reference to
m. Takes ownership of the lock state ofm.- Postcondition:
owns_lock()returnstrue.mutex()returns&m.- Throws:
Nothing.
