Files
2025-10-25 03:02:53 +03:00

1259 lines
48 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[thread.lock]
# 32 Concurrency support library [[thread]](./#thread)
## 32.6 Mutual exclusion [[thread.mutex]](thread.mutex#thread.lock)
### 32.6.5 Locks [thread.lock]
#### [32.6.5.1](#general) General [[thread.lock.general]](thread.lock.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8144)
A [*lock*](#def:lock) is an object that holds a reference to a lockable object and may unlock the
lockable object during the lock's destruction (such as when leaving block scope)[.](#general-1.sentence-1)
An execution
agent may use a lock to aid in managing ownership of a lockable object in an exception safe
manner[.](#general-1.sentence-2)
A lock is said to [*own*](#def:own) a lockable object if it is currently managing the
ownership of that lockable object for an execution agent[.](#general-1.sentence-3)
A lock does not manage the lifetime
of the lockable object it references[.](#general-1.sentence-4)
[*Note [1](#general-note-1)*:
Locks are intended to ease the burden of
unlocking the lockable object under both normal and exceptional circumstances[.](#general-1.sentence-5)
— *end note*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8156)
Some lock constructors take tag types which describe what should be done with the lockable
object during the lock's construction[.](#general-2.sentence-1)
[🔗](#lib:defer_lock_t)
namespace std {struct defer_lock_t { }; // do not acquire ownership of the mutexstruct try_to_lock_t { }; // try to acquire ownership of the mutex// without blockingstruct adopt_lock_t { }; // assume the calling thread has already// obtained mutex ownership and manage itinline constexpr defer_lock_t defer_lock { }; inline constexpr try_to_lock_t try_to_lock { }; inline constexpr adopt_lock_t adopt_lock { };}
#### [32.6.5.2](#guard) Class template lock_guard [[thread.lock.guard]](thread.lock.guard)
[🔗](#lib:lock_guard)
namespace std {template<class Mutex>class lock_guard {public:using mutex_type = Mutex; explicit lock_guard(mutex_type& m);
lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard();
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete; private: mutex_type& pm; // *exposition only*};}
[1](#guard-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8203)
An object of type lock_guard controls the ownership of a lockable object
within a scope[.](#guard-1.sentence-1)
A lock_guard object maintains ownership of a lockable
object throughout the lock_guard object's [lifetime](basic.life#def:lifetime "6.8.4Lifetime[basic.life]")[.](#guard-1.sentence-2)
The behavior of a program is undefined if the lockable object referenced bypm does not exist for the entire lifetime of the lock_guard object[.](#guard-1.sentence-3)
The supplied Mutex type shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2Cpp17BasicLockable requirements[thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2Cpp17BasicLockable requirements"))[.](#guard-1.sentence-4)
[🔗](#lib:lock_guard,constructor)
`explicit lock_guard(mutex_type& m);
`
[2](#guard-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8218)
*Effects*: Initializes pm with m[.](#guard-2.sentence-1)
Calls m.lock()[.](#guard-2.sentence-2)
[🔗](#lib:lock_guard,constructor_)
`lock_guard(mutex_type& m, adopt_lock_t);
`
[3](#guard-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8229)
*Preconditions*: The calling thread holds a non-shared lock on m[.](#guard-3.sentence-1)
[4](#guard-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8233)
*Effects*: Initializes pm with m[.](#guard-4.sentence-1)
[5](#guard-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8237)
*Throws*: Nothing[.](#guard-5.sentence-1)
[🔗](#lib:lock_guard,destructor)
`~lock_guard();
`
[6](#guard-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8248)
*Effects*: Equivalent to: pm.unlock()
#### [32.6.5.3](#scoped) Class template scoped_lock [[thread.lock.scoped]](thread.lock.scoped)
[🔗](#lib:scoped_lock)
namespace std {template<class... MutexTypes>class scoped_lock {public:using mutex_type = *see below*; // Only if sizeof...(MutexTypes) == 1 is trueexplicit scoped_lock(MutexTypes&... m); explicit scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock();
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete; private: tuple<MutexTypes&...> pm; // *exposition only*};}
[1](#scoped-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8276)
An object of type scoped_lock controls the ownership of lockable objects
within a scope[.](#scoped-1.sentence-1)
A scoped_lock object maintains ownership of lockable
objects throughout the scoped_lock object's [lifetime](basic.life#def:lifetime "6.8.4Lifetime[basic.life]")[.](#scoped-1.sentence-2)
The behavior of a program is undefined if the lockable objects referenced bypm do not exist for the entire lifetime of the scoped_lock object[.](#scoped-1.sentence-3)
- [(1.1)](#scoped-1.1)
If sizeof...(MutexTypes) is one,
let Mutex denote the sole type constituting the pack MutexTypes[.](#scoped-1.1.sentence-1)
Mutex shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2Cpp17BasicLockable requirements[thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2Cpp17BasicLockable requirements"))[.](#scoped-1.1.sentence-2)
The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") mutex_type denotes the same type as Mutex[.](#scoped-1.1.sentence-3)
- [(1.2)](#scoped-1.2)
Otherwise, all types in the template parameter pack MutexTypes shall meet the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3Cpp17Lockable requirements"))
and there is no member mutex_type[.](#scoped-1.2.sentence-1)
[🔗](#lib:scoped_lock,constructor)
`explicit scoped_lock(MutexTypes&... m);
`
[2](#scoped-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8303)
*Effects*: Initializes pm with tie(m...)[.](#scoped-2.sentence-1)
Then if sizeof...(MutexTypes) is 0, no effects[.](#scoped-2.sentence-2)
Otherwise if sizeof...(MutexTypes) is 1, then m.lock()[.](#scoped-2.sentence-3)
Otherwise, lock(m...)[.](#scoped-2.sentence-4)
[🔗](#lib:scoped_lock,constructor_)
`explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
`
[3](#scoped-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8317)
*Preconditions*: The calling thread holds a non-shared lock on each element of m[.](#scoped-3.sentence-1)
[4](#scoped-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8321)
*Effects*: Initializes pm with tie(m...)[.](#scoped-4.sentence-1)
[5](#scoped-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8325)
*Throws*: Nothing[.](#scoped-5.sentence-1)
[🔗](#lib:scoped_lock,destructor)
`~scoped_lock();
`
[6](#scoped-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8336)
*Effects*: For all i in [0, sizeof...(MutexTypes)),get<i>(pm).unlock()[.](#scoped-6.sentence-1)
#### [32.6.5.4](#unique) Class template unique_lock [[thread.lock.unique]](thread.lock.unique)
#### [32.6.5.4.1](#unique.general) General [[thread.lock.unique.general]](thread.lock.unique.general)
[🔗](#lib:unique_lock)
namespace std {template<class Mutex>class unique_lock {public:using mutex_type = Mutex; // [[thread.lock.unique.cons]](#unique.cons "32.6.5.4.2Constructors, destructor, and assignment"), construct/copy/destroy unique_lock() noexcept; explicit unique_lock(mutex_type& m);
unique_lock(mutex_type& m, defer_lock_t) noexcept;
unique_lock(mutex_type& m, try_to_lock_t);
unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); ~unique_lock();
unique_lock(const unique_lock&) = delete;
unique_lock& operator=(const unique_lock&) = delete;
unique_lock(unique_lock&& u) noexcept;
unique_lock& operator=(unique_lock&& u) noexcept; // [[thread.lock.unique.locking]](#unique.locking "32.6.5.4.3Locking"), lockingvoid lock(); bool try_lock(); template<class Rep, class Period>bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration>bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); // [[thread.lock.unique.mod]](#unique.mod "32.6.5.4.4Modifiers"), modifiersvoid swap(unique_lock& u) noexcept;
mutex_type* release() noexcept; // [[thread.lock.unique.obs]](#unique.obs "32.6.5.4.5Observers"), 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](#unique.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8399)
An object of type unique_lock controls the ownership of a lockable
object within a scope[.](#unique.general-1.sentence-1)
Ownership of the lockable object may be acquired at
construction or after construction, and may be transferred, after
acquisition, to another unique_lock object[.](#unique.general-1.sentence-2)
Objects of type unique_lock are not
copyable but are movable[.](#unique.general-1.sentence-3)
The behavior of a program is undefined if the contained pointerpm 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.4Lifetime")) of the unique_lock object[.](#unique.general-1.sentence-4)
The suppliedMutex type shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2Cpp17BasicLockable requirements[thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2Cpp17BasicLockable requirements"))[.](#unique.general-1.sentence-5)
[2](#unique.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8411)
[*Note [1](#unique.general-note-1)*:
unique_lock<Mutex> meets the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2Cpp17BasicLockable requirements[thread.req.lockable.basic]") requirements[.](#unique.general-2.sentence-1)
If Mutex meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3Cpp17Lockable requirements")),unique_lock<Mutex> also meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements;
if Mutex meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements")),unique_lock<Mutex> also meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements[.](#unique.general-2.sentence-2)
— *end note*]
#### [32.6.5.4.2](#unique.cons) Constructors, destructor, and assignment [[thread.lock.unique.cons]](thread.lock.unique.cons)
[🔗](#lib:unique_lock,constructor)
`unique_lock() noexcept;
`
[1](#unique.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8429)
*Postconditions*: pm == nullptr and owns == false[.](#unique.cons-1.sentence-1)
[🔗](#lib:unique_lock,constructor_)
`explicit unique_lock(mutex_type& m);
`
[2](#unique.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8440)
*Effects*: Calls m.lock()[.](#unique.cons-2.sentence-1)
[3](#unique.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8444)
*Postconditions*: pm == addressof(m) and owns == true[.](#unique.cons-3.sentence-1)
[🔗](#lib:unique_lock,constructor__)
`unique_lock(mutex_type& m, defer_lock_t) noexcept;
`
[4](#unique.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8455)
*Postconditions*: pm == addressof(m) and owns == false[.](#unique.cons-4.sentence-1)
[🔗](#lib:unique_lock,constructor___)
`unique_lock(mutex_type& m, try_to_lock_t);
`
[5](#unique.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8466)
*Preconditions*: The supplied Mutex type meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3Cpp17Lockable requirements"))[.](#unique.cons-5.sentence-1)
[6](#unique.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8471)
*Effects*: Calls m.try_lock()[.](#unique.cons-6.sentence-1)
[7](#unique.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8475)
*Postconditions*: pm == addressof(m) and owns == res,
where res is the value returned by the call to m.try_lock()[.](#unique.cons-7.sentence-1)
[🔗](#lib:unique_lock,constructor____)
`unique_lock(mutex_type& m, adopt_lock_t);
`
[8](#unique.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8487)
*Preconditions*: The calling thread holds a non-shared lock on m[.](#unique.cons-8.sentence-1)
[9](#unique.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8491)
*Postconditions*: pm == addressof(m) and owns == true[.](#unique.cons-9.sentence-1)
[10](#unique.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8495)
*Throws*: Nothing[.](#unique.cons-10.sentence-1)
[🔗](#lib:unique_lock,constructor_____)
`template<class Clock, class Duration>
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
`
[11](#unique.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8507)
*Preconditions*: The supplied Mutex type meets the[*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements"))[.](#unique.cons-11.sentence-1)
[12](#unique.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8512)
*Effects*: Calls m.try_lock_until(abs_time)[.](#unique.cons-12.sentence-1)
[13](#unique.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8516)
*Postconditions*: pm == addressof(m) and owns == res,
where res is
the value returned by the call to m.try_lock_until(abs_time)[.](#unique.cons-13.sentence-1)
[🔗](#lib:unique_lock,constructor______)
`template<class Rep, class Period>
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
`
[14](#unique.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8530)
*Preconditions*: The supplied Mutex type meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements"))[.](#unique.cons-14.sentence-1)
[15](#unique.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8534)
*Effects*: Calls m.try_lock_for(rel_time)[.](#unique.cons-15.sentence-1)
[16](#unique.cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8538)
*Postconditions*: pm == addressof(m) and owns == res,
where res is the value returned by the call to m.try_lock_for(rel_time)[.](#unique.cons-16.sentence-1)
[🔗](#lib:unique_lock,constructor_______)
`unique_lock(unique_lock&& u) noexcept;
`
[17](#unique.cons-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8550)
*Postconditions*: pm == u_p.pm and owns == u_p.owns (where u_p is the state of u just prior to this construction), u.pm == 0 and u.owns == false[.](#unique.cons-17.sentence-1)
[🔗](#lib:operator=,unique_lock)
`unique_lock& operator=(unique_lock&& u) noexcept;
`
[18](#unique.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8561)
*Effects*: Equivalent to: unique_lock(std::move(u)).swap(*this)
[19](#unique.cons-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8565)
*Returns*: *this[.](#unique.cons-19.sentence-1)
[🔗](#lib:unique_lock,destructor)
`~unique_lock();
`
[20](#unique.cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8576)
*Effects*: If owns calls pm->unlock()[.](#unique.cons-20.sentence-1)
#### [32.6.5.4.3](#unique.locking) Locking [[thread.lock.unique.locking]](thread.lock.unique.locking)
[🔗](#lib:lock,unique_lock)
`void lock();
`
[1](#unique.locking-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8589)
*Effects*: As if by pm->lock()[.](#unique.locking-1.sentence-1)
[2](#unique.locking-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8593)
*Postconditions*: owns == true[.](#unique.locking-2.sentence-1)
[3](#unique.locking-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8597)
*Throws*: Any exception thrown by pm->lock()[.](#unique.locking-3.sentence-1)
system_error when an exception
is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#unique.locking-3.sentence-2)
[4](#unique.locking-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8602)
*Error conditions*:
- [(4.1)](#unique.locking-4.1)
operation_not_permitted — if pm is nullptr[.](#unique.locking-4.1.sentence-1)
- [(4.2)](#unique.locking-4.2)
resource_deadlock_would_occur — if on entry owns is true[.](#unique.locking-4.2.sentence-1)
[🔗](#lib:try_lock,unique_lock)
`bool try_lock();
`
[5](#unique.locking-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8617)
*Preconditions*: The supplied Mutex meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3Cpp17Lockable requirements"))[.](#unique.locking-5.sentence-1)
[6](#unique.locking-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8622)
*Effects*: As if by pm->try_lock()[.](#unique.locking-6.sentence-1)
[7](#unique.locking-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8626)
*Postconditions*: owns == res, where res is the value returned bypm->try_lock()[.](#unique.locking-7.sentence-1)
[8](#unique.locking-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8631)
*Returns*: The value returned by pm->try_lock()[.](#unique.locking-8.sentence-1)
[9](#unique.locking-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8635)
*Throws*: Any exception thrown by pm->try_lock()[.](#unique.locking-9.sentence-1)
system_error when an exception
is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#unique.locking-9.sentence-2)
[10](#unique.locking-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8640)
*Error conditions*:
- [(10.1)](#unique.locking-10.1)
operation_not_permitted — if pm is nullptr[.](#unique.locking-10.1.sentence-1)
- [(10.2)](#unique.locking-10.2)
resource_deadlock_would_occur — if on entry owns is true[.](#unique.locking-10.2.sentence-1)
[🔗](#lib:try_lock_until,unique_lock)
`template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
`
[11](#unique.locking-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8656)
*Preconditions*: The supplied Mutex type meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements"))[.](#unique.locking-11.sentence-1)
[12](#unique.locking-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8661)
*Effects*: As if by pm->try_lock_until(abs_time)[.](#unique.locking-12.sentence-1)
[13](#unique.locking-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8665)
*Postconditions*: owns == res, where res is the value returned bypm->try_lock_until(abs_time)[.](#unique.locking-13.sentence-1)
[14](#unique.locking-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8670)
*Returns*: The value returned by pm->try_lock_until(abs_time)[.](#unique.locking-14.sentence-1)
[15](#unique.locking-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8674)
*Throws*: Any exception thrown by pm->try_lock_until(abstime)[.](#unique.locking-15.sentence-1)
system_error when an
exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#unique.locking-15.sentence-2)
[16](#unique.locking-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8679)
*Error conditions*:
- [(16.1)](#unique.locking-16.1)
operation_not_permitted — if pm is nullptr[.](#unique.locking-16.1.sentence-1)
- [(16.2)](#unique.locking-16.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#unique.locking-16.2.sentence-1)
[🔗](#lib:try_lock_for,unique_lock)
`template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
`
[17](#unique.locking-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8695)
*Preconditions*: The supplied Mutex type meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements"))[.](#unique.locking-17.sentence-1)
[18](#unique.locking-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8699)
*Effects*: As if by pm->try_lock_for(rel_time)[.](#unique.locking-18.sentence-1)
[19](#unique.locking-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8703)
*Postconditions*: owns == res, where res is the value returned by pm->try_lock_for(rel_time)[.](#unique.locking-19.sentence-1)
[20](#unique.locking-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8707)
*Returns*: The value returned by pm->try_lock_for(rel_time)[.](#unique.locking-20.sentence-1)
[21](#unique.locking-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8711)
*Throws*: Any exception thrown by pm->try_lock_for(rel_time)[.](#unique.locking-21.sentence-1)
system_error when an
exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#unique.locking-21.sentence-2)
[22](#unique.locking-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8716)
*Error conditions*:
- [(22.1)](#unique.locking-22.1)
operation_not_permitted — if pm is nullptr[.](#unique.locking-22.1.sentence-1)
- [(22.2)](#unique.locking-22.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#unique.locking-22.2.sentence-1)
[🔗](#lib:unlock,unique_lock)
`void unlock();
`
[23](#unique.locking-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8731)
*Effects*: As if by pm->unlock()[.](#unique.locking-23.sentence-1)
[24](#unique.locking-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8735)
*Postconditions*: owns == false[.](#unique.locking-24.sentence-1)
[25](#unique.locking-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8739)
*Throws*: system_error when
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#unique.locking-25.sentence-1)
[26](#unique.locking-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8744)
*Error conditions*:
- [(26.1)](#unique.locking-26.1)
operation_not_permitted — if on entry owns is false[.](#unique.locking-26.sentence-1)
#### [32.6.5.4.4](#unique.mod) Modifiers [[thread.lock.unique.mod]](thread.lock.unique.mod)
[🔗](#lib:swap,unique_lock)
`void swap(unique_lock& u) noexcept;
`
[1](#unique.mod-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8759)
*Effects*: Swaps the data members of *this and u[.](#unique.mod-1.sentence-1)
[🔗](#lib:release,unique_lock)
`mutex_type* release() noexcept;
`
[2](#unique.mod-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8770)
*Postconditions*: pm == 0 and owns == false[.](#unique.mod-2.sentence-1)
[3](#unique.mod-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8774)
*Returns*: The previous value of pm[.](#unique.mod-3.sentence-1)
[🔗](#lib:swap,unique_lock_)
`template<class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
`
[4](#unique.mod-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8786)
*Effects*: As if by x.swap(y)[.](#unique.mod-4.sentence-1)
#### [32.6.5.4.5](#unique.obs) Observers [[thread.lock.unique.obs]](thread.lock.unique.obs)
[🔗](#lib:owns_lock,unique_lock)
`bool owns_lock() const noexcept;
`
[1](#unique.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8799)
*Returns*: owns[.](#unique.obs-1.sentence-1)
[🔗](#lib:operator_bool,unique_lock)
`explicit operator bool() const noexcept;
`
[2](#unique.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8810)
*Returns*: owns[.](#unique.obs-2.sentence-1)
[🔗](#lib:mutex,unique_lock)
`mutex_type *mutex() const noexcept;
`
[3](#unique.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8821)
*Returns*: pm[.](#unique.obs-3.sentence-1)
#### [32.6.5.5](#shared) Class template shared_lock [[thread.lock.shared]](thread.lock.shared)
#### [32.6.5.5.1](#shared.general) General [[thread.lock.shared.general]](thread.lock.shared.general)
[🔗](#lib:shared_lock)
namespace std {template<class Mutex>class shared_lock {public:using mutex_type = Mutex; // [[thread.lock.shared.cons]](#shared.cons "32.6.5.5.2Constructors, 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<class Clock, class Duration> shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& 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]](#shared.locking "32.6.5.5.3Locking"), lockingvoid lock(); // blockingbool try_lock(); template<class Rep, class Period>bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration>bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); // [[thread.lock.shared.mod]](#shared.mod "32.6.5.5.4Modifiers"), modifiersvoid swap(shared_lock& u) noexcept;
mutex_type* release() noexcept; // [[thread.lock.shared.obs]](#shared.obs "32.6.5.5.5Observers"), 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](#shared.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[.](#shared.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[.](#shared.general-1.sentence-2)
Objects of typeshared_lock are not copyable but are movable[.](#shared.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.4Lifetime")) of the shared_lock object[.](#shared.general-1.sentence-4)
The suppliedMutex type shall meet the [*Cpp17SharedLockable*](thread.req.lockable.shared#:Cpp17SharedLockable "32.2.5.5Cpp17SharedLockable requirements[thread.req.lockable.shared]") requirements ([[thread.req.lockable.shared]](thread.req.lockable.shared "32.2.5.5Cpp17SharedLockable requirements"))[.](#shared.general-1.sentence-5)
[2](#shared.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8893)
[*Note [1](#shared.general-note-1)*:
shared_lock<Mutex> meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3Cpp17Lockable requirements"))[.](#shared.general-2.sentence-1)
If Mutex meets the [*Cpp17SharedTimedLockable*](thread.req.lockable.shared.timed#:Cpp17SharedTimedLockable "32.2.5.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable requirements")),shared_lock<Mutex> also meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4Cpp17TimedLockable requirements"))[.](#shared.general-2.sentence-2)
— *end note*]
#### [32.6.5.5.2](#shared.cons) Constructors, destructor, and assignment [[thread.lock.shared.cons]](thread.lock.shared.cons)
[🔗](#lib:shared_lock,constructor)
`shared_lock() noexcept;
`
[1](#shared.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8911)
*Postconditions*: pm == nullptr and owns == false[.](#shared.cons-1.sentence-1)
[🔗](#lib:shared_lock,constructor_)
`explicit shared_lock(mutex_type& m);
`
[2](#shared.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8922)
*Effects*: Calls m.lock_shared()[.](#shared.cons-2.sentence-1)
[3](#shared.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8926)
*Postconditions*: pm == addressof(m) and owns == true[.](#shared.cons-3.sentence-1)
[🔗](#lib:shared_lock,constructor__)
`shared_lock(mutex_type& m, defer_lock_t) noexcept;
`
[4](#shared.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8937)
*Postconditions*: pm == addressof(m) and owns == false[.](#shared.cons-4.sentence-1)
[🔗](#lib:shared_lock,constructor___)
`shared_lock(mutex_type& m, try_to_lock_t);
`
[5](#shared.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8948)
*Effects*: Calls m.try_lock_shared()[.](#shared.cons-5.sentence-1)
[6](#shared.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()[.](#shared.cons-6.sentence-1)
[🔗](#lib:shared_lock,constructor____)
`shared_lock(mutex_type& m, adopt_lock_t);
`
[7](#shared.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8965)
*Preconditions*: The calling thread holds a shared lock on m[.](#shared.cons-7.sentence-1)
[8](#shared.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8969)
*Postconditions*: pm == addressof(m) and owns == true[.](#shared.cons-8.sentence-1)
[🔗](#lib:shared_lock,constructor_____)
`template<class Clock, class Duration>
shared_lock(mutex_type& m,
const chrono::time_point<Clock, Duration>& abs_time);
`
[9](#shared.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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable requirements"))[.](#shared.cons-9.sentence-1)
[10](#shared.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8987)
*Effects*: Calls m.try_lock_shared_until(abs_time)[.](#shared.cons-10.sentence-1)
[11](#shared.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)[.](#shared.cons-11.sentence-1)
[🔗](#lib:shared_lock,constructor______)
`template<class Rep, class Period>
shared_lock(mutex_type& m,
const chrono::duration<Rep, Period>& rel_time);
`
[12](#shared.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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable requirements"))[.](#shared.cons-12.sentence-1)
[13](#shared.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9011)
*Effects*: Calls m.try_lock_shared_for(rel_time)[.](#shared.cons-13.sentence-1)
[14](#shared.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)[.](#shared.cons-14.sentence-1)
[🔗](#lib:shared_lock,destructor)
`~shared_lock();
`
[15](#shared.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9028)
*Effects*: If owns calls pm->unlock_shared()[.](#shared.cons-15.sentence-1)
[🔗](#lib:shared_lock,constructor_______)
`shared_lock(shared_lock&& sl) noexcept;
`
[16](#shared.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[.](#shared.cons-16.sentence-1)
[🔗](#lib:operator=,shared_lock)
`shared_lock& operator=(shared_lock&& sl) noexcept;
`
[17](#shared.cons-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9052)
*Effects*: Equivalent to: shared_lock(std::move(sl)).swap(*this)
[18](#shared.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9056)
*Returns*: *this[.](#shared.cons-18.sentence-1)
#### [32.6.5.5.3](#shared.locking) Locking [[thread.lock.shared.locking]](thread.lock.shared.locking)
[🔗](#lib:lock,shared_lock)
`void lock();
`
[1](#shared.locking-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9069)
*Effects*: As if by pm->lock_shared()[.](#shared.locking-1.sentence-1)
[2](#shared.locking-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9073)
*Postconditions*: owns == true[.](#shared.locking-2.sentence-1)
[3](#shared.locking-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9077)
*Throws*: Any exception thrown by pm->lock_shared()[.](#shared.locking-3.sentence-1)
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#shared.locking-3.sentence-2)
[4](#shared.locking-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9082)
*Error conditions*:
- [(4.1)](#shared.locking-4.1)
operation_not_permitted — if pm is nullptr[.](#shared.locking-4.1.sentence-1)
- [(4.2)](#shared.locking-4.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#shared.locking-4.2.sentence-1)
[🔗](#lib:try_lock,shared_lock)
`bool try_lock();
`
[5](#shared.locking-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9097)
*Effects*: As if by pm->try_lock_shared()[.](#shared.locking-5.sentence-1)
[6](#shared.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()[.](#shared.locking-6.sentence-1)
[7](#shared.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()[.](#shared.locking-7.sentence-1)
[8](#shared.locking-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9110)
*Throws*: Any exception thrown by pm->try_lock_shared()[.](#shared.locking-8.sentence-1)
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#shared.locking-8.sentence-2)
[9](#shared.locking-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9115)
*Error conditions*:
- [(9.1)](#shared.locking-9.1)
operation_not_permitted — if pm is nullptr[.](#shared.locking-9.1.sentence-1)
- [(9.2)](#shared.locking-9.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#shared.locking-9.2.sentence-1)
[🔗](#lib:try_lock_until,shared_lock)
`template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
`
[10](#shared.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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable requirements"))[.](#shared.locking-10.sentence-1)
[11](#shared.locking-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9136)
*Effects*: As if by pm->try_lock_shared_until(abs_time)[.](#shared.locking-11.sentence-1)
[12](#shared.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)[.](#shared.locking-12.sentence-1)
[13](#shared.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)[.](#shared.locking-13.sentence-1)
[14](#shared.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)[.](#shared.locking-14.sentence-1)
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#shared.locking-14.sentence-2)
[15](#shared.locking-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9155)
*Error conditions*:
- [(15.1)](#shared.locking-15.1)
operation_not_permitted — if pm is nullptr[.](#shared.locking-15.1.sentence-1)
- [(15.2)](#shared.locking-15.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#shared.locking-15.2.sentence-1)
[🔗](#lib:try_lock_for,shared_lock)
`template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
`
[16](#shared.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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable requirements"))[.](#shared.locking-16.sentence-1)
[17](#shared.locking-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9176)
*Effects*: As if by pm->try_lock_shared_for(rel_time)[.](#shared.locking-17.sentence-1)
[18](#shared.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)[.](#shared.locking-18.sentence-1)
[19](#shared.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)[.](#shared.locking-19.sentence-1)
[20](#shared.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)[.](#shared.locking-20.sentence-1)
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#shared.locking-20.sentence-2)
[21](#shared.locking-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9192)
*Error conditions*:
- [(21.1)](#shared.locking-21.1)
operation_not_permitted — if pm is nullptr[.](#shared.locking-21.1.sentence-1)
- [(21.2)](#shared.locking-21.2)
resource_deadlock_would_occur — if on entry owns istrue[.](#shared.locking-21.2.sentence-1)
[🔗](#lib:unlock,shared_lock)
`void unlock();
`
[22](#shared.locking-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9207)
*Effects*: As if by pm->unlock_shared()[.](#shared.locking-22.sentence-1)
[23](#shared.locking-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9211)
*Postconditions*: owns == false[.](#shared.locking-23.sentence-1)
[24](#shared.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.2Exceptions"))[.](#shared.locking-24.sentence-1)
[25](#shared.locking-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9219)
*Error conditions*:
- [(25.1)](#shared.locking-25.1)
operation_not_permitted — if on entry owns isfalse[.](#shared.locking-25.sentence-1)
#### [32.6.5.5.4](#shared.mod) Modifiers [[thread.lock.shared.mod]](thread.lock.shared.mod)
[🔗](#lib:swap,shared_lock)
`void swap(shared_lock& sl) noexcept;
`
[1](#shared.mod-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9235)
*Effects*: Swaps the data members of *this and sl[.](#shared.mod-1.sentence-1)
[🔗](#lib:release,shared_lock)
`mutex_type* release() noexcept;
`
[2](#shared.mod-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9246)
*Postconditions*: pm == nullptr and owns == false[.](#shared.mod-2.sentence-1)
[3](#shared.mod-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9250)
*Returns*: The previous value of pm[.](#shared.mod-3.sentence-1)
[🔗](#lib:swap,shared_lock_)
`template<class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
`
[4](#shared.mod-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9262)
*Effects*: As if by x.swap(y)[.](#shared.mod-4.sentence-1)
#### [32.6.5.5.5](#shared.obs) Observers [[thread.lock.shared.obs]](thread.lock.shared.obs)
[🔗](#lib:owns_lock,shared_lock)
`bool owns_lock() const noexcept;
`
[1](#shared.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9275)
*Returns*: owns[.](#shared.obs-1.sentence-1)
[🔗](#lib:operator_bool,shared_lock)
`explicit operator bool() const noexcept;
`
[2](#shared.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9286)
*Returns*: owns[.](#shared.obs-2.sentence-1)
[🔗](#lib:mutex,shared_lock)
`mutex_type* mutex() const noexcept;
`
[3](#shared.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9297)
*Returns*: pm[.](#shared.obs-3.sentence-1)