32 Thread support library [thread]

32.5 Mutual exclusion [thread.mutex]

32.5.4 Mutex requirements [thread.mutex.requirements]

32.5.4.2 Mutex types [thread.mutex.requirements.mutex]

32.5.4.2.1 General [thread.mutex.requirements.mutex.general]

The mutex types are the standard library types mutex, recursive_­mutex, timed_­mutex, recursive_­timed_­mutex, shared_­mutex, and shared_­timed_­mutex.
They meet the requirements set out in [thread.mutex.requirements.mutex].
In this description, m denotes an object of a mutex type.
The mutex types meet the Cpp17Lockable requirements ([thread.req.lockable.req]).
The mutex types meet Cpp17DefaultConstructible and Cpp17Destructible.
If initialization of an object of a mutex type fails, an exception of type system_­error is thrown.
The mutex types are neither copyable nor movable.
The error conditions for error codes, if any, reported by member functions of the mutex types are as follows:
  • resource_­unavailable_­try_­again — if any native handle type manipulated is not available.
  • operation_­not_­permitted — if the thread does not have the privilege to perform the operation.
  • invalid_­argument — if any native handle type manipulated as part of mutex construction is incorrect.
The implementation provides lock and unlock operations, as described below.
For purposes of determining the existence of a data race, these behave as atomic operations ([intro.multithread]).
The lock and unlock operations on a single mutex appears to occur in a single total order.
[Note 1:
This can be viewed as the modification order of the mutex.
— end note]
[Note 2:
Construction and destruction of an object of a mutex type need not be thread-safe; other synchronization can be used to ensure that mutex objects are initialized and visible to other threads.
— end note]
The expression m.lock() is well-formed and has the following semantics:
Preconditions: If m is of type mutex, timed_­mutex, shared_­mutex, or shared_­timed_­mutex, the calling thread does not own the mutex.
Effects: Blocks the calling thread until ownership of the mutex can be obtained for the calling thread.
Postconditions: The calling thread owns the mutex.
Return type: void.
Synchronization: Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Throws: system_­error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_­not_­permitted — if the thread does not have the privilege to perform the operation.
  • resource_­deadlock_­would_­occur — if the implementation detects that a deadlock would occur.
The expression m.try_­lock() is well-formed and has the following semantics:
Preconditions: If m is of type mutex, timed_­mutex, shared_­mutex, or shared_­timed_­mutex, the calling thread does not own the mutex.
Effects: Attempts to obtain ownership of the mutex for the calling thread without blocking.
If ownership is not obtained, there is no effect and try_­lock() immediately returns.
An implementation may fail to obtain the lock even if it is not held by any other thread.
[Note 3:
This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange ([atomics]).
— end note]
An implementation should ensure that try_­lock() does not consistently return false in the absence of contending mutex acquisitions.
Return type: bool.
Returns: true if ownership was obtained, otherwise false.
Synchronization: If try_­lock() returns true, prior unlock() operations on the same object synchronize with this operation.
[Note 4:
Since lock() does not synchronize with a failed subsequent try_­lock(), the visibility rules are weak enough that little would be known about the state after a failure, even in the absence of spurious failures.
— end note]
Throws: Nothing.
The expression m.unlock() is well-formed and has the following semantics:
Preconditions: The calling thread owns the mutex.
Effects: Releases the calling thread's ownership of the mutex.
Return type: void.
Synchronization: This operation synchronizes with subsequent lock operations that obtain ownership on the same object.
Throws: Nothing.