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

526 lines
19 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.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 {template<class Mutex>class shared_lock {public:using mutex_type = Mutex; // [[thread.lock.shared.cons]](#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]](#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]](#mod "32.6.5.5.4Modifiers"), modifiersvoid swap(shared_lock& u) noexcept;
mutex_type* release() noexcept; // [[thread.lock.shared.obs]](#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](#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.4Lifetime")) of the shared_lock object[.](#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"))[.](#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<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"))[.](#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"))[.](#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<class Clock, class Duration>
shared_lock(mutex_type& m,
const chrono::time_point<Clock, Duration>& 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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable 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<class Rep, class Period>
shared_lock(mutex_type& m,
const chrono::duration<Rep, Period>& 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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable 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.2Exceptions"))[.](#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.2Exceptions"))[.](#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<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& 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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable 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.2Exceptions"))[.](#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<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& 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.6Cpp17SharedTimedLockable requirements[thread.req.lockable.shared.timed]") requirements ([[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed "32.2.5.6Cpp17SharedTimedLockable 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.2Exceptions"))[.](#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.2Exceptions"))[.](#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<class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& 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)