Boost C++ Libraries

“...one of the most highly regarded and expertly designed C++ library projects in the world.” Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

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_error if an error occurs.

Effects:

Attempt to obtain ownership for the current thread without blocking.

Returns:

true if ownership was obtained for the current thread, false otherwise.

Postcondition:

If the call returns true, the current thread owns the *this.

Throws:

boost::thread_resource_error if 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:

true if ownership was obtained for the current thread, false otherwise.

Postcondition:

If the call returns true, the current thread owns *this.

Throws:

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().

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_error if an error occurs.

Effects:

Attempt to obtain shared ownership for the current thread without blocking.

Returns:

true if shared ownership was obtained for the current thread, false otherwise.

Postcondition:

If the call returns true, the current thread has shared ownership of *this.

Throws:

boost::thread_resource_error if 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:

true if shared ownership was acquired for the current thread, false otherwise.

Postcondition:

If the call returns true, the current thread has shared ownership of *this.

Throws:

boost::thread_resource_error if an error occurs.

Precondition:

The current thread has shared ownership of *this.

Effects:

Releases shared ownership of *this by 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_error if an error occurs.

Precondition:

The current thread has upgrade ownership of *this.

Effects:

Releases upgrade ownership of *this by 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 *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.

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 *this by the current thread and acquires shared ownership of *this without 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 *this by the current thread and acquires upgrade ownership of *this without 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.

Effects:

Stores a reference to m. Invokes m.lock().

Throws:

Any exception thrown by the call to m.lock().

Precondition:

The current thread owns a lock on m equivalent to one obtained by a call to m.lock().

Effects:

Stores a reference to m. Takes ownership of the lock state of m.

Throws:

Nothing.

Effects:

Invokes m.unlock() on the Lockable object passed to the constructor.

Throws:

Nothing.

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. Invokes m.lock().

Postcondition:

owns_lock() returns true. 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 of m.

Postcondition:

owns_lock() returns true. mutex() returns &m.

Throws:

Nothing.

Effects:

Stores a reference to m.

Postcondition:

owns_lock() returns false. mutex() returns &m.

Throws:

Nothing.

Effects:

Stores a reference to m. Invokes m.try_lock(), and takes ownership of the lock state if the call returns true.

Postcondition:

mutex() returns &m. If the call to try_lock() returned true, then owns_lock() returns true, otherwise owns_lock() returns false.

Throws:

Nothing.

Effects:

Stores a reference to m. Invokes m.timed_lock(abs_time), and takes ownership of the lock state if the call returns true.

Postcondition:

mutex() returns &m. If the call to timed_lock() returned true, then owns_lock() returns true, otherwise owns_lock() returns false.

Throws:

Any exceptions thrown by the call to m.timed_lock(abs_time).

Effects:

Invokes mutex()-> unlock() if owns_lock() returns true.

Throws:

Nothing.

Returns:

true if the *this owns the lock on the Lockable object associated with *this.

Throws:

Nothing.

Returns:

A pointer to the Lockable object associated with *this, or NULL if there is no such object.

Throws:

Nothing.

Returns:

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.

Throws:

Nothing.

Returns:

! owns_lock().

Throws:

Nothing.

Effects:

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.

Returns:

A pointer to the Lockable object associated with *this at the point of the call, or NULL if there is no such object.

Throws:

Nothing.

Postcondition:

*this is no longer associated with any Lockable object. mutex() returns NULL and owns_lock() returns false.

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. Invokes m.lock_shared().

Postcondition:

owns_lock() returns true. 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 of m.

Postcondition:

owns_lock() returns true. mutex() returns &m.

Throws:

Nothing.