32 Thread support library [thread]

32.5 Mutual exclusion [thread.mutex]

32.5.4 Mutex requirements [thread.mutex.requirements]

32.5.4.4 Shared mutex types [thread.sharedmutex.requirements]

32.5.4.4.1 General [thread.sharedmutex.requirements.general]

The standard library types shared_­mutex and shared_­timed_­mutex are shared mutex types.
Shared mutex types meet the requirements of mutex types ([thread.mutex.requirements.mutex]) and additionally meet the requirements set out below.
In this description, m denotes an object of a shared mutex type.
[Note 1:
The shared mutex types meet the Cpp17SharedLockable requirements ([thread.req.lockable.shared]).
— end note]
In addition to the exclusive lock ownership mode specified in [thread.mutex.requirements.mutex], shared mutex types provide a shared lock ownership mode.
Multiple execution agents can simultaneously hold a shared lock ownership of a shared mutex type.
But no execution agent holds a shared lock while another execution agent holds an exclusive lock on the same shared mutex type, and vice-versa.
The maximum number of execution agents which can share a shared lock on a single shared mutex type is unspecified, but is at least 10000.
If more than the maximum number of execution agents attempt to obtain a shared lock, the excess execution agents block until the number of shared locks are reduced below the maximum amount by other execution agents releasing their shared lock.
The expression m.lock_­shared() is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: Blocks the calling thread until shared ownership of the mutex can be obtained for the calling thread.
If an exception is thrown then a shared lock has not been acquired for the current thread.
Synchronization: Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Postconditions: The calling thread has a shared lock on 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.unlock_­shared() is well-formed and has the following semantics:
Preconditions: The calling thread holds a shared lock on the mutex.
Effects: Releases a shared lock on the mutex held by the calling thread.
Return type: void.
Synchronization: This operation synchronizes with subsequent lock() operations that obtain ownership on the same object.
Throws: Nothing.
The expression m.try_­lock_­shared() is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: Attempts to obtain shared ownership of the mutex for the calling thread without blocking.
If shared ownership is not obtained, there is no effect and try_­lock_­shared() immediately returns.
An implementation may fail to obtain the lock even if it is not held by any other thread.
Synchronization: If try_­lock_­shared() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if the shared lock was acquired, otherwise false.
Throws: Nothing.

32.5.4.4.2 Class shared_­mutex [thread.sharedmutex.class]

namespace std { class shared_mutex { public: shared_mutex(); ~shared_mutex(); shared_mutex(const shared_mutex&) = delete; shared_mutex& operator=(const shared_mutex&) = delete; // exclusive ownership void lock(); // blocking bool try_lock(); void unlock(); // shared ownership void lock_shared(); // blocking bool try_lock_shared(); void unlock_shared(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class shared_­mutex provides a non-recursive mutex with shared ownership semantics.
The class shared_­mutex meets all of the shared mutex requirements ([thread.sharedmutex.requirements]).
It is a standard-layout class ([class.prop]).
The behavior of a program is undefined if:
  • it destroys a shared_­mutex object owned by any thread,
  • a thread attempts to recursively gain any ownership of a shared_­mutex, or
  • a thread terminates while possessing any ownership of a shared_­mutex.
shared_­mutex may be a synonym for shared_­timed_­mutex.