[thread.lock.shared] # 32 Concurrency support library [[thread]](./#thread) ## 32.6 Mutual exclusion [[thread.mutex]](thread.mutex#thread.lock.shared) ### 32.6.5 Locks [[thread.lock]](thread.lock#shared) #### 32.6.5.5 Class template shared_lock [thread.lock.shared] #### [32.6.5.5.1](#general) General [[thread.lock.shared.general]](thread.lock.shared.general) [🔗](#lib:shared_lock) namespace std {templateclass shared_lock {public:using mutex_type = Mutex; // [[thread.lock.shared.cons]](#cons "32.6.5.5.2 Constructors, destructor, and assignment"), construct/copy/destroy shared_lock() noexcept; explicit shared_lock(mutex_type& m); // blocking shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template shared_lock(mutex_type& m, const chrono::time_point& abs_time); template shared_lock(mutex_type& m, const chrono::duration& rel_time); ~shared_lock(); shared_lock(const shared_lock&) = delete; shared_lock& operator=(const shared_lock&) = delete; shared_lock(shared_lock&& u) noexcept; shared_lock& operator=(shared_lock&& u) noexcept; // [[thread.lock.shared.locking]](#locking "32.6.5.5.3 Locking"), lockingvoid lock(); // blockingbool try_lock(); templatebool try_lock_for(const chrono::duration& rel_time); templatebool try_lock_until(const chrono::time_point& abs_time); void unlock(); // [[thread.lock.shared.mod]](#mod "32.6.5.5.4 Modifiers"), modifiersvoid swap(shared_lock& u) noexcept; mutex_type* release() noexcept; // [[thread.lock.shared.obs]](#obs "32.6.5.5.5 Observers"), observersbool owns_lock() const noexcept; explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: mutex_type* pm; // *exposition only*bool owns; // *exposition only*};} [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8881) An object of type shared_lock controls the shared ownership of a lockable object within a scope[.](#general-1.sentence-1) Shared ownership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another shared_lock object[.](#general-1.sentence-2) Objects of typeshared_lock are not copyable but are movable[.](#general-1.sentence-3) The behavior of a program is undefined if the contained pointer pm is not null and the lockable object pointed to by pm does not exist for the entire remaining lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) of the shared_lock object[.](#general-1.sentence-4) The suppliedMutex type shall 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-5) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8893) [*Note [1](#general-note-1)*: shared_lock meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3 Cpp17Lockable requirements"))[.](#general-2.sentence-1) If Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6 Cpp17SharedTimedLockable requirements")),shared_lock also meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4 Cpp17TimedLockable requirements"))[.](#general-2.sentence-2) — *end note*] #### [32.6.5.5.2](#cons) Constructors, destructor, and assignment [[thread.lock.shared.cons]](thread.lock.shared.cons) [🔗](#lib:shared_lock,constructor) `shared_lock() noexcept; ` [1](#cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8911) *Postconditions*: pm == nullptr and owns == false[.](#cons-1.sentence-1) [🔗](#lib:shared_lock,constructor_) `explicit shared_lock(mutex_type& m); ` [2](#cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8922) *Effects*: Calls m.lock_shared()[.](#cons-2.sentence-1) [3](#cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8926) *Postconditions*: pm == addressof(m) and owns == true[.](#cons-3.sentence-1) [🔗](#lib:shared_lock,constructor__) `shared_lock(mutex_type& m, defer_lock_t) noexcept; ` [4](#cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8937) *Postconditions*: pm == addressof(m) and owns == false[.](#cons-4.sentence-1) [🔗](#lib:shared_lock,constructor___) `shared_lock(mutex_type& m, try_to_lock_t); ` [5](#cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8948) *Effects*: Calls m.try_lock_shared()[.](#cons-5.sentence-1) [6](#cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8952) *Postconditions*: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared()[.](#cons-6.sentence-1) [🔗](#lib:shared_lock,constructor____) `shared_lock(mutex_type& m, adopt_lock_t); ` [7](#cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8965) *Preconditions*: The calling thread holds a shared lock on m[.](#cons-7.sentence-1) [8](#cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8969) *Postconditions*: pm == addressof(m) and owns == true[.](#cons-8.sentence-1) [🔗](#lib:shared_lock,constructor_____) `template shared_lock(mutex_type& m, const chrono::time_point& abs_time); ` [9](#cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8982) *Preconditions*: Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6 Cpp17SharedTimedLockable requirements"))[.](#cons-9.sentence-1) [10](#cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8987) *Effects*: Calls m.try_lock_shared_until(abs_time)[.](#cons-10.sentence-1) [11](#cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8991) *Postconditions*: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_until(abs_time)[.](#cons-11.sentence-1) [🔗](#lib:shared_lock,constructor______) `template shared_lock(mutex_type& m, const chrono::duration& rel_time); ` [12](#cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9006) *Preconditions*: Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6 Cpp17SharedTimedLockable requirements"))[.](#cons-12.sentence-1) [13](#cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9011) *Effects*: Calls m.try_lock_shared_for(rel_time)[.](#cons-13.sentence-1) [14](#cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9015) *Postconditions*: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_for(rel_time)[.](#cons-14.sentence-1) [🔗](#lib:shared_lock,destructor) `~shared_lock(); ` [15](#cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9028) *Effects*: If owns calls pm->unlock_shared()[.](#cons-15.sentence-1) [🔗](#lib:shared_lock,constructor_______) `shared_lock(shared_lock&& sl) noexcept; ` [16](#cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9039) *Postconditions*: pm == sl_p.pm and owns == sl_p.owns (wheresl_p is the state of sl just prior to this construction),sl.pm == nullptr and sl.owns == false[.](#cons-16.sentence-1) [🔗](#lib:operator=,shared_lock) `shared_lock& operator=(shared_lock&& sl) noexcept; ` [17](#cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9052) *Effects*: Equivalent to: shared_lock(std​::​move(sl)).swap(*this) [18](#cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9056) *Returns*: *this[.](#cons-18.sentence-1) #### [32.6.5.5.3](#locking) Locking [[thread.lock.shared.locking]](thread.lock.shared.locking) [🔗](#lib:lock,shared_lock) `void lock(); ` [1](#locking-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9069) *Effects*: As if by pm->lock_shared()[.](#locking-1.sentence-1) [2](#locking-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9073) *Postconditions*: owns == true[.](#locking-2.sentence-1) [3](#locking-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9077) *Throws*: Any exception thrown by pm->lock_shared()[.](#locking-3.sentence-1) system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#locking-3.sentence-2) [4](#locking-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9082) *Error conditions*: - [(4.1)](#locking-4.1) operation_not_permitted — if pm is nullptr[.](#locking-4.1.sentence-1) - [(4.2)](#locking-4.2) resource_deadlock_would_occur — if on entry owns istrue[.](#locking-4.2.sentence-1) [🔗](#lib:try_lock,shared_lock) `bool try_lock(); ` [5](#locking-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9097) *Effects*: As if by pm->try_lock_shared()[.](#locking-5.sentence-1) [6](#locking-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9101) *Postconditions*: owns == res, where res is the value returned by the call to pm->try_lock_shared()[.](#locking-6.sentence-1) [7](#locking-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9106) *Returns*: The value returned by the call to pm->try_lock_shared()[.](#locking-7.sentence-1) [8](#locking-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9110) *Throws*: Any exception thrown by pm->try_lock_shared()[.](#locking-8.sentence-1) system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#locking-8.sentence-2) [9](#locking-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9115) *Error conditions*: - [(9.1)](#locking-9.1) operation_not_permitted — if pm is nullptr[.](#locking-9.1.sentence-1) - [(9.2)](#locking-9.2) resource_deadlock_would_occur — if on entry owns istrue[.](#locking-9.2.sentence-1) [🔗](#lib:try_lock_until,shared_lock) `template bool try_lock_until(const chrono::time_point& abs_time); ` [10](#locking-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9131) *Preconditions*: Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6 Cpp17SharedTimedLockable requirements"))[.](#locking-10.sentence-1) [11](#locking-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9136) *Effects*: As if by pm->try_lock_shared_until(abs_time)[.](#locking-11.sentence-1) [12](#locking-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9140) *Postconditions*: owns == res, where res is the value returned by the call to pm->try_lock_shared_until(abs_time)[.](#locking-12.sentence-1) [13](#locking-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9145) *Returns*: The value returned by the call topm->try_lock_shared_until(abs_time)[.](#locking-13.sentence-1) [14](#locking-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9150) *Throws*: Any exception thrown by pm->try_lock_shared_until(abs_time)[.](#locking-14.sentence-1) system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#locking-14.sentence-2) [15](#locking-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9155) *Error conditions*: - [(15.1)](#locking-15.1) operation_not_permitted — if pm is nullptr[.](#locking-15.1.sentence-1) - [(15.2)](#locking-15.2) resource_deadlock_would_occur — if on entry owns istrue[.](#locking-15.2.sentence-1) [🔗](#lib:try_lock_for,shared_lock) `template bool try_lock_for(const chrono::duration& rel_time); ` [16](#locking-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9171) *Preconditions*: Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6 Cpp17SharedTimedLockable requirements"))[.](#locking-16.sentence-1) [17](#locking-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9176) *Effects*: As if by pm->try_lock_shared_for(rel_time)[.](#locking-17.sentence-1) [18](#locking-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9180) *Postconditions*: owns == res, where res is the value returned by the call to pm->try_lock_shared_for(rel_time)[.](#locking-18.sentence-1) [19](#locking-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9184) *Returns*: The value returned by the call to pm->try_lock_shared_for(rel_time)[.](#locking-19.sentence-1) [20](#locking-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9188) *Throws*: Any exception thrown by pm->try_lock_shared_for(rel_time)[.](#locking-20.sentence-1) system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#locking-20.sentence-2) [21](#locking-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9192) *Error conditions*: - [(21.1)](#locking-21.1) operation_not_permitted — if pm is nullptr[.](#locking-21.1.sentence-1) - [(21.2)](#locking-21.2) resource_deadlock_would_occur — if on entry owns istrue[.](#locking-21.2.sentence-1) [🔗](#lib:unlock,shared_lock) `void unlock(); ` [22](#locking-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9207) *Effects*: As if by pm->unlock_shared()[.](#locking-22.sentence-1) [23](#locking-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9211) *Postconditions*: owns == false[.](#locking-23.sentence-1) [24](#locking-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9215) *Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#locking-24.sentence-1) [25](#locking-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9219) *Error conditions*: - [(25.1)](#locking-25.1) operation_not_permitted — if on entry owns isfalse[.](#locking-25.sentence-1) #### [32.6.5.5.4](#mod) Modifiers [[thread.lock.shared.mod]](thread.lock.shared.mod) [🔗](#lib:swap,shared_lock) `void swap(shared_lock& sl) noexcept; ` [1](#mod-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9235) *Effects*: Swaps the data members of *this and sl[.](#mod-1.sentence-1) [🔗](#lib:release,shared_lock) `mutex_type* release() noexcept; ` [2](#mod-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9246) *Postconditions*: pm == nullptr and owns == false[.](#mod-2.sentence-1) [3](#mod-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9250) *Returns*: The previous value of pm[.](#mod-3.sentence-1) [🔗](#lib:swap,shared_lock_) `template void swap(shared_lock& x, shared_lock& y) noexcept; ` [4](#mod-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9262) *Effects*: As if by x.swap(y)[.](#mod-4.sentence-1) #### [32.6.5.5.5](#obs) Observers [[thread.lock.shared.obs]](thread.lock.shared.obs) [🔗](#lib:owns_lock,shared_lock) `bool owns_lock() const noexcept; ` [1](#obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9275) *Returns*: owns[.](#obs-1.sentence-1) [🔗](#lib:operator_bool,shared_lock) `explicit operator bool() const noexcept; ` [2](#obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9286) *Returns*: owns[.](#obs-2.sentence-1) [🔗](#lib:mutex,shared_lock) `mutex_type* mutex() const noexcept; ` [3](#obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9297) *Returns*: pm[.](#obs-3.sentence-1)