[thread.sharedmutex.requirements] # 32 Concurrency support library [[thread]](./#thread) ## 32.6 Mutual exclusion [[thread.mutex]](thread.mutex#thread.sharedmutex.requirements) ### 32.6.4 Mutex requirements [[thread.mutex.requirements]](thread.mutex.requirements#thread.sharedmutex.requirements) #### 32.6.4.4 Shared mutex types [thread.sharedmutex.requirements] #### [32.6.4.4.1](#general) General [[thread.sharedmutex.requirements.general]](thread.sharedmutex.requirements.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7815) The standard library types shared_mutex and shared_timed_mutex are [*shared mutex types*](#def:shared_mutex_types "32.6.4.4.1 General [thread.sharedmutex.requirements.general]")[.](#general-1.sentence-1) Shared mutex types meet the requirements of mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types")) and additionally meet the requirements set out below[.](#general-1.sentence-2) In this description,m denotes an object of a shared mutex type[.](#general-1.sentence-3) [*Note [1](#general-note-1)*: The shared mutex types meet the [*Cpp17SharedLockable*](thread.req.lockable.shared#:Cpp17SharedLockable "32.2.5.5 Cpp17SharedLockable requirements [thread.req.lockable.shared]") requirements ([[thread.req.lockable.shared]](thread.req.lockable.shared "32.2.5.5 Cpp17SharedLockable requirements"))[.](#general-1.sentence-4) — *end note*] [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7826) In addition to the exclusive lock ownership mode specified in [[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types"), shared mutex types provide a[*shared lock*](#def:shared_lock "32.6.4.4.1 General [thread.sharedmutex.requirements.general]") ownership mode[.](#general-2.sentence-1) Multiple execution agents can simultaneously hold a shared lock ownership of a shared mutex type[.](#general-2.sentence-2) 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[.](#general-2.sentence-3) 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[.](#general-2.sentence-4) 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[.](#general-2.sentence-5) [3](#general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7841) The expression m.lock_shared() is well-formed and has the following semantics: [4](#general-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7845) *Preconditions*: The calling thread has no ownership of the mutex[.](#general-4.sentence-1) [5](#general-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7849) *Effects*: Blocks the calling thread until shared ownership of the mutex can be obtained for the calling thread[.](#general-5.sentence-1) If an exception is thrown then a shared lock has not been acquired for the current thread[.](#general-5.sentence-2) [6](#general-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7855) *Synchronization*: Prior unlock() operations on the same object synchronize with ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#general-6.sentence-1) [7](#general-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7859) *Postconditions*: The calling thread has a shared lock on the mutex[.](#general-7.sentence-1) [8](#general-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7863) *Return type*: void[.](#general-8.sentence-1) [9](#general-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7866) *Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#general-9.sentence-1) [10](#general-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7870) *Error conditions*: - [(10.1)](#general-10.1) operation_not_permitted — if the thread does not have the privilege to perform the operation[.](#general-10.1.sentence-1) - [(10.2)](#general-10.2) resource_deadlock_would_occur — if the implementation detects that a deadlock would occur[.](#general-10.2.sentence-1) [11](#general-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7878) The expression m.unlock_shared() is well-formed and has the following semantics: [12](#general-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7881) *Preconditions*: The calling thread holds a shared lock on the mutex[.](#general-12.sentence-1) [13](#general-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7885) *Effects*: Releases a shared lock on the mutex held by the calling thread[.](#general-13.sentence-1) [14](#general-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7889) *Return type*: void[.](#general-14.sentence-1) [15](#general-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7892) *Synchronization*: This operation [synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") subsequentlock() operations that obtain ownership on the same object[.](#general-15.sentence-1) [16](#general-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7897) *Throws*: Nothing[.](#general-16.sentence-1) [17](#general-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7902) The expression m.try_lock_shared() is well-formed and has the following semantics: [18](#general-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7905) *Preconditions*: The calling thread has no ownership of the mutex[.](#general-18.sentence-1) [19](#general-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7909) *Effects*: Attempts to obtain shared ownership of the mutex for the calling thread without blocking[.](#general-19.sentence-1) If shared ownership is not obtained, there is no effect and try_lock_shared() immediately returns[.](#general-19.sentence-2) An implementation may fail to obtain the lock even if it is not held by any other thread[.](#general-19.sentence-3) [20](#general-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7916) *Synchronization*: If try_lock_shared() returns true, prior unlock() operations on the same object synchronize with ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#general-20.sentence-1) [21](#general-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7922) *Return type*: bool[.](#general-21.sentence-1) [22](#general-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7925) *Returns*: true if the shared lock was acquired, otherwise false[.](#general-22.sentence-1) [23](#general-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7929) *Throws*: Nothing[.](#general-23.sentence-1) #### [32.6.4.4.2](#thread.sharedmutex.class) Class shared_mutex [[thread.sharedmutex.class]](thread.sharedmutex.class) [🔗](#lib:shared_mutex) namespace std {class shared_mutex {public: shared_mutex(); ~shared_mutex(); shared_mutex(const shared_mutex&) = delete; shared_mutex& operator=(const shared_mutex&) = delete; // exclusive ownershipvoid lock(); // blockingbool try_lock(); void unlock(); // shared ownershipvoid lock_shared(); // blockingbool try_lock_shared(); void unlock_shared(); using native_handle_type = *implementation-defined*; // see [[thread.req.native]](thread.req.native "32.2.3 Native handles") native_handle_type native_handle(); // see [[thread.req.native]](thread.req.native "32.2.3 Native handles")};} [1](#thread.sharedmutex.class-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7963) The class shared_mutex provides a non-recursive mutex with shared ownership semantics[.](#thread.sharedmutex.class-1.sentence-1) [2](#thread.sharedmutex.class-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7967) The class shared_mutex meets all of the shared mutex requirements ([thread.sharedmutex.requirements])[.](#thread.sharedmutex.class-2.sentence-1) It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#thread.sharedmutex.class-2.sentence-2) [3](#thread.sharedmutex.class-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7972) The behavior of a program is undefined if - [(3.1)](#thread.sharedmutex.class-3.1) it destroys a shared_mutex object owned by any thread, - [(3.2)](#thread.sharedmutex.class-3.2) a thread attempts to recursively gain any ownership of a shared_mutex, or - [(3.3)](#thread.sharedmutex.class-3.3) a thread terminates while possessing any ownership of a shared_mutex[.](#thread.sharedmutex.class-3.sentence-1) [4](#thread.sharedmutex.class-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7980) shared_mutex may be a synonym for shared_timed_mutex[.](#thread.sharedmutex.class-4.sentence-1)