33 Concurrency support library [thread]

33.6 Mutual exclusion [thread.mutex]

33.6.4 Mutex requirements [thread.mutex.requirements]

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

33.6.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.
[Note 1: 
The mutex types meet the Cpp17Lockable requirements ([thread.req.lockable.req]).
— end note]
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 2: 
This can be viewed as the modification order of the mutex.
— end note]
[Note 3: 
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.
Synchronization: Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Postconditions: The calling thread owns the mutex.
Return type: void.
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 4: 
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.
Synchronization: If try_lock() returns true, prior unlock() operations on the same object synchronize with this operation.
[Note 5: 
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]
Return type: bool.
Returns: true if ownership was obtained, otherwise false.
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.