2547 lines
116 KiB
Markdown
2547 lines
116 KiB
Markdown
[thread.mutex]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.6 Mutual exclusion [thread.mutex]
|
||
|
||
### [32.6.1](#general) General [[thread.mutex.general]](thread.mutex.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7252)
|
||
|
||
Subclause [thread.mutex] provides mechanisms for mutual exclusion: mutexes, locks, and call
|
||
once[.](#general-1.sentence-1)
|
||
|
||
These mechanisms ease the production of race-free
|
||
programs ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#general-1.sentence-2)
|
||
|
||
### [32.6.2](#mutex.syn) Header <mutex> synopsis [[mutex.syn]](mutex.syn)
|
||
|
||
[ð](#header:%3cmutex%3e)
|
||
|
||
namespace std {// [[thread.mutex.class]](#class "32.6.4.2.2 Class mutex"), class mutexclass mutex; // [[thread.mutex.recursive]](#recursive "32.6.4.2.3 Class recursive_mutex"), class recursive_mutexclass recursive_mutex; // [[thread.timedmutex.class]](#thread.timedmutex.class "32.6.4.3.2 Class timed_mutex"), class timed_mutexclass timed_mutex; // [[thread.timedmutex.recursive]](#thread.timedmutex.recursive "32.6.4.3.3 Class recursive_timed_mutex"), class recursive_timed_mutexclass recursive_timed_mutex; struct defer_lock_t { explicit defer_lock_t() = default; }; struct try_to_lock_t { explicit try_to_lock_t() = default; }; struct adopt_lock_t { explicit adopt_lock_t() = default; }; inline constexpr defer_lock_t defer_lock { }; inline constexpr try_to_lock_t try_to_lock { }; inline constexpr adopt_lock_t adopt_lock { }; // [[thread.lock]](#thread.lock "32.6.5 Locks"), lockstemplate<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock; template<class Mutex>void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; // [[thread.lock.algorithm]](#thread.lock.algorithm "32.6.6 Generic locking algorithms"), generic locking algorithmstemplate<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...); struct once_flag; template<class Callable, class... Args>void call_once(once_flag& flag, Callable&& func, Args&&... args);}
|
||
|
||
### [32.6.3](#shared.mutex.syn) Header <shared_mutex> synopsis [[shared.mutex.syn]](shared.mutex.syn)
|
||
|
||
[ð](#header:%3cshared_mutex%3e)
|
||
|
||
namespace std {// [[thread.sharedmutex.class]](#thread.sharedmutex.class "32.6.4.4.2 Class shared_mutex"), class shared_mutexclass shared_mutex; // [[thread.sharedtimedmutex.class]](#thread.sharedtimedmutex.class "32.6.4.5.2 Class shared_timed_mutex"), class shared_timed_mutexclass shared_timed_mutex; // [[thread.lock.shared]](#thread.lock.shared "32.6.5.5 Class template shared_lock"), class template shared_locktemplate<class Mutex> class shared_lock; template<class Mutex>void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;}
|
||
|
||
### [32.6.4](#requirements) Mutex requirements [[thread.mutex.requirements]](thread.mutex.requirements)
|
||
|
||
#### [32.6.4.1](#requirements.general) General [[thread.mutex.requirements.general]](thread.mutex.requirements.general)
|
||
|
||
[1](#requirements.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7318)
|
||
|
||
A mutex object facilitates protection against data races and allows safe synchronization of
|
||
data between [execution agents](thread.req.lockable#def:execution_agent "32.2.5 Requirements for Cpp17Lockable types [thread.req.lockable]")[.](#requirements.general-1.sentence-1)
|
||
|
||
An execution agent [*owns*](#def:owns) a mutex from the time it successfully calls one of the
|
||
lock functions until it calls unlock[.](#requirements.general-1.sentence-2)
|
||
|
||
Mutexes can be either recursive or non-recursive, and can
|
||
grant simultaneous ownership to one or many execution agents[.](#requirements.general-1.sentence-3)
|
||
|
||
Both
|
||
recursive and non-recursive mutexes are supplied[.](#requirements.general-1.sentence-4)
|
||
|
||
#### [32.6.4.2](#requirements.mutex) Mutex types [[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex)
|
||
|
||
#### [32.6.4.2.1](#requirements.mutex.general) General [[thread.mutex.requirements.mutex.general]](thread.mutex.requirements.mutex.general)
|
||
|
||
[1](#requirements.mutex.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7330)
|
||
|
||
The [*mutex types*](#def:mutex_types "32.6.4.2.1 General [thread.mutex.requirements.mutex.general]") are the standard library types mutex,recursive_mutex, timed_mutex, recursive_timed_mutex,shared_mutex, and shared_timed_mutex[.](#requirements.mutex.general-1.sentence-1)
|
||
|
||
They meet the requirements set out in [[thread.mutex.requirements.mutex]](#requirements.mutex "32.6.4.2 Mutex types")[.](#requirements.mutex.general-1.sentence-2)
|
||
|
||
In this description, m denotes an object of a mutex type[.](#requirements.mutex.general-1.sentence-3)
|
||
|
||
[*Note [1](#requirements.mutex.general-note-1)*:
|
||
|
||
The mutex types meet 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"))[.](#requirements.mutex.general-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#requirements.mutex.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7340)
|
||
|
||
The mutex types meet [*Cpp17DefaultConstructible*](utility.arg.requirements#:Cpp17DefaultConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") and [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]")[.](#requirements.mutex.general-2.sentence-1)
|
||
|
||
If initialization of an object of a mutex type fails,
|
||
an exception of type system_error is thrown[.](#requirements.mutex.general-2.sentence-2)
|
||
|
||
The mutex types are neither copyable nor movable[.](#requirements.mutex.general-2.sentence-3)
|
||
|
||
[3](#requirements.mutex.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7346)
|
||
|
||
The error conditions for error codes, if any, reported by member functions of the mutex types
|
||
are as follows:
|
||
|
||
- [(3.1)](#requirements.mutex.general-3.1)
|
||
|
||
resource_unavailable_try_again â if any native handle type manipulated is not available[.](#requirements.mutex.general-3.1.sentence-1)
|
||
|
||
- [(3.2)](#requirements.mutex.general-3.2)
|
||
|
||
operation_not_permitted â if the thread does not have the
|
||
privilege to perform the operation[.](#requirements.mutex.general-3.2.sentence-1)
|
||
|
||
- [(3.3)](#requirements.mutex.general-3.3)
|
||
|
||
invalid_argument â if any native handle type manipulated as part of mutex
|
||
construction is incorrect[.](#requirements.mutex.general-3.3.sentence-1)
|
||
|
||
[4](#requirements.mutex.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7357)
|
||
|
||
The implementation provides lock and unlock operations, as described below[.](#requirements.mutex.general-4.sentence-1)
|
||
|
||
For purposes of determining the existence of a data race, these behave as
|
||
atomic operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#requirements.mutex.general-4.sentence-2)
|
||
|
||
The lock and unlock operations on
|
||
a single mutex appears to occur in a single total order[.](#requirements.mutex.general-4.sentence-3)
|
||
|
||
[*Note [2](#requirements.mutex.general-note-2)*:
|
||
|
||
This
|
||
can be viewed as the [modification order](intro.multithread#def:modification_order "6.10.2 Multi-threaded executions and data races [intro.multithread]") of the
|
||
mutex[.](#requirements.mutex.general-4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [3](#requirements.mutex.general-note-3)*:
|
||
|
||
Construction and
|
||
destruction of an object of a mutex type need not be thread-safe; other
|
||
synchronization can be used to ensure that mutex objects are initialized
|
||
and visible to other threads[.](#requirements.mutex.general-4.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[5](#requirements.mutex.general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7374)
|
||
|
||
The expression m.lock() is well-formed and has the following semantics:
|
||
|
||
[6](#requirements.mutex.general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7377)
|
||
|
||
*Preconditions*: If m is of type mutex, timed_mutex,shared_mutex, or shared_timed_mutex, the calling
|
||
thread does not own the mutex[.](#requirements.mutex.general-6.sentence-1)
|
||
|
||
[7](#requirements.mutex.general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7383)
|
||
|
||
*Effects*: Blocks the calling thread until ownership of the mutex can be obtained for the calling thread[.](#requirements.mutex.general-7.sentence-1)
|
||
|
||
[8](#requirements.mutex.general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7388)
|
||
|
||
*Synchronization*: Prior unlock() operations on the same object[*synchronize with*](#def:synchronize_with) ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#requirements.mutex.general-8.sentence-1)
|
||
|
||
[9](#requirements.mutex.general-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7393)
|
||
|
||
*Postconditions*: The calling thread owns the mutex[.](#requirements.mutex.general-9.sentence-1)
|
||
|
||
[10](#requirements.mutex.general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7397)
|
||
|
||
*Return type*: void[.](#requirements.mutex.general-10.sentence-1)
|
||
|
||
[11](#requirements.mutex.general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7400)
|
||
|
||
*Throws*: system_error when
|
||
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#requirements.mutex.general-11.sentence-1)
|
||
|
||
[12](#requirements.mutex.general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7405)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(12.1)](#requirements.mutex.general-12.1)
|
||
|
||
operation_not_permitted â if the thread does not have the
|
||
privilege to perform the operation[.](#requirements.mutex.general-12.1.sentence-1)
|
||
|
||
- [(12.2)](#requirements.mutex.general-12.2)
|
||
|
||
resource_deadlock_would_occur â if the implementation detects
|
||
that a deadlock would occur[.](#requirements.mutex.general-12.2.sentence-1)
|
||
|
||
[13](#requirements.mutex.general-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7416)
|
||
|
||
The expression m.try_lock() is well-formed and has the following semantics:
|
||
|
||
[14](#requirements.mutex.general-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7419)
|
||
|
||
*Preconditions*: If m is of type mutex, timed_mutex,shared_mutex, or shared_timed_mutex, the calling
|
||
thread does not own the mutex[.](#requirements.mutex.general-14.sentence-1)
|
||
|
||
[15](#requirements.mutex.general-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7425)
|
||
|
||
*Effects*: Attempts to obtain ownership of the mutex for the calling thread without
|
||
blocking[.](#requirements.mutex.general-15.sentence-1)
|
||
|
||
If ownership is not obtained, there is no effect and try_lock() immediately returns[.](#requirements.mutex.general-15.sentence-2)
|
||
|
||
An implementation may fail to obtain the lock even if it is not
|
||
held by any other thread[.](#requirements.mutex.general-15.sentence-3)
|
||
|
||
[*Note [4](#requirements.mutex.general-note-4)*:
|
||
|
||
This spurious failure is normally uncommon, but
|
||
allows interesting implementations based on a simple
|
||
compare and exchange ([[atomics]](atomics "32.5 Atomic operations"))[.](#requirements.mutex.general-15.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
An implementation should ensure that try_lock() does not consistently return false in the absence of contending mutex acquisitions[.](#requirements.mutex.general-15.sentence-5)
|
||
|
||
[16](#requirements.mutex.general-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7439)
|
||
|
||
*Synchronization*: If try_lock() returns true, prior unlock() operations
|
||
on the same object [synchronize with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") this operation[.](#requirements.mutex.general-16.sentence-1)
|
||
|
||
[*Note [5](#requirements.mutex.general-note-5)*:
|
||
|
||
Since lock() does not synchronize with a failed subsequenttry_lock(), the visibility rules are weak enough that little would be
|
||
known about the state after a failure, even in the absence of spurious failures[.](#requirements.mutex.general-16.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[17](#requirements.mutex.general-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7449)
|
||
|
||
*Return type*: bool[.](#requirements.mutex.general-17.sentence-1)
|
||
|
||
[18](#requirements.mutex.general-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7452)
|
||
|
||
*Returns*: true if ownership was obtained, otherwise false[.](#requirements.mutex.general-18.sentence-1)
|
||
|
||
[19](#requirements.mutex.general-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7456)
|
||
|
||
*Throws*: Nothing[.](#requirements.mutex.general-19.sentence-1)
|
||
|
||
[20](#requirements.mutex.general-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7461)
|
||
|
||
The expression m.unlock() is well-formed and has the following semantics:
|
||
|
||
[21](#requirements.mutex.general-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7464)
|
||
|
||
*Preconditions*: The calling thread owns the mutex[.](#requirements.mutex.general-21.sentence-1)
|
||
|
||
[22](#requirements.mutex.general-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7468)
|
||
|
||
*Effects*: Releases the calling thread's ownership of the mutex[.](#requirements.mutex.general-22.sentence-1)
|
||
|
||
[23](#requirements.mutex.general-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7472)
|
||
|
||
*Return type*: void[.](#requirements.mutex.general-23.sentence-1)
|
||
|
||
[24](#requirements.mutex.general-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7475)
|
||
|
||
*Synchronization*: This operation [synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") subsequent
|
||
lock operations that obtain ownership on the same object[.](#requirements.mutex.general-24.sentence-1)
|
||
|
||
[25](#requirements.mutex.general-25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7480)
|
||
|
||
*Throws*: Nothing[.](#requirements.mutex.general-25.sentence-1)
|
||
|
||
#### [32.6.4.2.2](#class) Class mutex [[thread.mutex.class]](thread.mutex.class)
|
||
|
||
[ð](#lib:mutex)
|
||
|
||
namespace std {class mutex {public:constexpr mutex() noexcept; ~mutex();
|
||
|
||
mutex(const mutex&) = delete;
|
||
mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); 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](#class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7508)
|
||
|
||
The class mutex provides a non-recursive mutex with exclusive ownership
|
||
semantics[.](#class-1.sentence-1)
|
||
|
||
If one thread owns a mutex object, attempts by another thread to acquire
|
||
ownership of that object will fail (for try_lock()) or block (forlock()) until the owning thread has released ownership with a call tounlock()[.](#class-1.sentence-2)
|
||
|
||
[2](#class-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7516)
|
||
|
||
[*Note [1](#class-note-1)*:
|
||
|
||
After a thread A has called unlock(), releasing a mutex, it is possible for another
|
||
thread B to lock the same mutex, observe that it is no longer in use, unlock it, and
|
||
destroy it, before thread A appears to have returned from its unlock call[.](#class-2.sentence-1)
|
||
|
||
Conforming implementations
|
||
handle such scenarios correctly, as long as thread A does not access the
|
||
mutex after the unlock call returns[.](#class-2.sentence-2)
|
||
|
||
These cases typically occur when a reference-counted object
|
||
contains a mutex that is used to protect the reference count[.](#class-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[3](#class-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7526)
|
||
|
||
The class mutex meets
|
||
all of the mutex requirements ([[thread.mutex.requirements]](#requirements "32.6.4 Mutex requirements"))[.](#class-3.sentence-1)
|
||
|
||
It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#class-3.sentence-2)
|
||
|
||
[4](#class-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7531)
|
||
|
||
[*Note [2](#class-note-2)*:
|
||
|
||
A program can deadlock if the thread that owns a mutex object callslock() on that object[.](#class-4.sentence-1)
|
||
|
||
If the implementation can detect the deadlock,
|
||
a resource_deadlock_would_occur error condition might be observed[.](#class-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[5](#class-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7538)
|
||
|
||
The behavior of a program is undefined if
|
||
it destroys a mutex object owned by any thread or
|
||
a thread terminates while owning a mutex object[.](#class-5.sentence-1)
|
||
|
||
#### [32.6.4.2.3](#recursive) Class recursive_mutex [[thread.mutex.recursive]](thread.mutex.recursive)
|
||
|
||
[ð](#lib:recursive_mutex)
|
||
|
||
namespace std {class recursive_mutex {public: recursive_mutex(); ~recursive_mutex();
|
||
|
||
recursive_mutex(const recursive_mutex&) = delete;
|
||
recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() noexcept; void unlock(); 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](#recursive-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7566)
|
||
|
||
The class recursive_mutex provides a recursive mutex with exclusive ownership
|
||
semantics[.](#recursive-1.sentence-1)
|
||
|
||
If one thread owns a recursive_mutex object, attempts by another
|
||
thread to acquire ownership of that object will fail (for try_lock()) or block
|
||
(for lock()) until the first thread has completely released ownership[.](#recursive-1.sentence-2)
|
||
|
||
[2](#recursive-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7573)
|
||
|
||
The class recursive_mutex meets
|
||
all of the mutex requirements ([[thread.mutex.requirements]](#requirements "32.6.4 Mutex requirements"))[.](#recursive-2.sentence-1)
|
||
|
||
It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#recursive-2.sentence-2)
|
||
|
||
[3](#recursive-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7578)
|
||
|
||
A thread that owns a recursive_mutex object may acquire additional levels of
|
||
ownership by calling lock() or try_lock() on that object[.](#recursive-3.sentence-1)
|
||
|
||
It is
|
||
unspecified how many levels of ownership may be acquired by a single thread[.](#recursive-3.sentence-2)
|
||
|
||
If a thread
|
||
has already acquired the maximum level of ownership for a recursive_mutex object, additional calls to try_lock() fail, and additional calls tolock() throw an exception of type system_error[.](#recursive-3.sentence-3)
|
||
|
||
A thread
|
||
shall call unlock() once for each level of ownership acquired by calls tolock() and try_lock()[.](#recursive-3.sentence-4)
|
||
|
||
Only when all levels of ownership have been
|
||
released may ownership be acquired by another thread[.](#recursive-3.sentence-5)
|
||
|
||
[4](#recursive-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7589)
|
||
|
||
The behavior of a program is undefined if
|
||
|
||
- [(4.1)](#recursive-4.1)
|
||
|
||
it destroys a recursive_mutex object owned by any thread or
|
||
|
||
- [(4.2)](#recursive-4.2)
|
||
|
||
a thread terminates while owning a recursive_mutex object[.](#recursive-4.sentence-1)
|
||
|
||
#### [32.6.4.3](#thread.timedmutex.requirements) Timed mutex types [[thread.timedmutex.requirements]](thread.timedmutex.requirements)
|
||
|
||
#### [32.6.4.3.1](#thread.timedmutex.requirements.general) General [[thread.timedmutex.requirements.general]](thread.timedmutex.requirements.general)
|
||
|
||
[1](#thread.timedmutex.requirements.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7600)
|
||
|
||
The [*timed mutex types*](#def:timed_mutex_types "32.6.4.3.1 General [thread.timedmutex.requirements.general]") are the standard library types timed_mutex,recursive_timed_mutex, and shared_timed_mutex[.](#thread.timedmutex.requirements.general-1.sentence-1)
|
||
|
||
They
|
||
meet the requirements set out below[.](#thread.timedmutex.requirements.general-1.sentence-2)
|
||
|
||
In this description, m denotes an object of a mutex type,rel_time denotes an object of an
|
||
instantiation of [duration](time.duration "30.5 Class template duration [time.duration]"), and abs_time denotes an
|
||
object of an
|
||
instantiation of [time_point](time.point "30.6 Class template time_point [time.point]")[.](#thread.timedmutex.requirements.general-1.sentence-3)
|
||
|
||
[*Note [1](#thread.timedmutex.requirements.general-note-1)*:
|
||
|
||
The timed mutex types meet 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"))[.](#thread.timedmutex.requirements.general-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#thread.timedmutex.requirements.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7614)
|
||
|
||
The expression m.try_lock_for(rel_time) is well-formed
|
||
and has the following semantics:
|
||
|
||
[3](#thread.timedmutex.requirements.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7618)
|
||
|
||
*Preconditions*: If m is of type timed_mutex orshared_timed_mutex, the calling thread does not
|
||
own the mutex[.](#thread.timedmutex.requirements.general-3.sentence-1)
|
||
|
||
[4](#thread.timedmutex.requirements.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7624)
|
||
|
||
*Effects*: The function attempts to obtain ownership of the mutex within the
|
||
relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))
|
||
specified by rel_time[.](#thread.timedmutex.requirements.general-4.sentence-1)
|
||
|
||
If the time specified by rel_time is less than or
|
||
equal to rel_time.zero(), the function attempts to obtain ownership without blocking (as if by callingtry_lock())[.](#thread.timedmutex.requirements.general-4.sentence-2)
|
||
|
||
The function returns within the timeout specified byrel_time only if it has obtained ownership of the mutex object[.](#thread.timedmutex.requirements.general-4.sentence-3)
|
||
|
||
[*Note [2](#thread.timedmutex.requirements.general-note-2)*:
|
||
|
||
As
|
||
with try_lock(), there is no guarantee that ownership will be obtained if the
|
||
lock is available, but implementations are expected to make a strong effort to do so[.](#thread.timedmutex.requirements.general-4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[5](#thread.timedmutex.requirements.general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7638)
|
||
|
||
*Synchronization*: If try_lock_for() returns true, prior unlock() operations
|
||
on the same object [*synchronize with*](#def:synchronize_with) ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#thread.timedmutex.requirements.general-5.sentence-1)
|
||
|
||
[6](#thread.timedmutex.requirements.general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7643)
|
||
|
||
*Return type*: bool[.](#thread.timedmutex.requirements.general-6.sentence-1)
|
||
|
||
[7](#thread.timedmutex.requirements.general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7646)
|
||
|
||
*Returns*: true if ownership was obtained, otherwise false[.](#thread.timedmutex.requirements.general-7.sentence-1)
|
||
|
||
[8](#thread.timedmutex.requirements.general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7650)
|
||
|
||
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.timedmutex.requirements.general-8.sentence-1)
|
||
|
||
[9](#thread.timedmutex.requirements.general-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7655)
|
||
|
||
The expression m.try_lock_until(abs_time) is well-formed
|
||
and has the following semantics:
|
||
|
||
[10](#thread.timedmutex.requirements.general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7659)
|
||
|
||
*Preconditions*: If m is of type timed_mutex orshared_timed_mutex, the calling thread does not own the
|
||
mutex[.](#thread.timedmutex.requirements.general-10.sentence-1)
|
||
|
||
[11](#thread.timedmutex.requirements.general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7665)
|
||
|
||
*Effects*: The function attempts to obtain ownership of the mutex[.](#thread.timedmutex.requirements.general-11.sentence-1)
|
||
|
||
Ifabs_time has already passed, the function attempts to obtain ownership
|
||
without blocking (as if by calling try_lock())[.](#thread.timedmutex.requirements.general-11.sentence-2)
|
||
|
||
The function
|
||
returns before the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified byabs_time only if it has obtained ownership of the mutex object[.](#thread.timedmutex.requirements.general-11.sentence-3)
|
||
|
||
[*Note [3](#thread.timedmutex.requirements.general-note-3)*:
|
||
|
||
As with try_lock(), there is no guarantee that ownership will
|
||
be obtained if the lock is available, but implementations are expected to make a
|
||
strong effort to do so[.](#thread.timedmutex.requirements.general-11.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[12](#thread.timedmutex.requirements.general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7678)
|
||
|
||
*Synchronization*: If try_lock_until() returns true, prior unlock() operations on the same object [*synchronize with*](#def:synchronize_with) ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))
|
||
this operation[.](#thread.timedmutex.requirements.general-12.sentence-1)
|
||
|
||
[13](#thread.timedmutex.requirements.general-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7684)
|
||
|
||
*Return type*: bool[.](#thread.timedmutex.requirements.general-13.sentence-1)
|
||
|
||
[14](#thread.timedmutex.requirements.general-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7687)
|
||
|
||
*Returns*: true if ownership was obtained, otherwise false[.](#thread.timedmutex.requirements.general-14.sentence-1)
|
||
|
||
[15](#thread.timedmutex.requirements.general-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7691)
|
||
|
||
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.timedmutex.requirements.general-15.sentence-1)
|
||
|
||
#### [32.6.4.3.2](#thread.timedmutex.class) Class timed_mutex [[thread.timedmutex.class]](thread.timedmutex.class)
|
||
|
||
[ð](#lib:timed_mutex)
|
||
|
||
namespace std {class timed_mutex {public: timed_mutex(); ~timed_mutex();
|
||
|
||
timed_mutex(const timed_mutex&) = delete;
|
||
timed_mutex& operator=(const timed_mutex&) = delete; void 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(); 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.timedmutex.class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7723)
|
||
|
||
The class timed_mutex provides a non-recursive mutex with exclusive ownership
|
||
semantics[.](#thread.timedmutex.class-1.sentence-1)
|
||
|
||
If one thread owns a timed_mutex object, attempts by another thread
|
||
to acquire ownership of that object will fail (for try_lock()) or block
|
||
(for lock(), try_lock_for(), and try_lock_until()) until
|
||
the owning thread has released ownership with a call to unlock() or the
|
||
call to try_lock_for() or try_lock_until() times out (having
|
||
failed to obtain ownership)[.](#thread.timedmutex.class-1.sentence-2)
|
||
|
||
[2](#thread.timedmutex.class-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7733)
|
||
|
||
The class timed_mutex meets
|
||
all of the timed mutex requirements ([[thread.timedmutex.requirements]](#thread.timedmutex.requirements "32.6.4.3 Timed mutex types"))[.](#thread.timedmutex.class-2.sentence-1)
|
||
|
||
It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#thread.timedmutex.class-2.sentence-2)
|
||
|
||
[3](#thread.timedmutex.class-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7738)
|
||
|
||
The behavior of a program is undefined if
|
||
|
||
- [(3.1)](#thread.timedmutex.class-3.1)
|
||
|
||
it destroys a timed_mutex object owned by any thread,
|
||
|
||
- [(3.2)](#thread.timedmutex.class-3.2)
|
||
|
||
a thread that owns a timed_mutex object calls lock(),try_lock(), try_lock_for(), or try_lock_until() on that object, or
|
||
|
||
- [(3.3)](#thread.timedmutex.class-3.3)
|
||
|
||
a thread terminates while owning a timed_mutex object[.](#thread.timedmutex.class-3.sentence-1)
|
||
|
||
#### [32.6.4.3.3](#thread.timedmutex.recursive) Class recursive_timed_mutex [[thread.timedmutex.recursive]](thread.timedmutex.recursive)
|
||
|
||
[ð](#lib:recursive_timed_mutex)
|
||
|
||
namespace std {class recursive_timed_mutex {public: recursive_timed_mutex(); ~recursive_timed_mutex();
|
||
|
||
recursive_timed_mutex(const recursive_timed_mutex&) = delete;
|
||
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); // blockingbool try_lock() noexcept; 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(); 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.timedmutex.recursive-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7774)
|
||
|
||
The class recursive_timed_mutex provides a recursive mutex with exclusive
|
||
ownership semantics[.](#thread.timedmutex.recursive-1.sentence-1)
|
||
|
||
If one thread owns a recursive_timed_mutex object,
|
||
attempts by another thread to acquire ownership of that object will fail (fortry_lock()) or block (for lock(), try_lock_for(), andtry_lock_until()) until the owning thread has completely released
|
||
ownership or the call to try_lock_for() or try_lock_until() times out (having failed to obtain ownership)[.](#thread.timedmutex.recursive-1.sentence-2)
|
||
|
||
[2](#thread.timedmutex.recursive-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7784)
|
||
|
||
The class recursive_timed_mutex meets
|
||
all of the timed mutex requirements ([[thread.timedmutex.requirements]](#thread.timedmutex.requirements "32.6.4.3 Timed mutex types"))[.](#thread.timedmutex.recursive-2.sentence-1)
|
||
|
||
It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#thread.timedmutex.recursive-2.sentence-2)
|
||
|
||
[3](#thread.timedmutex.recursive-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7789)
|
||
|
||
A thread that owns a recursive_timed_mutex object may acquire additional
|
||
levels of ownership by calling lock(), try_lock(),try_lock_for(), or try_lock_until() on that object[.](#thread.timedmutex.recursive-3.sentence-1)
|
||
|
||
It is
|
||
unspecified how many levels of ownership may be acquired by a single thread[.](#thread.timedmutex.recursive-3.sentence-2)
|
||
|
||
If
|
||
a thread has already acquired the maximum level of ownership for arecursive_timed_mutex object, additional calls to try_lock(),try_lock_for(), or try_lock_until() fail, and additional
|
||
calls to lock() throw an exception of type system_error[.](#thread.timedmutex.recursive-3.sentence-3)
|
||
|
||
A
|
||
thread shall call unlock() once for each level of ownership acquired by
|
||
calls to lock(), try_lock(), try_lock_for(), andtry_lock_until()[.](#thread.timedmutex.recursive-3.sentence-4)
|
||
|
||
Only when all levels of ownership have been released
|
||
may ownership of the object be acquired by another thread[.](#thread.timedmutex.recursive-3.sentence-5)
|
||
|
||
[4](#thread.timedmutex.recursive-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7803)
|
||
|
||
The behavior of a program is undefined if
|
||
|
||
- [(4.1)](#thread.timedmutex.recursive-4.1)
|
||
|
||
it destroys a recursive_timed_mutex object owned by any thread, or
|
||
|
||
- [(4.2)](#thread.timedmutex.recursive-4.2)
|
||
|
||
a thread terminates while owning a recursive_timed_mutex object[.](#thread.timedmutex.recursive-4.sentence-1)
|
||
|
||
#### [32.6.4.4](#thread.sharedmutex.requirements) Shared mutex types [[thread.sharedmutex.requirements]](thread.sharedmutex.requirements)
|
||
|
||
#### [32.6.4.4.1](#thread.sharedmutex.requirements.general) General [[thread.sharedmutex.requirements.general]](thread.sharedmutex.requirements.general)
|
||
|
||
[1](#thread.sharedmutex.requirements.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]")[.](#thread.sharedmutex.requirements.general-1.sentence-1)
|
||
|
||
Shared mutex types meet the requirements of
|
||
mutex types ([[thread.mutex.requirements.mutex]](#requirements.mutex "32.6.4.2 Mutex types")) and additionally
|
||
meet the requirements set out below[.](#thread.sharedmutex.requirements.general-1.sentence-2)
|
||
|
||
In this description,m denotes an object of a shared mutex type[.](#thread.sharedmutex.requirements.general-1.sentence-3)
|
||
|
||
[*Note [1](#thread.sharedmutex.requirements.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"))[.](#thread.sharedmutex.requirements.general-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#thread.sharedmutex.requirements.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]](#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[.](#thread.sharedmutex.requirements.general-2.sentence-1)
|
||
|
||
Multiple execution agents can
|
||
simultaneously hold a shared lock ownership of a shared mutex type[.](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-2.sentence-5)
|
||
|
||
[3](#thread.sharedmutex.requirements.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](#thread.sharedmutex.requirements.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7845)
|
||
|
||
*Preconditions*: The calling thread has no ownership of the mutex[.](#thread.sharedmutex.requirements.general-4.sentence-1)
|
||
|
||
[5](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-5.sentence-1)
|
||
|
||
If an exception is thrown then a shared lock has not been acquired for the current thread[.](#thread.sharedmutex.requirements.general-5.sentence-2)
|
||
|
||
[6](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-6.sentence-1)
|
||
|
||
[7](#thread.sharedmutex.requirements.general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7859)
|
||
|
||
*Postconditions*: The calling thread has a shared lock on the mutex[.](#thread.sharedmutex.requirements.general-7.sentence-1)
|
||
|
||
[8](#thread.sharedmutex.requirements.general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7863)
|
||
|
||
*Return type*: void[.](#thread.sharedmutex.requirements.general-8.sentence-1)
|
||
|
||
[9](#thread.sharedmutex.requirements.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"))[.](#thread.sharedmutex.requirements.general-9.sentence-1)
|
||
|
||
[10](#thread.sharedmutex.requirements.general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7870)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(10.1)](#thread.sharedmutex.requirements.general-10.1)
|
||
|
||
operation_not_permitted â if the thread does not have the privilege to perform the operation[.](#thread.sharedmutex.requirements.general-10.1.sentence-1)
|
||
|
||
- [(10.2)](#thread.sharedmutex.requirements.general-10.2)
|
||
|
||
resource_deadlock_would_occur â if the implementation detects that a deadlock would occur[.](#thread.sharedmutex.requirements.general-10.2.sentence-1)
|
||
|
||
[11](#thread.sharedmutex.requirements.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](#thread.sharedmutex.requirements.general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7881)
|
||
|
||
*Preconditions*: The calling thread holds a shared lock on the mutex[.](#thread.sharedmutex.requirements.general-12.sentence-1)
|
||
|
||
[13](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-13.sentence-1)
|
||
|
||
[14](#thread.sharedmutex.requirements.general-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7889)
|
||
|
||
*Return type*: void[.](#thread.sharedmutex.requirements.general-14.sentence-1)
|
||
|
||
[15](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-15.sentence-1)
|
||
|
||
[16](#thread.sharedmutex.requirements.general-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7897)
|
||
|
||
*Throws*: Nothing[.](#thread.sharedmutex.requirements.general-16.sentence-1)
|
||
|
||
[17](#thread.sharedmutex.requirements.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](#thread.sharedmutex.requirements.general-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7905)
|
||
|
||
*Preconditions*: The calling thread has no ownership of the mutex[.](#thread.sharedmutex.requirements.general-18.sentence-1)
|
||
|
||
[19](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-19.sentence-1)
|
||
|
||
If shared ownership is not obtained, there is no
|
||
effect and try_lock_shared() immediately returns[.](#thread.sharedmutex.requirements.general-19.sentence-2)
|
||
|
||
An implementation
|
||
may fail to obtain the lock even if it is not held by any other thread[.](#thread.sharedmutex.requirements.general-19.sentence-3)
|
||
|
||
[20](#thread.sharedmutex.requirements.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[.](#thread.sharedmutex.requirements.general-20.sentence-1)
|
||
|
||
[21](#thread.sharedmutex.requirements.general-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7922)
|
||
|
||
*Return type*: bool[.](#thread.sharedmutex.requirements.general-21.sentence-1)
|
||
|
||
[22](#thread.sharedmutex.requirements.general-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7925)
|
||
|
||
*Returns*: true if the shared lock was acquired, otherwise false[.](#thread.sharedmutex.requirements.general-22.sentence-1)
|
||
|
||
[23](#thread.sharedmutex.requirements.general-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7929)
|
||
|
||
*Throws*: Nothing[.](#thread.sharedmutex.requirements.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.requirements "32.6.4.4 Shared mutex types"))[.](#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)
|
||
|
||
#### [32.6.4.5](#thread.sharedtimedmutex.requirements) Shared timed mutex types [[thread.sharedtimedmutex.requirements]](thread.sharedtimedmutex.requirements)
|
||
|
||
#### [32.6.4.5.1](#thread.sharedtimedmutex.requirements.general) General [[thread.sharedtimedmutex.requirements.general]](thread.sharedtimedmutex.requirements.general)
|
||
|
||
[1](#thread.sharedtimedmutex.requirements.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7987)
|
||
|
||
The standard library type shared_timed_mutex is a[*shared timed mutex type*](#def:shared_timed_mutex_type "32.6.4.5.1 General [thread.sharedtimedmutex.requirements.general]")[.](#thread.sharedtimedmutex.requirements.general-1.sentence-1)
|
||
|
||
Shared timed mutex types meet the requirements of
|
||
timed mutex types ([[thread.timedmutex.requirements]](#thread.timedmutex.requirements "32.6.4.3 Timed mutex types")),
|
||
shared mutex types ([[thread.sharedmutex.requirements]](#thread.sharedmutex.requirements "32.6.4.4 Shared mutex types")), and additionally
|
||
meet the requirements set out below[.](#thread.sharedtimedmutex.requirements.general-1.sentence-2)
|
||
|
||
In this description,m denotes an object of a shared timed mutex type,rel_time denotes an object of an instantiation ofduration ([[time.duration]](time.duration "30.5 Class template duration")), andabs_time denotes an object of an instantiation of[time_point](time.point "30.6 Class template time_point [time.point]")[.](#thread.sharedtimedmutex.requirements.general-1.sentence-3)
|
||
|
||
[*Note [1](#thread.sharedtimedmutex.requirements.general-note-1)*:
|
||
|
||
The shared timed mutex types meet 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"))[.](#thread.sharedtimedmutex.requirements.general-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#thread.sharedtimedmutex.requirements.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8003)
|
||
|
||
The expression m.try_lock_shared_for(rel_time) is well-formed and
|
||
has the following semantics:
|
||
|
||
[3](#thread.sharedtimedmutex.requirements.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8007)
|
||
|
||
*Preconditions*: The calling thread has no ownership of the mutex[.](#thread.sharedtimedmutex.requirements.general-3.sentence-1)
|
||
|
||
[4](#thread.sharedtimedmutex.requirements.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8011)
|
||
|
||
*Effects*: Attempts to obtain
|
||
shared lock ownership for the calling thread within the relative
|
||
timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by rel_time[.](#thread.sharedtimedmutex.requirements.general-4.sentence-1)
|
||
|
||
If the time
|
||
specified by rel_time is less than or equal to rel_time.zero(),
|
||
the function attempts to obtain ownership without blocking (as if by callingtry_lock_shared())[.](#thread.sharedtimedmutex.requirements.general-4.sentence-2)
|
||
|
||
The function returns within the timeout
|
||
specified by rel_time only if it has obtained shared ownership of the
|
||
mutex object[.](#thread.sharedtimedmutex.requirements.general-4.sentence-3)
|
||
|
||
[*Note [2](#thread.sharedtimedmutex.requirements.general-note-2)*:
|
||
|
||
As with try_lock(), there is no guarantee that
|
||
ownership will be obtained if the lock is available, but implementations are
|
||
expected to make a strong effort to do so[.](#thread.sharedtimedmutex.requirements.general-4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
If an exception is thrown then a shared lock has not been acquired for
|
||
the current thread[.](#thread.sharedtimedmutex.requirements.general-4.sentence-5)
|
||
|
||
[5](#thread.sharedtimedmutex.requirements.general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8029)
|
||
|
||
*Synchronization*: If try_lock_shared_for() returns true, priorunlock() operations on the same object synchronize
|
||
with ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#thread.sharedtimedmutex.requirements.general-5.sentence-1)
|
||
|
||
[6](#thread.sharedtimedmutex.requirements.general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8035)
|
||
|
||
*Return type*: bool[.](#thread.sharedtimedmutex.requirements.general-6.sentence-1)
|
||
|
||
[7](#thread.sharedtimedmutex.requirements.general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8038)
|
||
|
||
*Returns*: true if the shared lock was acquired, otherwise false[.](#thread.sharedtimedmutex.requirements.general-7.sentence-1)
|
||
|
||
[8](#thread.sharedtimedmutex.requirements.general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8042)
|
||
|
||
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.sharedtimedmutex.requirements.general-8.sentence-1)
|
||
|
||
[9](#thread.sharedtimedmutex.requirements.general-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8047)
|
||
|
||
The expression m.try_lock_shared_until(abs_time) is well-formed
|
||
and has the following semantics:
|
||
|
||
[10](#thread.sharedtimedmutex.requirements.general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8051)
|
||
|
||
*Preconditions*: The calling thread has no ownership of the mutex[.](#thread.sharedtimedmutex.requirements.general-10.sentence-1)
|
||
|
||
[11](#thread.sharedtimedmutex.requirements.general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8055)
|
||
|
||
*Effects*: The function attempts to obtain shared ownership of the mutex[.](#thread.sharedtimedmutex.requirements.general-11.sentence-1)
|
||
|
||
Ifabs_time has already passed, the function attempts to obtain shared
|
||
ownership without blocking (as if by calling try_lock_shared())[.](#thread.sharedtimedmutex.requirements.general-11.sentence-2)
|
||
|
||
The
|
||
function returns before the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))
|
||
specified by abs_time only if it has obtained shared ownership of the
|
||
mutex object[.](#thread.sharedtimedmutex.requirements.general-11.sentence-3)
|
||
|
||
[*Note [3](#thread.sharedtimedmutex.requirements.general-note-3)*:
|
||
|
||
As with try_lock(), there is no guarantee that
|
||
ownership will be obtained if the lock is available, but implementations are
|
||
expected to make a strong effort to do so[.](#thread.sharedtimedmutex.requirements.general-11.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
If an exception is thrown then a shared lock has not been acquired for
|
||
the current thread[.](#thread.sharedtimedmutex.requirements.general-11.sentence-5)
|
||
|
||
[12](#thread.sharedtimedmutex.requirements.general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8071)
|
||
|
||
*Synchronization*: If try_lock_shared_until() returns true, priorunlock() operations on the same object synchronize
|
||
with ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#thread.sharedtimedmutex.requirements.general-12.sentence-1)
|
||
|
||
[13](#thread.sharedtimedmutex.requirements.general-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8077)
|
||
|
||
*Return type*: bool[.](#thread.sharedtimedmutex.requirements.general-13.sentence-1)
|
||
|
||
[14](#thread.sharedtimedmutex.requirements.general-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8080)
|
||
|
||
*Returns*: true if the shared lock was acquired, otherwise false[.](#thread.sharedtimedmutex.requirements.general-14.sentence-1)
|
||
|
||
[15](#thread.sharedtimedmutex.requirements.general-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8084)
|
||
|
||
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.sharedtimedmutex.requirements.general-15.sentence-1)
|
||
|
||
#### [32.6.4.5.2](#thread.sharedtimedmutex.class) Class shared_timed_mutex [[thread.sharedtimedmutex.class]](thread.sharedtimedmutex.class)
|
||
|
||
[ð](#lib:shared_timed_mutex)
|
||
|
||
namespace std {class shared_timed_mutex {public: shared_timed_mutex(); ~shared_timed_mutex();
|
||
|
||
shared_timed_mutex(const shared_timed_mutex&) = delete;
|
||
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; // exclusive ownershipvoid 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(); // shared ownershipvoid lock_shared(); // blockingbool try_lock_shared(); template<class Rep, class Period>bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration>bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock_shared(); };}
|
||
|
||
[1](#thread.sharedtimedmutex.class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8123)
|
||
|
||
The class shared_timed_mutex provides a non-recursive mutex with shared
|
||
ownership semantics[.](#thread.sharedtimedmutex.class-1.sentence-1)
|
||
|
||
[2](#thread.sharedtimedmutex.class-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8127)
|
||
|
||
The class shared_timed_mutex meets
|
||
all of the shared timed mutex requirements ([[thread.sharedtimedmutex.requirements]](#thread.sharedtimedmutex.requirements "32.6.4.5 Shared timed mutex types"))[.](#thread.sharedtimedmutex.class-2.sentence-1)
|
||
|
||
It is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#thread.sharedtimedmutex.class-2.sentence-2)
|
||
|
||
[3](#thread.sharedtimedmutex.class-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8132)
|
||
|
||
The behavior of a program is undefined if
|
||
|
||
- [(3.1)](#thread.sharedtimedmutex.class-3.1)
|
||
|
||
it destroys a shared_timed_mutex object owned by any thread,
|
||
|
||
- [(3.2)](#thread.sharedtimedmutex.class-3.2)
|
||
|
||
a thread attempts to recursively gain any ownership of a shared_timed_mutex, or
|
||
|
||
- [(3.3)](#thread.sharedtimedmutex.class-3.3)
|
||
|
||
a thread terminates while possessing any ownership of a shared_timed_mutex[.](#thread.sharedtimedmutex.class-3.sentence-1)
|
||
|
||
### [32.6.5](#thread.lock) Locks [[thread.lock]](thread.lock)
|
||
|
||
#### [32.6.5.1](#thread.lock.general) General [[thread.lock.general]](thread.lock.general)
|
||
|
||
[1](#thread.lock.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)[.](#thread.lock.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[.](#thread.lock.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[.](#thread.lock.general-1.sentence-3)
|
||
|
||
A lock does not manage the lifetime
|
||
of the lockable object it references[.](#thread.lock.general-1.sentence-4)
|
||
|
||
[*Note [1](#thread.lock.general-note-1)*:
|
||
|
||
Locks are intended to ease the burden of
|
||
unlocking the lockable object under both normal and exceptional circumstances[.](#thread.lock.general-1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[2](#thread.lock.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[.](#thread.lock.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](#thread.lock.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](#thread.lock.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[.](#thread.lock.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.4 Lifetime [basic.life]")[.](#thread.lock.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[.](#thread.lock.guard-1.sentence-3)
|
||
|
||
The supplied Mutex type shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2 Cpp17BasicLockable requirements"))[.](#thread.lock.guard-1.sentence-4)
|
||
|
||
[ð](#lib:lock_guard,constructor)
|
||
|
||
`explicit lock_guard(mutex_type& m);
|
||
`
|
||
|
||
[2](#thread.lock.guard-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8218)
|
||
|
||
*Effects*: Initializes pm with m[.](#thread.lock.guard-2.sentence-1)
|
||
|
||
Calls m.lock()[.](#thread.lock.guard-2.sentence-2)
|
||
|
||
[ð](#lib:lock_guard,constructor_)
|
||
|
||
`lock_guard(mutex_type& m, adopt_lock_t);
|
||
`
|
||
|
||
[3](#thread.lock.guard-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8229)
|
||
|
||
*Preconditions*: The calling thread holds a non-shared lock on m[.](#thread.lock.guard-3.sentence-1)
|
||
|
||
[4](#thread.lock.guard-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8233)
|
||
|
||
*Effects*: Initializes pm with m[.](#thread.lock.guard-4.sentence-1)
|
||
|
||
[5](#thread.lock.guard-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8237)
|
||
|
||
*Throws*: Nothing[.](#thread.lock.guard-5.sentence-1)
|
||
|
||
[ð](#lib:lock_guard,destructor)
|
||
|
||
`~lock_guard();
|
||
`
|
||
|
||
[6](#thread.lock.guard-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8248)
|
||
|
||
*Effects*: Equivalent to: pm.unlock()
|
||
|
||
#### [32.6.5.3](#thread.lock.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](#thread.lock.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[.](#thread.lock.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.4 Lifetime [basic.life]")[.](#thread.lock.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[.](#thread.lock.scoped-1.sentence-3)
|
||
|
||
- [(1.1)](#thread.lock.scoped-1.1)
|
||
|
||
If sizeof...(MutexTypes) is one,
|
||
let Mutex denote the sole type constituting the pack MutexTypes[.](#thread.lock.scoped-1.1.sentence-1)
|
||
Mutex shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2 Cpp17BasicLockable requirements"))[.](#thread.lock.scoped-1.1.sentence-2)
|
||
The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") mutex_type denotes the same type as Mutex[.](#thread.lock.scoped-1.1.sentence-3)
|
||
|
||
- [(1.2)](#thread.lock.scoped-1.2)
|
||
|
||
Otherwise, all types in the template parameter pack MutexTypes shall meet 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"))
|
||
and there is no member mutex_type[.](#thread.lock.scoped-1.2.sentence-1)
|
||
|
||
[ð](#lib:scoped_lock,constructor)
|
||
|
||
`explicit scoped_lock(MutexTypes&... m);
|
||
`
|
||
|
||
[2](#thread.lock.scoped-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8303)
|
||
|
||
*Effects*: Initializes pm with tie(m...)[.](#thread.lock.scoped-2.sentence-1)
|
||
|
||
Then if sizeof...(MutexTypes) is 0, no effects[.](#thread.lock.scoped-2.sentence-2)
|
||
|
||
Otherwise if sizeof...(MutexTypes) is 1, then m.lock()[.](#thread.lock.scoped-2.sentence-3)
|
||
|
||
Otherwise, lock(m...)[.](#thread.lock.scoped-2.sentence-4)
|
||
|
||
[ð](#lib:scoped_lock,constructor_)
|
||
|
||
`explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
|
||
`
|
||
|
||
[3](#thread.lock.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[.](#thread.lock.scoped-3.sentence-1)
|
||
|
||
[4](#thread.lock.scoped-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8321)
|
||
|
||
*Effects*: Initializes pm with tie(m...)[.](#thread.lock.scoped-4.sentence-1)
|
||
|
||
[5](#thread.lock.scoped-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8325)
|
||
|
||
*Throws*: Nothing[.](#thread.lock.scoped-5.sentence-1)
|
||
|
||
[ð](#lib:scoped_lock,destructor)
|
||
|
||
`~scoped_lock();
|
||
`
|
||
|
||
[6](#thread.lock.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()[.](#thread.lock.scoped-6.sentence-1)
|
||
|
||
#### [32.6.5.4](#thread.lock.unique) Class template unique_lock [[thread.lock.unique]](thread.lock.unique)
|
||
|
||
#### [32.6.5.4.1](#thread.lock.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]](#thread.lock.unique.cons "32.6.5.4.2 Constructors, 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]](#thread.lock.unique.locking "32.6.5.4.3 Locking"), 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]](#thread.lock.unique.mod "32.6.5.4.4 Modifiers"), modifiersvoid swap(unique_lock& u) noexcept;
|
||
mutex_type* release() noexcept; // [[thread.lock.unique.obs]](#thread.lock.unique.obs "32.6.5.4.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](#thread.lock.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[.](#thread.lock.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[.](#thread.lock.unique.general-1.sentence-2)
|
||
|
||
Objects of type unique_lock are not
|
||
copyable but are movable[.](#thread.lock.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.4 Lifetime")) of the unique_lock object[.](#thread.lock.unique.general-1.sentence-4)
|
||
|
||
The suppliedMutex type shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2 Cpp17BasicLockable requirements"))[.](#thread.lock.unique.general-1.sentence-5)
|
||
|
||
[2](#thread.lock.unique.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8411)
|
||
|
||
[*Note [1](#thread.lock.unique.general-note-1)*:
|
||
|
||
unique_lock<Mutex> meets the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements[.](#thread.lock.unique.general-2.sentence-1)
|
||
|
||
If Mutex 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")),unique_lock<Mutex> also meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements;
|
||
if Mutex 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")),unique_lock<Mutex> also meets the [*Cpp17TimedLockable*](thread.req.lockable.timed#:Cpp17TimedLockable "32.2.5.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements[.](#thread.lock.unique.general-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
#### [32.6.5.4.2](#thread.lock.unique.cons) Constructors, destructor, and assignment [[thread.lock.unique.cons]](thread.lock.unique.cons)
|
||
|
||
[ð](#lib:unique_lock,constructor)
|
||
|
||
`unique_lock() noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.unique.cons-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8429)
|
||
|
||
*Postconditions*: pm == nullptr and owns == false[.](#thread.lock.unique.cons-1.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,constructor_)
|
||
|
||
`explicit unique_lock(mutex_type& m);
|
||
`
|
||
|
||
[2](#thread.lock.unique.cons-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8440)
|
||
|
||
*Effects*: Calls m.lock()[.](#thread.lock.unique.cons-2.sentence-1)
|
||
|
||
[3](#thread.lock.unique.cons-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8444)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == true[.](#thread.lock.unique.cons-3.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,constructor__)
|
||
|
||
`unique_lock(mutex_type& m, defer_lock_t) noexcept;
|
||
`
|
||
|
||
[4](#thread.lock.unique.cons-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8455)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == false[.](#thread.lock.unique.cons-4.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,constructor___)
|
||
|
||
`unique_lock(mutex_type& m, try_to_lock_t);
|
||
`
|
||
|
||
[5](#thread.lock.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.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3 Cpp17Lockable requirements"))[.](#thread.lock.unique.cons-5.sentence-1)
|
||
|
||
[6](#thread.lock.unique.cons-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8471)
|
||
|
||
*Effects*: Calls m.try_lock()[.](#thread.lock.unique.cons-6.sentence-1)
|
||
|
||
[7](#thread.lock.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()[.](#thread.lock.unique.cons-7.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,constructor____)
|
||
|
||
`unique_lock(mutex_type& m, adopt_lock_t);
|
||
`
|
||
|
||
[8](#thread.lock.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[.](#thread.lock.unique.cons-8.sentence-1)
|
||
|
||
[9](#thread.lock.unique.cons-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8491)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == true[.](#thread.lock.unique.cons-9.sentence-1)
|
||
|
||
[10](#thread.lock.unique.cons-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8495)
|
||
|
||
*Throws*: Nothing[.](#thread.lock.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](#thread.lock.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.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4 Cpp17TimedLockable requirements"))[.](#thread.lock.unique.cons-11.sentence-1)
|
||
|
||
[12](#thread.lock.unique.cons-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8512)
|
||
|
||
*Effects*: Calls m.try_lock_until(abs_time)[.](#thread.lock.unique.cons-12.sentence-1)
|
||
|
||
[13](#thread.lock.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)[.](#thread.lock.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](#thread.lock.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.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4 Cpp17TimedLockable requirements"))[.](#thread.lock.unique.cons-14.sentence-1)
|
||
|
||
[15](#thread.lock.unique.cons-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8534)
|
||
|
||
*Effects*: Calls m.try_lock_for(rel_time)[.](#thread.lock.unique.cons-15.sentence-1)
|
||
|
||
[16](#thread.lock.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)[.](#thread.lock.unique.cons-16.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,constructor_______)
|
||
|
||
`unique_lock(unique_lock&& u) noexcept;
|
||
`
|
||
|
||
[17](#thread.lock.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[.](#thread.lock.unique.cons-17.sentence-1)
|
||
|
||
[ð](#lib:operator=,unique_lock)
|
||
|
||
`unique_lock& operator=(unique_lock&& u) noexcept;
|
||
`
|
||
|
||
[18](#thread.lock.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](#thread.lock.unique.cons-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8565)
|
||
|
||
*Returns*: *this[.](#thread.lock.unique.cons-19.sentence-1)
|
||
|
||
[ð](#lib:unique_lock,destructor)
|
||
|
||
`~unique_lock();
|
||
`
|
||
|
||
[20](#thread.lock.unique.cons-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8576)
|
||
|
||
*Effects*: If owns calls pm->unlock()[.](#thread.lock.unique.cons-20.sentence-1)
|
||
|
||
#### [32.6.5.4.3](#thread.lock.unique.locking) Locking [[thread.lock.unique.locking]](thread.lock.unique.locking)
|
||
|
||
[ð](#lib:lock,unique_lock)
|
||
|
||
`void lock();
|
||
`
|
||
|
||
[1](#thread.lock.unique.locking-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8589)
|
||
|
||
*Effects*: As if by pm->lock()[.](#thread.lock.unique.locking-1.sentence-1)
|
||
|
||
[2](#thread.lock.unique.locking-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8593)
|
||
|
||
*Postconditions*: owns == true[.](#thread.lock.unique.locking-2.sentence-1)
|
||
|
||
[3](#thread.lock.unique.locking-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8597)
|
||
|
||
*Throws*: Any exception thrown by pm->lock()[.](#thread.lock.unique.locking-3.sentence-1)
|
||
|
||
system_error when an exception
|
||
is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.unique.locking-3.sentence-2)
|
||
|
||
[4](#thread.lock.unique.locking-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8602)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(4.1)](#thread.lock.unique.locking-4.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.unique.locking-4.1.sentence-1)
|
||
|
||
- [(4.2)](#thread.lock.unique.locking-4.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns is true[.](#thread.lock.unique.locking-4.2.sentence-1)
|
||
|
||
[ð](#lib:try_lock,unique_lock)
|
||
|
||
`bool try_lock();
|
||
`
|
||
|
||
[5](#thread.lock.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.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3 Cpp17Lockable requirements"))[.](#thread.lock.unique.locking-5.sentence-1)
|
||
|
||
[6](#thread.lock.unique.locking-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8622)
|
||
|
||
*Effects*: As if by pm->try_lock()[.](#thread.lock.unique.locking-6.sentence-1)
|
||
|
||
[7](#thread.lock.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()[.](#thread.lock.unique.locking-7.sentence-1)
|
||
|
||
[8](#thread.lock.unique.locking-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8631)
|
||
|
||
*Returns*: The value returned by pm->try_lock()[.](#thread.lock.unique.locking-8.sentence-1)
|
||
|
||
[9](#thread.lock.unique.locking-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8635)
|
||
|
||
*Throws*: Any exception thrown by pm->try_lock()[.](#thread.lock.unique.locking-9.sentence-1)
|
||
|
||
system_error when an exception
|
||
is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.unique.locking-9.sentence-2)
|
||
|
||
[10](#thread.lock.unique.locking-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8640)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(10.1)](#thread.lock.unique.locking-10.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.unique.locking-10.1.sentence-1)
|
||
|
||
- [(10.2)](#thread.lock.unique.locking-10.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns is true[.](#thread.lock.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](#thread.lock.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.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4 Cpp17TimedLockable requirements"))[.](#thread.lock.unique.locking-11.sentence-1)
|
||
|
||
[12](#thread.lock.unique.locking-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8661)
|
||
|
||
*Effects*: As if by pm->try_lock_until(abs_time)[.](#thread.lock.unique.locking-12.sentence-1)
|
||
|
||
[13](#thread.lock.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)[.](#thread.lock.unique.locking-13.sentence-1)
|
||
|
||
[14](#thread.lock.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)[.](#thread.lock.unique.locking-14.sentence-1)
|
||
|
||
[15](#thread.lock.unique.locking-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8674)
|
||
|
||
*Throws*: Any exception thrown by pm->try_lock_until(abstime)[.](#thread.lock.unique.locking-15.sentence-1)
|
||
|
||
system_error when an
|
||
exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.unique.locking-15.sentence-2)
|
||
|
||
[16](#thread.lock.unique.locking-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8679)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(16.1)](#thread.lock.unique.locking-16.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.unique.locking-16.1.sentence-1)
|
||
|
||
- [(16.2)](#thread.lock.unique.locking-16.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.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](#thread.lock.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.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements ([[thread.req.lockable.timed]](thread.req.lockable.timed "32.2.5.4 Cpp17TimedLockable requirements"))[.](#thread.lock.unique.locking-17.sentence-1)
|
||
|
||
[18](#thread.lock.unique.locking-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8699)
|
||
|
||
*Effects*: As if by pm->try_lock_for(rel_time)[.](#thread.lock.unique.locking-18.sentence-1)
|
||
|
||
[19](#thread.lock.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)[.](#thread.lock.unique.locking-19.sentence-1)
|
||
|
||
[20](#thread.lock.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)[.](#thread.lock.unique.locking-20.sentence-1)
|
||
|
||
[21](#thread.lock.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)[.](#thread.lock.unique.locking-21.sentence-1)
|
||
|
||
system_error when an
|
||
exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.unique.locking-21.sentence-2)
|
||
|
||
[22](#thread.lock.unique.locking-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8716)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(22.1)](#thread.lock.unique.locking-22.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.unique.locking-22.1.sentence-1)
|
||
|
||
- [(22.2)](#thread.lock.unique.locking-22.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.unique.locking-22.2.sentence-1)
|
||
|
||
[ð](#lib:unlock,unique_lock)
|
||
|
||
`void unlock();
|
||
`
|
||
|
||
[23](#thread.lock.unique.locking-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8731)
|
||
|
||
*Effects*: As if by pm->unlock()[.](#thread.lock.unique.locking-23.sentence-1)
|
||
|
||
[24](#thread.lock.unique.locking-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8735)
|
||
|
||
*Postconditions*: owns == false[.](#thread.lock.unique.locking-24.sentence-1)
|
||
|
||
[25](#thread.lock.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.2 Exceptions"))[.](#thread.lock.unique.locking-25.sentence-1)
|
||
|
||
[26](#thread.lock.unique.locking-26)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8744)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(26.1)](#thread.lock.unique.locking-26.1)
|
||
|
||
operation_not_permitted â if on entry owns is false[.](#thread.lock.unique.locking-26.sentence-1)
|
||
|
||
#### [32.6.5.4.4](#thread.lock.unique.mod) Modifiers [[thread.lock.unique.mod]](thread.lock.unique.mod)
|
||
|
||
[ð](#lib:swap,unique_lock)
|
||
|
||
`void swap(unique_lock& u) noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.unique.mod-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8759)
|
||
|
||
*Effects*: Swaps the data members of *this and u[.](#thread.lock.unique.mod-1.sentence-1)
|
||
|
||
[ð](#lib:release,unique_lock)
|
||
|
||
`mutex_type* release() noexcept;
|
||
`
|
||
|
||
[2](#thread.lock.unique.mod-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8770)
|
||
|
||
*Postconditions*: pm == 0 and owns == false[.](#thread.lock.unique.mod-2.sentence-1)
|
||
|
||
[3](#thread.lock.unique.mod-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8774)
|
||
|
||
*Returns*: The previous value of pm[.](#thread.lock.unique.mod-3.sentence-1)
|
||
|
||
[ð](#lib:swap,unique_lock_)
|
||
|
||
`template<class Mutex>
|
||
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
|
||
`
|
||
|
||
[4](#thread.lock.unique.mod-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8786)
|
||
|
||
*Effects*: As if by x.swap(y)[.](#thread.lock.unique.mod-4.sentence-1)
|
||
|
||
#### [32.6.5.4.5](#thread.lock.unique.obs) Observers [[thread.lock.unique.obs]](thread.lock.unique.obs)
|
||
|
||
[ð](#lib:owns_lock,unique_lock)
|
||
|
||
`bool owns_lock() const noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.unique.obs-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8799)
|
||
|
||
*Returns*: owns[.](#thread.lock.unique.obs-1.sentence-1)
|
||
|
||
[ð](#lib:operator_bool,unique_lock)
|
||
|
||
`explicit operator bool() const noexcept;
|
||
`
|
||
|
||
[2](#thread.lock.unique.obs-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8810)
|
||
|
||
*Returns*: owns[.](#thread.lock.unique.obs-2.sentence-1)
|
||
|
||
[ð](#lib:mutex,unique_lock)
|
||
|
||
`mutex_type *mutex() const noexcept;
|
||
`
|
||
|
||
[3](#thread.lock.unique.obs-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8821)
|
||
|
||
*Returns*: pm[.](#thread.lock.unique.obs-3.sentence-1)
|
||
|
||
#### [32.6.5.5](#thread.lock.shared) Class template shared_lock [[thread.lock.shared]](thread.lock.shared)
|
||
|
||
#### [32.6.5.5.1](#thread.lock.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]](#thread.lock.shared.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<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]](#thread.lock.shared.locking "32.6.5.5.3 Locking"), 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]](#thread.lock.shared.mod "32.6.5.5.4 Modifiers"), modifiersvoid swap(shared_lock& u) noexcept;
|
||
mutex_type* release() noexcept; // [[thread.lock.shared.obs]](#thread.lock.shared.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](#thread.lock.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[.](#thread.lock.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[.](#thread.lock.shared.general-1.sentence-2)
|
||
|
||
Objects of typeshared_lock are not copyable but are movable[.](#thread.lock.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.4 Lifetime")) of the shared_lock object[.](#thread.lock.shared.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"))[.](#thread.lock.shared.general-1.sentence-5)
|
||
|
||
[2](#thread.lock.shared.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8893)
|
||
|
||
[*Note [1](#thread.lock.shared.general-note-1)*:
|
||
|
||
shared_lock<Mutex> 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"))[.](#thread.lock.shared.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<Mutex> 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"))[.](#thread.lock.shared.general-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
#### [32.6.5.5.2](#thread.lock.shared.cons) Constructors, destructor, and assignment [[thread.lock.shared.cons]](thread.lock.shared.cons)
|
||
|
||
[ð](#lib:shared_lock,constructor)
|
||
|
||
`shared_lock() noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.shared.cons-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8911)
|
||
|
||
*Postconditions*: pm == nullptr and owns == false[.](#thread.lock.shared.cons-1.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,constructor_)
|
||
|
||
`explicit shared_lock(mutex_type& m);
|
||
`
|
||
|
||
[2](#thread.lock.shared.cons-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8922)
|
||
|
||
*Effects*: Calls m.lock_shared()[.](#thread.lock.shared.cons-2.sentence-1)
|
||
|
||
[3](#thread.lock.shared.cons-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8926)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == true[.](#thread.lock.shared.cons-3.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,constructor__)
|
||
|
||
`shared_lock(mutex_type& m, defer_lock_t) noexcept;
|
||
`
|
||
|
||
[4](#thread.lock.shared.cons-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8937)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == false[.](#thread.lock.shared.cons-4.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,constructor___)
|
||
|
||
`shared_lock(mutex_type& m, try_to_lock_t);
|
||
`
|
||
|
||
[5](#thread.lock.shared.cons-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8948)
|
||
|
||
*Effects*: Calls m.try_lock_shared()[.](#thread.lock.shared.cons-5.sentence-1)
|
||
|
||
[6](#thread.lock.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()[.](#thread.lock.shared.cons-6.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,constructor____)
|
||
|
||
`shared_lock(mutex_type& m, adopt_lock_t);
|
||
`
|
||
|
||
[7](#thread.lock.shared.cons-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8965)
|
||
|
||
*Preconditions*: The calling thread holds a shared lock on m[.](#thread.lock.shared.cons-7.sentence-1)
|
||
|
||
[8](#thread.lock.shared.cons-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8969)
|
||
|
||
*Postconditions*: pm == addressof(m) and owns == true[.](#thread.lock.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](#thread.lock.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.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"))[.](#thread.lock.shared.cons-9.sentence-1)
|
||
|
||
[10](#thread.lock.shared.cons-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L8987)
|
||
|
||
*Effects*: Calls m.try_lock_shared_until(abs_time)[.](#thread.lock.shared.cons-10.sentence-1)
|
||
|
||
[11](#thread.lock.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)[.](#thread.lock.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](#thread.lock.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.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"))[.](#thread.lock.shared.cons-12.sentence-1)
|
||
|
||
[13](#thread.lock.shared.cons-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9011)
|
||
|
||
*Effects*: Calls m.try_lock_shared_for(rel_time)[.](#thread.lock.shared.cons-13.sentence-1)
|
||
|
||
[14](#thread.lock.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)[.](#thread.lock.shared.cons-14.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,destructor)
|
||
|
||
`~shared_lock();
|
||
`
|
||
|
||
[15](#thread.lock.shared.cons-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9028)
|
||
|
||
*Effects*: If owns calls pm->unlock_shared()[.](#thread.lock.shared.cons-15.sentence-1)
|
||
|
||
[ð](#lib:shared_lock,constructor_______)
|
||
|
||
`shared_lock(shared_lock&& sl) noexcept;
|
||
`
|
||
|
||
[16](#thread.lock.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[.](#thread.lock.shared.cons-16.sentence-1)
|
||
|
||
[ð](#lib:operator=,shared_lock)
|
||
|
||
`shared_lock& operator=(shared_lock&& sl) noexcept;
|
||
`
|
||
|
||
[17](#thread.lock.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](#thread.lock.shared.cons-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9056)
|
||
|
||
*Returns*: *this[.](#thread.lock.shared.cons-18.sentence-1)
|
||
|
||
#### [32.6.5.5.3](#thread.lock.shared.locking) Locking [[thread.lock.shared.locking]](thread.lock.shared.locking)
|
||
|
||
[ð](#lib:lock,shared_lock)
|
||
|
||
`void lock();
|
||
`
|
||
|
||
[1](#thread.lock.shared.locking-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9069)
|
||
|
||
*Effects*: As if by pm->lock_shared()[.](#thread.lock.shared.locking-1.sentence-1)
|
||
|
||
[2](#thread.lock.shared.locking-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9073)
|
||
|
||
*Postconditions*: owns == true[.](#thread.lock.shared.locking-2.sentence-1)
|
||
|
||
[3](#thread.lock.shared.locking-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9077)
|
||
|
||
*Throws*: Any exception thrown by pm->lock_shared()[.](#thread.lock.shared.locking-3.sentence-1)
|
||
|
||
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.shared.locking-3.sentence-2)
|
||
|
||
[4](#thread.lock.shared.locking-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9082)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(4.1)](#thread.lock.shared.locking-4.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.shared.locking-4.1.sentence-1)
|
||
|
||
- [(4.2)](#thread.lock.shared.locking-4.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.shared.locking-4.2.sentence-1)
|
||
|
||
[ð](#lib:try_lock,shared_lock)
|
||
|
||
`bool try_lock();
|
||
`
|
||
|
||
[5](#thread.lock.shared.locking-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9097)
|
||
|
||
*Effects*: As if by pm->try_lock_shared()[.](#thread.lock.shared.locking-5.sentence-1)
|
||
|
||
[6](#thread.lock.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()[.](#thread.lock.shared.locking-6.sentence-1)
|
||
|
||
[7](#thread.lock.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()[.](#thread.lock.shared.locking-7.sentence-1)
|
||
|
||
[8](#thread.lock.shared.locking-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9110)
|
||
|
||
*Throws*: Any exception thrown by pm->try_lock_shared()[.](#thread.lock.shared.locking-8.sentence-1)
|
||
|
||
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.shared.locking-8.sentence-2)
|
||
|
||
[9](#thread.lock.shared.locking-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9115)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(9.1)](#thread.lock.shared.locking-9.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.shared.locking-9.1.sentence-1)
|
||
|
||
- [(9.2)](#thread.lock.shared.locking-9.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.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](#thread.lock.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.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"))[.](#thread.lock.shared.locking-10.sentence-1)
|
||
|
||
[11](#thread.lock.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)[.](#thread.lock.shared.locking-11.sentence-1)
|
||
|
||
[12](#thread.lock.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)[.](#thread.lock.shared.locking-12.sentence-1)
|
||
|
||
[13](#thread.lock.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)[.](#thread.lock.shared.locking-13.sentence-1)
|
||
|
||
[14](#thread.lock.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)[.](#thread.lock.shared.locking-14.sentence-1)
|
||
|
||
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.shared.locking-14.sentence-2)
|
||
|
||
[15](#thread.lock.shared.locking-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9155)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(15.1)](#thread.lock.shared.locking-15.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.shared.locking-15.1.sentence-1)
|
||
|
||
- [(15.2)](#thread.lock.shared.locking-15.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.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](#thread.lock.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.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"))[.](#thread.lock.shared.locking-16.sentence-1)
|
||
|
||
[17](#thread.lock.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)[.](#thread.lock.shared.locking-17.sentence-1)
|
||
|
||
[18](#thread.lock.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)[.](#thread.lock.shared.locking-18.sentence-1)
|
||
|
||
[19](#thread.lock.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)[.](#thread.lock.shared.locking-19.sentence-1)
|
||
|
||
[20](#thread.lock.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)[.](#thread.lock.shared.locking-20.sentence-1)
|
||
|
||
system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#thread.lock.shared.locking-20.sentence-2)
|
||
|
||
[21](#thread.lock.shared.locking-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9192)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(21.1)](#thread.lock.shared.locking-21.1)
|
||
|
||
operation_not_permitted â if pm is nullptr[.](#thread.lock.shared.locking-21.1.sentence-1)
|
||
|
||
- [(21.2)](#thread.lock.shared.locking-21.2)
|
||
|
||
resource_deadlock_would_occur â if on entry owns istrue[.](#thread.lock.shared.locking-21.2.sentence-1)
|
||
|
||
[ð](#lib:unlock,shared_lock)
|
||
|
||
`void unlock();
|
||
`
|
||
|
||
[22](#thread.lock.shared.locking-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9207)
|
||
|
||
*Effects*: As if by pm->unlock_shared()[.](#thread.lock.shared.locking-22.sentence-1)
|
||
|
||
[23](#thread.lock.shared.locking-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9211)
|
||
|
||
*Postconditions*: owns == false[.](#thread.lock.shared.locking-23.sentence-1)
|
||
|
||
[24](#thread.lock.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.2 Exceptions"))[.](#thread.lock.shared.locking-24.sentence-1)
|
||
|
||
[25](#thread.lock.shared.locking-25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9219)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(25.1)](#thread.lock.shared.locking-25.1)
|
||
|
||
operation_not_permitted â if on entry owns isfalse[.](#thread.lock.shared.locking-25.sentence-1)
|
||
|
||
#### [32.6.5.5.4](#thread.lock.shared.mod) Modifiers [[thread.lock.shared.mod]](thread.lock.shared.mod)
|
||
|
||
[ð](#lib:swap,shared_lock)
|
||
|
||
`void swap(shared_lock& sl) noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.shared.mod-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9235)
|
||
|
||
*Effects*: Swaps the data members of *this and sl[.](#thread.lock.shared.mod-1.sentence-1)
|
||
|
||
[ð](#lib:release,shared_lock)
|
||
|
||
`mutex_type* release() noexcept;
|
||
`
|
||
|
||
[2](#thread.lock.shared.mod-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9246)
|
||
|
||
*Postconditions*: pm == nullptr and owns == false[.](#thread.lock.shared.mod-2.sentence-1)
|
||
|
||
[3](#thread.lock.shared.mod-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9250)
|
||
|
||
*Returns*: The previous value of pm[.](#thread.lock.shared.mod-3.sentence-1)
|
||
|
||
[ð](#lib:swap,shared_lock_)
|
||
|
||
`template<class Mutex>
|
||
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
|
||
`
|
||
|
||
[4](#thread.lock.shared.mod-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9262)
|
||
|
||
*Effects*: As if by x.swap(y)[.](#thread.lock.shared.mod-4.sentence-1)
|
||
|
||
#### [32.6.5.5.5](#thread.lock.shared.obs) Observers [[thread.lock.shared.obs]](thread.lock.shared.obs)
|
||
|
||
[ð](#lib:owns_lock,shared_lock)
|
||
|
||
`bool owns_lock() const noexcept;
|
||
`
|
||
|
||
[1](#thread.lock.shared.obs-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9275)
|
||
|
||
*Returns*: owns[.](#thread.lock.shared.obs-1.sentence-1)
|
||
|
||
[ð](#lib:operator_bool,shared_lock)
|
||
|
||
`explicit operator bool() const noexcept;
|
||
`
|
||
|
||
[2](#thread.lock.shared.obs-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9286)
|
||
|
||
*Returns*: owns[.](#thread.lock.shared.obs-2.sentence-1)
|
||
|
||
[ð](#lib:mutex,shared_lock)
|
||
|
||
`mutex_type* mutex() const noexcept;
|
||
`
|
||
|
||
[3](#thread.lock.shared.obs-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9297)
|
||
|
||
*Returns*: pm[.](#thread.lock.shared.obs-3.sentence-1)
|
||
|
||
### [32.6.6](#thread.lock.algorithm) Generic locking algorithms [[thread.lock.algorithm]](thread.lock.algorithm)
|
||
|
||
[ð](#lib:try_lock)
|
||
|
||
`template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
|
||
`
|
||
|
||
[1](#thread.lock.algorithm-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9310)
|
||
|
||
*Preconditions*: Each template parameter type meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements[.](#thread.lock.algorithm-1.sentence-1)
|
||
|
||
[*Note [1](#thread.lock.algorithm-note-1)*:
|
||
|
||
Theunique_lock class template meets these requirements when suitably instantiated[.](#thread.lock.algorithm-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#thread.lock.algorithm-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9318)
|
||
|
||
*Effects*: Calls try_lock() for each argument in order beginning with the
|
||
first until all arguments have been processed or a call to try_lock() fails,
|
||
either by returning false or by throwing an exception[.](#thread.lock.algorithm-2.sentence-1)
|
||
|
||
If a call totry_lock() fails, unlock() is called for all prior arguments
|
||
with no further calls to try_lock()[.](#thread.lock.algorithm-2.sentence-2)
|
||
|
||
[3](#thread.lock.algorithm-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9326)
|
||
|
||
*Returns*: -1 if all calls to try_lock() returned true,
|
||
otherwise a zero-based index value that indicates the argument for which try_lock() returned false[.](#thread.lock.algorithm-3.sentence-1)
|
||
|
||
[ð](#lib:lock)
|
||
|
||
`template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
|
||
`
|
||
|
||
[4](#thread.lock.algorithm-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9339)
|
||
|
||
*Preconditions*: Each template parameter type meets the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements[.](#thread.lock.algorithm-4.sentence-1)
|
||
|
||
[*Note [2](#thread.lock.algorithm-note-2)*:
|
||
|
||
Theunique_lock class template meets these requirements when suitably instantiated[.](#thread.lock.algorithm-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[5](#thread.lock.algorithm-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9347)
|
||
|
||
*Effects*: All arguments are locked via a sequence of calls to lock(),try_lock(), or unlock() on each argument[.](#thread.lock.algorithm-5.sentence-1)
|
||
|
||
The sequence of calls does
|
||
not result in deadlock, but is otherwise unspecified[.](#thread.lock.algorithm-5.sentence-2)
|
||
|
||
[*Note [3](#thread.lock.algorithm-note-3)*:
|
||
|
||
A deadlock avoidance
|
||
algorithm such as try-and-back-off can be used, but the specific algorithm is not
|
||
specified to avoid over-constraining implementations[.](#thread.lock.algorithm-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
If a call tolock() or try_lock() throws an exception, unlock() is
|
||
called for any argument that had been locked by a call to lock() ortry_lock()[.](#thread.lock.algorithm-5.sentence-4)
|
||
|
||
### [32.6.7](#thread.once) Call once [[thread.once]](thread.once)
|
||
|
||
#### [32.6.7.1](#thread.once.onceflag) Struct once_flag [[thread.once.onceflag]](thread.once.onceflag)
|
||
|
||
[ð](#lib:once_flag)
|
||
|
||
namespace std {struct once_flag {constexpr once_flag() noexcept;
|
||
|
||
once_flag(const once_flag&) = delete;
|
||
once_flag& operator=(const once_flag&) = delete; };}
|
||
|
||
[1](#thread.once.onceflag-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9379)
|
||
|
||
The class once_flag is an opaque data structure that call_once uses to
|
||
initialize data without causing a data race or deadlock[.](#thread.once.onceflag-1.sentence-1)
|
||
|
||
[ð](#lib:once_flag_)
|
||
|
||
`constexpr once_flag() noexcept;
|
||
`
|
||
|
||
[2](#thread.once.onceflag-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9389)
|
||
|
||
*Synchronization*: The construction of a once_flag object is not synchronized[.](#thread.once.onceflag-2.sentence-1)
|
||
|
||
[3](#thread.once.onceflag-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9393)
|
||
|
||
*Postconditions*: The object's internal state is set to indicate to an invocation ofcall_once with the object as its initial argument that no function has been
|
||
called[.](#thread.once.onceflag-3.sentence-1)
|
||
|
||
#### [32.6.7.2](#thread.once.callonce) Function call_once [[thread.once.callonce]](thread.once.callonce)
|
||
|
||
[ð](#lib:call_once)
|
||
|
||
`template<class Callable, class... Args>
|
||
void call_once(once_flag& flag, Callable&& func, Args&&... args);
|
||
`
|
||
|
||
[1](#thread.once.callonce-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9409)
|
||
|
||
*Mandates*: is_invocable_v<Callable, Args...> is true[.](#thread.once.callonce-1.sentence-1)
|
||
|
||
[2](#thread.once.callonce-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9413)
|
||
|
||
*Effects*: An execution of call_once that does not call its func is a[*passive*](#def:passive) execution[.](#thread.once.callonce-2.sentence-1)
|
||
|
||
An execution of call_once that calls its func is an [*active*](#def:active) execution[.](#thread.once.callonce-2.sentence-2)
|
||
|
||
An active execution evaluates*INVOKE*(std::forward<Callable>(func),
|
||
std::forward<Args>(args)...) ([[func.require]](func.require "22.10.4 Requirements"))[.](#thread.once.callonce-2.sentence-3)
|
||
|
||
If such a call to func throws an exception the execution is [*exceptional*](#def:exceptional), otherwise it is [*returning*](#def:returning)[.](#thread.once.callonce-2.sentence-4)
|
||
|
||
An exceptional execution propagates the exception to the caller ofcall_once[.](#thread.once.callonce-2.sentence-5)
|
||
|
||
Among all executions of call_once for any givenonce_flag: at most one is a returning execution; if there is a
|
||
returning execution, it is the last active execution; and there are
|
||
passive executions only if there is a returning execution[.](#thread.once.callonce-2.sentence-6)
|
||
|
||
[*Note [1](#thread.once.callonce-note-1)*:
|
||
|
||
Passive
|
||
executions allow other threads to reliably observe the results produced by the
|
||
earlier returning execution[.](#thread.once.callonce-2.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[3](#thread.once.callonce-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9433)
|
||
|
||
*Synchronization*: For any given once_flag: all active executions occur in a total
|
||
order; completion of an active execution [synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") the start of the next one in this total order; and the returning execution
|
||
synchronizes with the return from all passive executions[.](#thread.once.callonce-3.sentence-1)
|
||
|
||
[4](#thread.once.callonce-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9440)
|
||
|
||
*Throws*: system_error when
|
||
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions")), or any exception thrown by func[.](#thread.once.callonce-4.sentence-1)
|
||
|
||
[5](#thread.once.callonce-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9445)
|
||
|
||
[*Example [1](#thread.once.callonce-example-1)*: // global flag, regular functionvoid init();
|
||
std::once_flag flag;
|
||
|
||
void f() { std::call_once(flag, init);}// function static flag, function objectstruct initializer {void operator()();};
|
||
|
||
void g() {static std::once_flag flag2;
|
||
std::call_once(flag2, initializer());}// object flag, member functionclass information { std::once_flag verified; void verifier();public:void verify() { std::call_once(verified, &information::verifier, *this); }}; â *end example*]
|