From Jason Turner

[thread.mutex]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpzbk0d1oa/{from.md → to.md} +151 -129
tmp/tmpzbk0d1oa/{from.md → to.md} RENAMED
@@ -1,35 +1,43 @@
1
  ## Mutual exclusion <a id="thread.mutex">[[thread.mutex]]</a>
2
 
3
- This subclause provides mechanisms for mutual exclusion: mutexes, locks,
4
- and call once. These mechanisms ease the production of race-free
5
- programs [[intro.multithread]].
 
 
6
 
7
  ### Header `<mutex>` synopsis <a id="mutex.syn">[[mutex.syn]]</a>
8
 
9
  ``` cpp
10
  namespace std {
 
11
  class mutex;
 
12
  class recursive_mutex;
 
13
  class timed_mutex;
 
14
  class recursive_timed_mutex;
15
 
16
  struct defer_lock_t { explicit defer_lock_t() = default; };
17
  struct try_to_lock_t { explicit try_to_lock_t() = default; };
18
  struct adopt_lock_t { explicit adopt_lock_t() = default; };
19
 
20
  inline constexpr defer_lock_t defer_lock { };
21
  inline constexpr try_to_lock_t try_to_lock { };
22
  inline constexpr adopt_lock_t adopt_lock { };
23
 
 
24
  template<class Mutex> class lock_guard;
25
  template<class... MutexTypes> class scoped_lock;
26
  template<class Mutex> class unique_lock;
27
 
28
  template<class Mutex>
29
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
30
 
 
31
  template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
32
  template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
33
 
34
  struct once_flag;
35
 
@@ -40,12 +48,15 @@ namespace std {
40
 
41
  ### Header `<shared_mutex>` synopsis <a id="shared.mutex.syn">[[shared.mutex.syn]]</a>
42
 
43
  ``` cpp
44
  namespace std {
 
45
  class shared_mutex;
 
46
  class shared_timed_mutex;
 
47
  template<class Mutex> class shared_lock;
48
  template<class Mutex>
49
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
50
  }
51
  ```
@@ -62,18 +73,20 @@ Mutexes can be either recursive or non-recursive, and can grant
62
  simultaneous ownership to one or many execution agents. Both recursive
63
  and non-recursive mutexes are supplied.
64
 
65
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
66
 
 
 
67
  The *mutex types* are the standard library types `mutex`,
68
  `recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
69
  `shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
70
- out in this subclause. In this description, `m` denotes an object of a
71
- mutex type.
72
 
73
- The mutex types meet the *Cpp17Lockable* requirements
74
- [[thread.req.lockable.req]].
75
 
76
  The mutex types meet *Cpp17DefaultConstructible* and
77
  *Cpp17Destructible*. If initialization of an object of a mutex type
78
  fails, an exception of type `system_error` is thrown. The mutex types
79
  are neither copyable nor movable.
@@ -91,15 +104,15 @@ functions of the mutex types are as follows:
91
  The implementation provides lock and unlock operations, as described
92
  below. For purposes of determining the existence of a data race, these
93
  behave as atomic operations [[intro.multithread]]. The lock and unlock
94
  operations on a single mutex appears to occur in a single total order.
95
 
96
- [*Note 1*: This can be viewed as the modification order
97
  [[intro.multithread]] of the mutex. — *end note*]
98
 
99
- [*Note 2*: Construction and destruction of an object of a mutex type
100
- need not be thread-safe; other synchronization should be used to ensure
101
  that mutex objects are initialized and visible to other
102
  threads. — *end note*]
103
 
104
  The expression `m.lock()` is well-formed and has the following
105
  semantics:
@@ -109,17 +122,17 @@ semantics:
109
  the mutex.
110
 
111
  *Effects:* Blocks the calling thread until ownership of the mutex can be
112
  obtained for the calling thread.
113
 
114
- *Ensures:* The calling thread owns the mutex.
115
-
116
- *Return type:* `void`.
117
-
118
  *Synchronization:* Prior `unlock()` operations on the same object
119
  *synchronize with*[[intro.multithread]] this operation.
120
 
 
 
 
 
121
  *Throws:* `system_error` when an exception is
122
  required [[thread.req.exception]].
123
 
124
  *Error conditions:*
125
 
@@ -145,24 +158,23 @@ interesting implementations based on a simple compare and
145
  exchange [[atomics]]. — *end note*]
146
 
147
  An implementation should ensure that `try_lock()` does not consistently
148
  return `false` in the absence of contending mutex acquisitions.
149
 
150
- *Return type:* `bool`.
151
-
152
- *Returns:* `true` if ownership of the mutex was obtained for the calling
153
- thread, otherwise `false`.
154
-
155
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
156
  operations on the same object *synchronize with*[[intro.multithread]]
157
  this operation.
158
 
159
  [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
160
  `try_lock()`, the visibility rules are weak enough that little would be
161
  known about the state after a failure, even in the absence of spurious
162
  failures. — *end note*]
163
 
 
 
 
 
164
  *Throws:* Nothing.
165
 
166
  The expression `m.unlock()` is well-formed and has the following
167
  semantics:
168
 
@@ -204,11 +216,11 @@ The class `mutex` provides a non-recursive mutex with exclusive
204
  ownership semantics. If one thread owns a mutex object, attempts by
205
  another thread to acquire ownership of that object will fail (for
206
  `try_lock()`) or block (for `lock()`) until the owning thread has
207
  released ownership with a call to `unlock()`.
208
 
209
- [*Note 3*: After a thread `A` has called `unlock()`, releasing a mutex,
210
  it is possible for another thread `B` to lock the same mutex, observe
211
  that it is no longer in use, unlock it, and destroy it, before thread
212
  `A` appears to have returned from its unlock call. Implementations are
213
  required to handle such scenarios correctly, as long as thread `A`
214
  doesn’t access the mutex after the unlock call returns. These cases
@@ -217,11 +229,11 @@ used to protect the reference count. — *end note*]
217
 
218
  The class `mutex` meets all of the mutex requirements
219
  [[thread.mutex.requirements]]. It is a standard-layout class
220
  [[class.prop]].
221
 
222
- [*Note 4*: A program can deadlock if the thread that owns a `mutex`
223
  object calls `lock()` on that object. If the implementation can detect
224
  the deadlock, a `resource_deadlock_would_occur` error condition might be
225
  observed. — *end note*]
226
 
227
  The behavior of a program is undefined if it destroys a `mutex` object
@@ -276,19 +288,21 @@ The behavior of a program is undefined if:
276
  - it destroys a `recursive_mutex` object owned by any thread or
277
  - a thread terminates while owning a `recursive_mutex` object.
278
 
279
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
280
 
 
 
281
  The *timed mutex types* are the standard library types `timed_mutex`,
282
  `recursive_timed_mutex`, and `shared_timed_mutex`. They meet the
283
  requirements set out below. In this description, `m` denotes an object
284
  of a mutex type, `rel_time` denotes an object of an instantiation of
285
  `duration` [[time.duration]], and `abs_time` denotes an object of an
286
  instantiation of `time_point` [[time.point]].
287
 
288
- The timed mutex types meet the *Cpp17TimedLockable* requirements
289
- [[thread.req.lockable.timed]].
290
 
291
  The expression `m.try_lock_for(rel_time)` is well-formed and has the
292
  following semantics:
293
 
294
  *Preconditions:* If `m` is of type `timed_mutex` or
@@ -304,18 +318,18 @@ the mutex object.
304
 
305
  [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
306
  will be obtained if the lock is available, but implementations are
307
  expected to make a strong effort to do so. — *end note*]
308
 
309
- *Return type:* `bool`.
310
-
311
- *Returns:* `true` if ownership was obtained, otherwise `false`.
312
-
313
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
314
  operations on the same object *synchronize with*[[intro.multithread]]
315
  this operation.
316
 
 
 
 
 
317
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
318
 
319
  The expression `m.try_lock_until(abs_time)` is well-formed and has the
320
  following semantics:
321
 
@@ -330,18 +344,18 @@ before the absolute timeout [[thread.req.timing]] specified by
330
 
331
  [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
332
  will be obtained if the lock is available, but implementations are
333
  expected to make a strong effort to do so. — *end note*]
334
 
335
- *Return type:* `bool`.
336
-
337
- *Returns:* `true` if ownership was obtained, otherwise `false`.
338
-
339
  *Synchronization:* If `try_lock_until()` returns `true`, prior
340
  `unlock()` operations on the same object *synchronize
341
  with*[[intro.multithread]] this operation.
342
 
 
 
 
 
343
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
344
 
345
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
346
 
347
  ``` cpp
@@ -444,16 +458,21 @@ The behavior of a program is undefined if:
444
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
445
  - a thread terminates while owning a `recursive_timed_mutex` object.
446
 
447
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
448
 
 
 
449
  The standard library types `shared_mutex` and `shared_timed_mutex` are
450
  *shared mutex types*. Shared mutex types meet the requirements of mutex
451
  types [[thread.mutex.requirements.mutex]] and additionally meet the
452
  requirements set out below. In this description, `m` denotes an object
453
  of a shared mutex type.
454
 
 
 
 
455
  In addition to the exclusive lock ownership mode specified in 
456
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
457
  *shared lock* ownership mode. Multiple execution agents can
458
  simultaneously hold a shared lock ownership of a shared mutex type. But
459
  no execution agent holds a shared lock while another execution agent
@@ -472,17 +491,17 @@ semantics:
472
 
473
  *Effects:* Blocks the calling thread until shared ownership of the mutex
474
  can be obtained for the calling thread. If an exception is thrown then a
475
  shared lock has not been acquired for the current thread.
476
 
477
- *Ensures:* The calling thread has a shared lock on the mutex.
478
-
479
- *Return type:* `void`.
480
-
481
  *Synchronization:* Prior `unlock()` operations on the same object
482
  synchronize with [[intro.multithread]] this operation.
483
 
 
 
 
 
484
  *Throws:* `system_error` when an exception is
485
  required [[thread.req.exception]].
486
 
487
  *Error conditions:*
488
 
@@ -516,19 +535,18 @@ following semantics:
516
  calling thread without blocking. If shared ownership is not obtained,
517
  there is no effect and `try_lock_shared()` immediately returns. An
518
  implementation may fail to obtain the lock even if it is not held by any
519
  other thread.
520
 
521
- *Return type:* `bool`.
522
-
523
- *Returns:* `true` if the shared ownership lock was acquired, `false`
524
- otherwise.
525
-
526
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
527
  `unlock()` operations on the same object synchronize
528
  with [[intro.multithread]] this operation.
529
 
 
 
 
 
530
  *Throws:* Nothing.
531
 
532
  ##### Class `shared_mutex` <a id="thread.sharedmutex.class">[[thread.sharedmutex.class]]</a>
533
 
534
  ``` cpp
@@ -574,19 +592,25 @@ The behavior of a program is undefined if:
574
 
575
  `shared_mutex` may be a synonym for `shared_timed_mutex`.
576
 
577
  #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
578
 
 
 
579
  The standard library type `shared_timed_mutex` is a *shared timed mutex
580
  type*. Shared timed mutex types meet the requirements of timed mutex
581
  types [[thread.timedmutex.requirements]], shared mutex types
582
  [[thread.sharedmutex.requirements]], and additionally meet the
583
  requirements set out below. In this description, `m` denotes an object
584
- of a shared timed mutex type, `rel_type` denotes an object of an
585
  instantiation of `duration` [[time.duration]], and `abs_time` denotes an
586
  object of an instantiation of `time_point` [[time.point]].
587
 
 
 
 
 
588
  The expression `m.try_lock_shared_for(rel_time)` is well-formed and has
589
  the following semantics:
590
 
591
  *Preconditions:* The calling thread has no ownership of the mutex.
592
 
@@ -603,18 +627,18 @@ will be obtained if the lock is available, but implementations are
603
  expected to make a strong effort to do so. — *end note*]
604
 
605
  If an exception is thrown then a shared lock has not been acquired for
606
  the current thread.
607
 
608
- *Return type:* `bool`.
609
-
610
- *Returns:* `true` if the shared lock was acquired, `false` otherwise.
611
-
612
  *Synchronization:* If `try_lock_shared_for()` returns `true`, prior
613
  `unlock()` operations on the same object synchronize
614
  with [[intro.multithread]] this operation.
615
 
 
 
 
 
616
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
617
 
618
  The expression `m.try_lock_shared_until(abs_time)` is well-formed and
619
  has the following semantics:
620
 
@@ -632,18 +656,18 @@ will be obtained if the lock is available, but implementations are
632
  expected to make a strong effort to do so. — *end note*]
633
 
634
  If an exception is thrown then a shared lock has not been acquired for
635
  the current thread.
636
 
637
- *Return type:* `bool`.
638
-
639
- *Returns:* `true` if the shared lock was acquired, `false` otherwise.
640
-
641
  *Synchronization:* If `try_lock_shared_until()` returns `true`, prior
642
  `unlock()` operations on the same object synchronize
643
  with [[intro.multithread]] this operation.
644
 
 
 
 
 
645
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
646
 
647
  ##### Class `shared_timed_mutex` <a id="thread.sharedtimedmutex.class">[[thread.sharedtimedmutex.class]]</a>
648
 
649
  ``` cpp
@@ -692,10 +716,12 @@ The behavior of a program is undefined if:
692
  - a thread terminates while possessing any ownership of a
693
  `shared_timed_mutex`.
694
 
695
  ### Locks <a id="thread.lock">[[thread.lock]]</a>
696
 
 
 
697
  A *lock* is an object that holds a reference to a lockable object and
698
  may unlock the lockable object during the lock’s destruction (such as
699
  when leaving block scope). An execution agent may use a lock to aid in
700
  managing ownership of a lockable object in an exception safe manner. A
701
  lock is said to *own* a lockable object if it is currently managing the
@@ -755,39 +781,36 @@ object referenced by `pm` does not exist for the entire lifetime of the
755
 
756
  ``` cpp
757
  explicit lock_guard(mutex_type& m);
758
  ```
759
 
760
- *Preconditions:* If `mutex_type` is not a recursive mutex, the calling
761
- thread does not own the mutex `m`.
762
-
763
  *Effects:* Initializes `pm` with `m`. Calls `m.lock()`.
764
 
765
  ``` cpp
766
  lock_guard(mutex_type& m, adopt_lock_t);
767
  ```
768
 
769
- *Preconditions:* The calling thread owns the mutex `m`.
770
 
771
  *Effects:* Initializes `pm` with `m`.
772
 
773
  *Throws:* Nothing.
774
 
775
  ``` cpp
776
  ~lock_guard();
777
  ```
778
 
779
- *Effects:* As if by `pm.unlock()`.
780
 
781
  #### Class template `scoped_lock` <a id="thread.lock.scoped">[[thread.lock.scoped]]</a>
782
 
783
  ``` cpp
784
  namespace std {
785
  template<class... MutexTypes>
786
  class scoped_lock {
787
  public:
788
- using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
789
 
790
  explicit scoped_lock(MutexTypes&... m);
791
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
792
  ~scoped_lock();
793
 
@@ -803,32 +826,35 @@ namespace std {
803
  An object of type `scoped_lock` controls the ownership of lockable
804
  objects within a scope. A `scoped_lock` object maintains ownership of
805
  lockable objects throughout the `scoped_lock` object’s lifetime
806
  [[basic.life]]. The behavior of a program is undefined if the lockable
807
  objects referenced by `pm` do not exist for the entire lifetime of the
808
- `scoped_lock` object. When `sizeof...(MutexTypes)` is `1`, the supplied
809
- `Mutex` type shall meet the *Cpp17BasicLockable* requirements
810
- [[thread.req.lockable.basic]]. Otherwise, each of the mutex types shall
811
- meet the *Cpp17Lockable* requirements [[thread.req.lockable.req]].
 
 
 
 
 
812
 
813
  ``` cpp
814
  explicit scoped_lock(MutexTypes&... m);
815
  ```
816
 
817
- *Preconditions:* If a `MutexTypes` type is not a recursive mutex, the
818
- calling thread does not own the corresponding mutex element of `m`.
819
-
820
  *Effects:* Initializes `pm` with `tie(m...)`. Then if
821
  `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
822
  `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
823
  `lock(m...)`.
824
 
825
  ``` cpp
826
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
827
  ```
828
 
829
- *Preconditions:* The calling thread owns all the mutexes in `m`.
 
830
 
831
  *Effects:* Initializes `pm` with `tie(m...)`.
832
 
833
  *Throws:* Nothing.
834
 
@@ -839,10 +865,12 @@ explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
839
  *Effects:* For all `i` in \[`0`, `sizeof...(MutexTypes)`),
840
  `get<i>(pm).unlock()`.
841
 
842
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
843
 
 
 
844
  ``` cpp
845
  namespace std {
846
  template<class Mutex>
847
  class unique_lock {
848
  public:
@@ -888,13 +916,10 @@ namespace std {
888
 
889
  private:
890
  mutex_type* pm; // exposition only
891
  bool owns; // exposition only
892
  };
893
-
894
- template<class Mutex>
895
- void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
896
  }
897
  ```
898
 
899
  An object of type `unique_lock` controls the ownership of a lockable
900
  object within a scope. Ownership of the lockable object may be acquired
@@ -918,19 +943,16 @@ meets the *Cpp17TimedLockable* requirements. — *end note*]
918
 
919
  ``` cpp
920
  unique_lock() noexcept;
921
  ```
922
 
923
- *Ensures:* `pm == 0` and `owns == false`.
924
 
925
  ``` cpp
926
  explicit unique_lock(mutex_type& m);
927
  ```
928
 
929
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
930
- thread does not own the mutex.
931
-
932
  *Effects:* Calls `m.lock()`.
933
 
934
  *Ensures:* `pm == addressof(m)` and `owns == true`.
935
 
936
  ``` cpp
@@ -942,35 +964,33 @@ unique_lock(mutex_type& m, defer_lock_t) noexcept;
942
  ``` cpp
943
  unique_lock(mutex_type& m, try_to_lock_t);
944
  ```
945
 
946
  *Preconditions:* The supplied `Mutex` type meets the *Cpp17Lockable*
947
- requirements [[thread.req.lockable.req]]. If `mutex_type` is not a
948
- recursive mutex the calling thread does not own the mutex.
949
 
950
  *Effects:* Calls `m.try_lock()`.
951
 
952
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
953
  value returned by the call to `m.try_lock()`.
954
 
955
  ``` cpp
956
  unique_lock(mutex_type& m, adopt_lock_t);
957
  ```
958
 
959
- *Preconditions:* The calling thread owns the mutex.
960
 
961
  *Ensures:* `pm == addressof(m)` and `owns == true`.
962
 
963
  *Throws:* Nothing.
964
 
965
  ``` cpp
966
  template<class Clock, class Duration>
967
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
968
  ```
969
 
970
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
971
- thread does not own the mutex. The supplied `Mutex` type meets the
972
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
973
 
974
  *Effects:* Calls `m.try_lock_until(abs_time)`.
975
 
976
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
@@ -979,12 +999,11 @@ value returned by the call to `m.try_lock_until(abs_time)`.
979
  ``` cpp
980
  template<class Rep, class Period>
981
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
982
  ```
983
 
984
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
985
- thread does not own the mutex. The supplied `Mutex` type meets the
986
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
987
 
988
  *Effects:* Calls `m.try_lock_for(rel_time)`.
989
 
990
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
@@ -1045,14 +1064,14 @@ bool try_lock();
1045
  *Preconditions:* The supplied `Mutex` meets the *Cpp17Lockable*
1046
  requirements [[thread.req.lockable.req]].
1047
 
1048
  *Effects:* As if by `pm->try_lock()`.
1049
 
1050
- *Returns:* The value returned by the call to `try_lock()`.
 
1051
 
1052
- *Ensures:* `owns == res`, where `res` is the value returned by the call
1053
- to `try_lock()`.
1054
 
1055
  *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
1056
  an exception is required [[thread.req.exception]].
1057
 
1058
  *Error conditions:*
@@ -1068,17 +1087,17 @@ template<class Clock, class Duration>
1068
  *Preconditions:* The supplied `Mutex` type meets the
1069
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
1070
 
1071
  *Effects:* As if by `pm->try_lock_until(abs_time)`.
1072
 
1073
- *Returns:* The value returned by the call to `try_lock_until(abs_time)`.
 
1074
 
1075
- *Ensures:* `owns == res`, where `res` is the value returned by the call
1076
- to `try_lock_until(abs_time)`.
1077
 
1078
- *Throws:* Any exception thrown by `pm->try_lock_until()`. `system_error`
1079
- when an exception is required [[thread.req.exception]].
1080
 
1081
  *Error conditions:*
1082
 
1083
  - `operation_not_permitted` — if `pm` is `nullptr`.
1084
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -1091,17 +1110,17 @@ template<class Rep, class Period>
1091
  *Preconditions:* The supplied `Mutex` type meets the
1092
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
1093
 
1094
  *Effects:* As if by `pm->try_lock_for(rel_time)`.
1095
 
1096
- *Returns:* The value returned by the call to `try_lock_for(rel_time)`.
 
1097
 
1098
- *Ensures:* `owns == res`, where `res` is the value returned by the call
1099
- to `try_lock_for(rel_time)`.
1100
 
1101
- *Throws:* Any exception thrown by `pm->try_lock_for()`. `system_error`
1102
- when an exception is required [[thread.req.exception]].
1103
 
1104
  *Error conditions:*
1105
 
1106
  - `operation_not_permitted` — if `pm` is `nullptr`.
1107
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -1131,14 +1150,14 @@ void swap(unique_lock& u) noexcept;
1131
 
1132
  ``` cpp
1133
  mutex_type* release() noexcept;
1134
  ```
1135
 
1136
- *Returns:* The previous value of `pm`.
1137
-
1138
  *Ensures:* `pm == 0` and `owns == false`.
1139
 
 
 
1140
  ``` cpp
1141
  template<class Mutex>
1142
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1143
  ```
1144
 
@@ -1164,10 +1183,12 @@ mutex_type *mutex() const noexcept;
1164
 
1165
  *Returns:* `pm`.
1166
 
1167
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
1168
 
 
 
1169
  ``` cpp
1170
  namespace std {
1171
  template<class Mutex>
1172
  class shared_lock {
1173
  public:
@@ -1211,13 +1232,10 @@ namespace std {
1211
 
1212
  private:
1213
  mutex_type* pm; // exposition only
1214
  bool owns; // exposition only
1215
  };
1216
-
1217
- template<class Mutex>
1218
- void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1219
  }
1220
  ```
1221
 
1222
  An object of type `shared_lock` controls the shared ownership of a
1223
  lockable object within a scope. Shared ownership of the lockable object
@@ -1225,15 +1243,19 @@ may be acquired at construction or after construction, and may be
1225
  transferred, after acquisition, to another `shared_lock` object. Objects
1226
  of type `shared_lock` are not copyable but are movable. The behavior of
1227
  a program is undefined if the contained pointer `pm` is not null and the
1228
  lockable object pointed to by `pm` does not exist for the entire
1229
  remaining lifetime [[basic.life]] of the `shared_lock` object. The
1230
- supplied `Mutex` type shall meet the shared mutex requirements
1231
- [[thread.sharedtimedmutex.requirements]].
1232
 
1233
- [*Note 1*: `shared_lock<Mutex>` meets the *Cpp17TimedLockable*
1234
- requirements [[thread.req.lockable.timed]]. *end note*]
 
 
 
 
1235
 
1236
  ##### Constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
1237
 
1238
  ``` cpp
1239
  shared_lock() noexcept;
@@ -1243,13 +1265,10 @@ shared_lock() noexcept;
1243
 
1244
  ``` cpp
1245
  explicit shared_lock(mutex_type& m);
1246
  ```
1247
 
1248
- *Preconditions:* The calling thread does not own the mutex for any
1249
- ownership mode.
1250
-
1251
  *Effects:* Calls `m.lock_shared()`.
1252
 
1253
  *Ensures:* `pm == addressof(m)` and `owns == true`.
1254
 
1255
  ``` cpp
@@ -1260,34 +1279,31 @@ shared_lock(mutex_type& m, defer_lock_t) noexcept;
1260
 
1261
  ``` cpp
1262
  shared_lock(mutex_type& m, try_to_lock_t);
1263
  ```
1264
 
1265
- *Preconditions:* The calling thread does not own the mutex for any
1266
- ownership mode.
1267
-
1268
  *Effects:* Calls `m.try_lock_shared()`.
1269
 
1270
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1271
  value returned by the call to `m.try_lock_shared()`.
1272
 
1273
  ``` cpp
1274
  shared_lock(mutex_type& m, adopt_lock_t);
1275
  ```
1276
 
1277
- *Preconditions:* The calling thread has shared ownership of the mutex.
1278
 
1279
  *Ensures:* `pm == addressof(m)` and `owns == true`.
1280
 
1281
  ``` cpp
1282
  template<class Clock, class Duration>
1283
  shared_lock(mutex_type& m,
1284
  const chrono::time_point<Clock, Duration>& abs_time);
1285
  ```
1286
 
1287
- *Preconditions:* The calling thread does not own the mutex for any
1288
- ownership mode.
1289
 
1290
  *Effects:* Calls `m.try_lock_shared_until(abs_time)`.
1291
 
1292
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1293
  value returned by the call to `m.try_lock_shared_until(abs_time)`.
@@ -1296,12 +1312,12 @@ value returned by the call to `m.try_lock_shared_until(abs_time)`.
1296
  template<class Rep, class Period>
1297
  shared_lock(mutex_type& m,
1298
  const chrono::duration<Rep, Period>& rel_time);
1299
  ```
1300
 
1301
- *Preconditions:* The calling thread does not own the mutex for any
1302
- ownership mode.
1303
 
1304
  *Effects:* Calls `m.try_lock_shared_for(rel_time)`.
1305
 
1306
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1307
  value returned by the call to `m.try_lock_shared_for(rel_time)`.
@@ -1352,15 +1368,15 @@ when an exception is required [[thread.req.exception]].
1352
  bool try_lock();
1353
  ```
1354
 
1355
  *Effects:* As if by `pm->try_lock_shared()`.
1356
 
1357
- *Returns:* The value returned by the call to `pm->try_lock_shared()`.
1358
-
1359
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1360
  to `pm->try_lock_shared()`.
1361
 
 
 
1362
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
1363
  `system_error` when an exception is required [[thread.req.exception]].
1364
 
1365
  *Error conditions:*
1366
 
@@ -1370,18 +1386,21 @@ to `pm->try_lock_shared()`.
1370
  ``` cpp
1371
  template<class Clock, class Duration>
1372
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1373
  ```
1374
 
 
 
 
1375
  *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
1376
 
1377
- *Returns:* The value returned by the call to
1378
- `pm->try_lock_shared_until(abs_time)`.
1379
-
1380
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1381
  to `pm->try_lock_shared_until(abs_time)`.
1382
 
 
 
 
1383
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
1384
  `system_error` when an exception is required [[thread.req.exception]].
1385
 
1386
  *Error conditions:*
1387
 
@@ -1391,18 +1410,21 @@ to `pm->try_lock_shared_until(abs_time)`.
1391
  ``` cpp
1392
  template<class Rep, class Period>
1393
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1394
  ```
1395
 
 
 
 
1396
  *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
1397
 
1398
- *Returns:* The value returned by the call to
1399
- `pm->try_lock_shared_for(rel_time)`.
1400
-
1401
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1402
  to `pm->try_lock_shared_for(rel_time)`.
1403
 
 
 
 
1404
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
1405
  `system_error` when an exception is required [[thread.req.exception]].
1406
 
1407
  *Error conditions:*
1408
 
@@ -1434,14 +1456,14 @@ void swap(shared_lock& sl) noexcept;
1434
 
1435
  ``` cpp
1436
  mutex_type* release() noexcept;
1437
  ```
1438
 
1439
- *Returns:* The previous value of `pm`.
1440
-
1441
  *Ensures:* `pm == nullptr` and `owns == false`.
1442
 
 
 
1443
  ``` cpp
1444
  template<class Mutex>
1445
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1446
  ```
1447
 
@@ -1501,11 +1523,11 @@ when suitably instantiated. — *end note*]
1501
 
1502
  *Effects:* All arguments are locked via a sequence of calls to `lock()`,
1503
  `try_lock()`, or `unlock()` on each argument. The sequence of calls does
1504
  not result in deadlock, but is otherwise unspecified.
1505
 
1506
- [*Note 3*: A deadlock avoidance algorithm such as try-and-back-off must
1507
  be used, but the specific algorithm is not specified to avoid
1508
  over-constraining implementations. — *end note*]
1509
 
1510
  If a call to `lock()` or `try_lock()` throws an exception, `unlock()` is
1511
  called for any argument that had been locked by a call to `lock()` or
@@ -1550,18 +1572,18 @@ template<class Callable, class... Args>
1550
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
1551
 
1552
  *Effects:* An execution of `call_once` that does not call its `func` is
1553
  a *passive* execution. An execution of `call_once` that calls its `func`
1554
  is an *active* execution. An active execution calls *INVOKE*(
1555
- std::forward\<Callable\>(func), std::forward\<Args\>(args)...). If such
1556
- a call to `func` throws an exception the execution is *exceptional*,
1557
- otherwise it is *returning*. An exceptional execution propagates the
1558
- exception to the caller of `call_once`. Among all executions of
1559
- `call_once` for any given `once_flag`: at most one is a returning
1560
- execution; if there is a returning execution, it is the last active
1561
- execution; and there are passive executions only if there is a returning
1562
- execution.
1563
 
1564
  [*Note 1*: Passive executions allow other threads to reliably observe
1565
  the results produced by the earlier returning execution. — *end note*]
1566
 
1567
  *Synchronization:* For any given `once_flag`: all active executions
 
1
  ## Mutual exclusion <a id="thread.mutex">[[thread.mutex]]</a>
2
 
3
+ ### General <a id="thread.mutex.general">[[thread.mutex.general]]</a>
4
+
5
+ Subclause [[thread.mutex]] provides mechanisms for mutual exclusion:
6
+ mutexes, locks, and call once. These mechanisms ease the production of
7
+ race-free programs [[intro.multithread]].
8
 
9
  ### Header `<mutex>` synopsis <a id="mutex.syn">[[mutex.syn]]</a>
10
 
11
  ``` cpp
12
  namespace std {
13
+ // [thread.mutex.class], class mutex
14
  class mutex;
15
+ // [thread.mutex.recursive], class recursive_mutex
16
  class recursive_mutex;
17
+ // [thread.timedmutex.class] class timed_mutex
18
  class timed_mutex;
19
+ // [thread.timedmutex.recursive], class recursive_timed_mutex
20
  class recursive_timed_mutex;
21
 
22
  struct defer_lock_t { explicit defer_lock_t() = default; };
23
  struct try_to_lock_t { explicit try_to_lock_t() = default; };
24
  struct adopt_lock_t { explicit adopt_lock_t() = default; };
25
 
26
  inline constexpr defer_lock_t defer_lock { };
27
  inline constexpr try_to_lock_t try_to_lock { };
28
  inline constexpr adopt_lock_t adopt_lock { };
29
 
30
+ // [thread.lock], locks
31
  template<class Mutex> class lock_guard;
32
  template<class... MutexTypes> class scoped_lock;
33
  template<class Mutex> class unique_lock;
34
 
35
  template<class Mutex>
36
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
37
 
38
+ // [thread.lock.algorithm], generic locking algorithms
39
  template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
40
  template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
41
 
42
  struct once_flag;
43
 
 
48
 
49
  ### Header `<shared_mutex>` synopsis <a id="shared.mutex.syn">[[shared.mutex.syn]]</a>
50
 
51
  ``` cpp
52
  namespace std {
53
+ // [thread.sharedmutex.class], class shared_mutex
54
  class shared_mutex;
55
+ // [thread.sharedtimedmutex.class], class shared_timed_mutex
56
  class shared_timed_mutex;
57
+ // [thread.lock.shared], class template shared_lock
58
  template<class Mutex> class shared_lock;
59
  template<class Mutex>
60
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
61
  }
62
  ```
 
73
  simultaneous ownership to one or many execution agents. Both recursive
74
  and non-recursive mutexes are supplied.
75
 
76
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
77
 
78
+ ##### General <a id="thread.mutex.requirements.mutex.general">[[thread.mutex.requirements.mutex.general]]</a>
79
+
80
  The *mutex types* are the standard library types `mutex`,
81
  `recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
82
  `shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
83
+ out in [[thread.mutex.requirements.mutex]]. In this description, `m`
84
+ denotes an object of a mutex type.
85
 
86
+ [*Note 1*: The mutex types meet the *Cpp17Lockable* requirements
87
+ [[thread.req.lockable.req]]. — *end note*]
88
 
89
  The mutex types meet *Cpp17DefaultConstructible* and
90
  *Cpp17Destructible*. If initialization of an object of a mutex type
91
  fails, an exception of type `system_error` is thrown. The mutex types
92
  are neither copyable nor movable.
 
104
  The implementation provides lock and unlock operations, as described
105
  below. For purposes of determining the existence of a data race, these
106
  behave as atomic operations [[intro.multithread]]. The lock and unlock
107
  operations on a single mutex appears to occur in a single total order.
108
 
109
+ [*Note 2*: This can be viewed as the modification order
110
  [[intro.multithread]] of the mutex. — *end note*]
111
 
112
+ [*Note 3*: Construction and destruction of an object of a mutex type
113
+ need not be thread-safe; other synchronization can be used to ensure
114
  that mutex objects are initialized and visible to other
115
  threads. — *end note*]
116
 
117
  The expression `m.lock()` is well-formed and has the following
118
  semantics:
 
122
  the mutex.
123
 
124
  *Effects:* Blocks the calling thread until ownership of the mutex can be
125
  obtained for the calling thread.
126
 
 
 
 
 
127
  *Synchronization:* Prior `unlock()` operations on the same object
128
  *synchronize with*[[intro.multithread]] this operation.
129
 
130
+ *Ensures:* The calling thread owns the mutex.
131
+
132
+ *Return type:* `void`.
133
+
134
  *Throws:* `system_error` when an exception is
135
  required [[thread.req.exception]].
136
 
137
  *Error conditions:*
138
 
 
158
  exchange [[atomics]]. — *end note*]
159
 
160
  An implementation should ensure that `try_lock()` does not consistently
161
  return `false` in the absence of contending mutex acquisitions.
162
 
 
 
 
 
 
163
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
164
  operations on the same object *synchronize with*[[intro.multithread]]
165
  this operation.
166
 
167
  [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
168
  `try_lock()`, the visibility rules are weak enough that little would be
169
  known about the state after a failure, even in the absence of spurious
170
  failures. — *end note*]
171
 
172
+ *Return type:* `bool`.
173
+
174
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
175
+
176
  *Throws:* Nothing.
177
 
178
  The expression `m.unlock()` is well-formed and has the following
179
  semantics:
180
 
 
216
  ownership semantics. If one thread owns a mutex object, attempts by
217
  another thread to acquire ownership of that object will fail (for
218
  `try_lock()`) or block (for `lock()`) until the owning thread has
219
  released ownership with a call to `unlock()`.
220
 
221
+ [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
222
  it is possible for another thread `B` to lock the same mutex, observe
223
  that it is no longer in use, unlock it, and destroy it, before thread
224
  `A` appears to have returned from its unlock call. Implementations are
225
  required to handle such scenarios correctly, as long as thread `A`
226
  doesn’t access the mutex after the unlock call returns. These cases
 
229
 
230
  The class `mutex` meets all of the mutex requirements
231
  [[thread.mutex.requirements]]. It is a standard-layout class
232
  [[class.prop]].
233
 
234
+ [*Note 5*: A program can deadlock if the thread that owns a `mutex`
235
  object calls `lock()` on that object. If the implementation can detect
236
  the deadlock, a `resource_deadlock_would_occur` error condition might be
237
  observed. — *end note*]
238
 
239
  The behavior of a program is undefined if it destroys a `mutex` object
 
288
  - it destroys a `recursive_mutex` object owned by any thread or
289
  - a thread terminates while owning a `recursive_mutex` object.
290
 
291
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
292
 
293
+ ##### General <a id="thread.timedmutex.requirements.general">[[thread.timedmutex.requirements.general]]</a>
294
+
295
  The *timed mutex types* are the standard library types `timed_mutex`,
296
  `recursive_timed_mutex`, and `shared_timed_mutex`. They meet the
297
  requirements set out below. In this description, `m` denotes an object
298
  of a mutex type, `rel_time` denotes an object of an instantiation of
299
  `duration` [[time.duration]], and `abs_time` denotes an object of an
300
  instantiation of `time_point` [[time.point]].
301
 
302
+ [*Note 1*: The timed mutex types meet the *Cpp17TimedLockable*
303
+ requirements [[thread.req.lockable.timed]]. — *end note*]
304
 
305
  The expression `m.try_lock_for(rel_time)` is well-formed and has the
306
  following semantics:
307
 
308
  *Preconditions:* If `m` is of type `timed_mutex` or
 
318
 
319
  [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
320
  will be obtained if the lock is available, but implementations are
321
  expected to make a strong effort to do so. — *end note*]
322
 
 
 
 
 
323
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
324
  operations on the same object *synchronize with*[[intro.multithread]]
325
  this operation.
326
 
327
+ *Return type:* `bool`.
328
+
329
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
330
+
331
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
332
 
333
  The expression `m.try_lock_until(abs_time)` is well-formed and has the
334
  following semantics:
335
 
 
344
 
345
  [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
346
  will be obtained if the lock is available, but implementations are
347
  expected to make a strong effort to do so. — *end note*]
348
 
 
 
 
 
349
  *Synchronization:* If `try_lock_until()` returns `true`, prior
350
  `unlock()` operations on the same object *synchronize
351
  with*[[intro.multithread]] this operation.
352
 
353
+ *Return type:* `bool`.
354
+
355
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
356
+
357
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
358
 
359
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
360
 
361
  ``` cpp
 
458
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
459
  - a thread terminates while owning a `recursive_timed_mutex` object.
460
 
461
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
462
 
463
+ ##### General <a id="thread.sharedmutex.requirements.general">[[thread.sharedmutex.requirements.general]]</a>
464
+
465
  The standard library types `shared_mutex` and `shared_timed_mutex` are
466
  *shared mutex types*. Shared mutex types meet the requirements of mutex
467
  types [[thread.mutex.requirements.mutex]] and additionally meet the
468
  requirements set out below. In this description, `m` denotes an object
469
  of a shared mutex type.
470
 
471
+ [*Note 1*: The shared mutex types meet the *Cpp17SharedLockable*
472
+ requirements [[thread.req.lockable.shared]]. — *end note*]
473
+
474
  In addition to the exclusive lock ownership mode specified in 
475
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
476
  *shared lock* ownership mode. Multiple execution agents can
477
  simultaneously hold a shared lock ownership of a shared mutex type. But
478
  no execution agent holds a shared lock while another execution agent
 
491
 
492
  *Effects:* Blocks the calling thread until shared ownership of the mutex
493
  can be obtained for the calling thread. If an exception is thrown then a
494
  shared lock has not been acquired for the current thread.
495
 
 
 
 
 
496
  *Synchronization:* Prior `unlock()` operations on the same object
497
  synchronize with [[intro.multithread]] this operation.
498
 
499
+ *Ensures:* The calling thread has a shared lock on the mutex.
500
+
501
+ *Return type:* `void`.
502
+
503
  *Throws:* `system_error` when an exception is
504
  required [[thread.req.exception]].
505
 
506
  *Error conditions:*
507
 
 
535
  calling thread without blocking. If shared ownership is not obtained,
536
  there is no effect and `try_lock_shared()` immediately returns. An
537
  implementation may fail to obtain the lock even if it is not held by any
538
  other thread.
539
 
 
 
 
 
 
540
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
541
  `unlock()` operations on the same object synchronize
542
  with [[intro.multithread]] this operation.
543
 
544
+ *Return type:* `bool`.
545
+
546
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
547
+
548
  *Throws:* Nothing.
549
 
550
  ##### Class `shared_mutex` <a id="thread.sharedmutex.class">[[thread.sharedmutex.class]]</a>
551
 
552
  ``` cpp
 
592
 
593
  `shared_mutex` may be a synonym for `shared_timed_mutex`.
594
 
595
  #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
596
 
597
+ ##### General <a id="thread.sharedtimedmutex.requirements.general">[[thread.sharedtimedmutex.requirements.general]]</a>
598
+
599
  The standard library type `shared_timed_mutex` is a *shared timed mutex
600
  type*. Shared timed mutex types meet the requirements of timed mutex
601
  types [[thread.timedmutex.requirements]], shared mutex types
602
  [[thread.sharedmutex.requirements]], and additionally meet the
603
  requirements set out below. In this description, `m` denotes an object
604
+ of a shared timed mutex type, `rel_time` denotes an object of an
605
  instantiation of `duration` [[time.duration]], and `abs_time` denotes an
606
  object of an instantiation of `time_point` [[time.point]].
607
 
608
+ [*Note 1*: The shared timed mutex types meet the
609
+ *Cpp17SharedTimedLockable* requirements
610
+ [[thread.req.lockable.shared.timed]]. — *end note*]
611
+
612
  The expression `m.try_lock_shared_for(rel_time)` is well-formed and has
613
  the following semantics:
614
 
615
  *Preconditions:* The calling thread has no ownership of the mutex.
616
 
 
627
  expected to make a strong effort to do so. — *end note*]
628
 
629
  If an exception is thrown then a shared lock has not been acquired for
630
  the current thread.
631
 
 
 
 
 
632
  *Synchronization:* If `try_lock_shared_for()` returns `true`, prior
633
  `unlock()` operations on the same object synchronize
634
  with [[intro.multithread]] this operation.
635
 
636
+ *Return type:* `bool`.
637
+
638
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
639
+
640
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
641
 
642
  The expression `m.try_lock_shared_until(abs_time)` is well-formed and
643
  has the following semantics:
644
 
 
656
  expected to make a strong effort to do so. — *end note*]
657
 
658
  If an exception is thrown then a shared lock has not been acquired for
659
  the current thread.
660
 
 
 
 
 
661
  *Synchronization:* If `try_lock_shared_until()` returns `true`, prior
662
  `unlock()` operations on the same object synchronize
663
  with [[intro.multithread]] this operation.
664
 
665
+ *Return type:* `bool`.
666
+
667
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
668
+
669
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
670
 
671
  ##### Class `shared_timed_mutex` <a id="thread.sharedtimedmutex.class">[[thread.sharedtimedmutex.class]]</a>
672
 
673
  ``` cpp
 
716
  - a thread terminates while possessing any ownership of a
717
  `shared_timed_mutex`.
718
 
719
  ### Locks <a id="thread.lock">[[thread.lock]]</a>
720
 
721
+ #### General <a id="thread.lock.general">[[thread.lock.general]]</a>
722
+
723
  A *lock* is an object that holds a reference to a lockable object and
724
  may unlock the lockable object during the lock’s destruction (such as
725
  when leaving block scope). An execution agent may use a lock to aid in
726
  managing ownership of a lockable object in an exception safe manner. A
727
  lock is said to *own* a lockable object if it is currently managing the
 
781
 
782
  ``` cpp
783
  explicit lock_guard(mutex_type& m);
784
  ```
785
 
 
 
 
786
  *Effects:* Initializes `pm` with `m`. Calls `m.lock()`.
787
 
788
  ``` cpp
789
  lock_guard(mutex_type& m, adopt_lock_t);
790
  ```
791
 
792
+ *Preconditions:* The calling thread holds a non-shared lock on `m`.
793
 
794
  *Effects:* Initializes `pm` with `m`.
795
 
796
  *Throws:* Nothing.
797
 
798
  ``` cpp
799
  ~lock_guard();
800
  ```
801
 
802
+ *Effects:* Equivalent to: `pm.unlock()`
803
 
804
  #### Class template `scoped_lock` <a id="thread.lock.scoped">[[thread.lock.scoped]]</a>
805
 
806
  ``` cpp
807
  namespace std {
808
  template<class... MutexTypes>
809
  class scoped_lock {
810
  public:
811
+ using mutex_type = see below; // Only if sizeof...(MutexTypes) == 1 is true
812
 
813
  explicit scoped_lock(MutexTypes&... m);
814
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
815
  ~scoped_lock();
816
 
 
826
  An object of type `scoped_lock` controls the ownership of lockable
827
  objects within a scope. A `scoped_lock` object maintains ownership of
828
  lockable objects throughout the `scoped_lock` object’s lifetime
829
  [[basic.life]]. The behavior of a program is undefined if the lockable
830
  objects referenced by `pm` do not exist for the entire lifetime of the
831
+ `scoped_lock` object.
832
+
833
+ - If `sizeof...(MutexTypes)` is one, let `Mutex` denote the sole type
834
+ constituting the pack `MutexTypes`. `Mutex` shall meet the
835
+ *Cpp17BasicLockable* requirements [[thread.req.lockable.basic]]. The
836
+ member *typedef-name* `mutex_type` denotes the same type as `Mutex`.
837
+ - Otherwise, all types in the template parameter pack `MutexTypes` shall
838
+ meet the *Cpp17Lockable* requirements [[thread.req.lockable.req]] and
839
+ there is no member `mutex_type`.
840
 
841
  ``` cpp
842
  explicit scoped_lock(MutexTypes&... m);
843
  ```
844
 
 
 
 
845
  *Effects:* Initializes `pm` with `tie(m...)`. Then if
846
  `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
847
  `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
848
  `lock(m...)`.
849
 
850
  ``` cpp
851
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
852
  ```
853
 
854
+ *Preconditions:* The calling thread holds a non-shared lock on each
855
+ element of `m`.
856
 
857
  *Effects:* Initializes `pm` with `tie(m...)`.
858
 
859
  *Throws:* Nothing.
860
 
 
865
  *Effects:* For all `i` in \[`0`, `sizeof...(MutexTypes)`),
866
  `get<i>(pm).unlock()`.
867
 
868
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
869
 
870
+ ##### General <a id="thread.lock.unique.general">[[thread.lock.unique.general]]</a>
871
+
872
  ``` cpp
873
  namespace std {
874
  template<class Mutex>
875
  class unique_lock {
876
  public:
 
916
 
917
  private:
918
  mutex_type* pm; // exposition only
919
  bool owns; // exposition only
920
  };
 
 
 
921
  }
922
  ```
923
 
924
  An object of type `unique_lock` controls the ownership of a lockable
925
  object within a scope. Ownership of the lockable object may be acquired
 
943
 
944
  ``` cpp
945
  unique_lock() noexcept;
946
  ```
947
 
948
+ *Ensures:* `pm == nullptr` and `owns == false`.
949
 
950
  ``` cpp
951
  explicit unique_lock(mutex_type& m);
952
  ```
953
 
 
 
 
954
  *Effects:* Calls `m.lock()`.
955
 
956
  *Ensures:* `pm == addressof(m)` and `owns == true`.
957
 
958
  ``` cpp
 
964
  ``` cpp
965
  unique_lock(mutex_type& m, try_to_lock_t);
966
  ```
967
 
968
  *Preconditions:* The supplied `Mutex` type meets the *Cpp17Lockable*
969
+ requirements [[thread.req.lockable.req]].
 
970
 
971
  *Effects:* Calls `m.try_lock()`.
972
 
973
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
974
  value returned by the call to `m.try_lock()`.
975
 
976
  ``` cpp
977
  unique_lock(mutex_type& m, adopt_lock_t);
978
  ```
979
 
980
+ *Preconditions:* The calling thread holds a non-shared lock on `m`.
981
 
982
  *Ensures:* `pm == addressof(m)` and `owns == true`.
983
 
984
  *Throws:* Nothing.
985
 
986
  ``` cpp
987
  template<class Clock, class Duration>
988
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
989
  ```
990
 
991
+ *Preconditions:* The supplied `Mutex` type meets the
 
992
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
993
 
994
  *Effects:* Calls `m.try_lock_until(abs_time)`.
995
 
996
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
 
999
  ``` cpp
1000
  template<class Rep, class Period>
1001
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
1002
  ```
1003
 
1004
+ *Preconditions:* The supplied `Mutex` type meets the
 
1005
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
1006
 
1007
  *Effects:* Calls `m.try_lock_for(rel_time)`.
1008
 
1009
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
 
1064
  *Preconditions:* The supplied `Mutex` meets the *Cpp17Lockable*
1065
  requirements [[thread.req.lockable.req]].
1066
 
1067
  *Effects:* As if by `pm->try_lock()`.
1068
 
1069
+ *Ensures:* `owns == res`, where `res` is the value returned by
1070
+ `pm->try_lock()`.
1071
 
1072
+ *Returns:* The value returned by `pm->try_lock()`.
 
1073
 
1074
  *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
1075
  an exception is required [[thread.req.exception]].
1076
 
1077
  *Error conditions:*
 
1087
  *Preconditions:* The supplied `Mutex` type meets the
1088
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
1089
 
1090
  *Effects:* As if by `pm->try_lock_until(abs_time)`.
1091
 
1092
+ *Ensures:* `owns == res`, where `res` is the value returned by
1093
+ `pm->try_lock_until(abs_time)`.
1094
 
1095
+ *Returns:* The value returned by `pm->try_lock_until(abs_time)`.
 
1096
 
1097
+ *Throws:* Any exception thrown by `pm->try_lock_until(abstime)`.
1098
+ `system_error` when an exception is required [[thread.req.exception]].
1099
 
1100
  *Error conditions:*
1101
 
1102
  - `operation_not_permitted` — if `pm` is `nullptr`.
1103
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
1110
  *Preconditions:* The supplied `Mutex` type meets the
1111
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
1112
 
1113
  *Effects:* As if by `pm->try_lock_for(rel_time)`.
1114
 
1115
+ *Ensures:* `owns == res`, where `res` is the value returned by
1116
+ `pm->try_lock_for(rel_time)`.
1117
 
1118
+ *Returns:* The value returned by `pm->try_lock_for(rel_time)`.
 
1119
 
1120
+ *Throws:* Any exception thrown by `pm->try_lock_for(rel_time)`.
1121
+ `system_error` when an exception is required [[thread.req.exception]].
1122
 
1123
  *Error conditions:*
1124
 
1125
  - `operation_not_permitted` — if `pm` is `nullptr`.
1126
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
1150
 
1151
  ``` cpp
1152
  mutex_type* release() noexcept;
1153
  ```
1154
 
 
 
1155
  *Ensures:* `pm == 0` and `owns == false`.
1156
 
1157
+ *Returns:* The previous value of `pm`.
1158
+
1159
  ``` cpp
1160
  template<class Mutex>
1161
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1162
  ```
1163
 
 
1183
 
1184
  *Returns:* `pm`.
1185
 
1186
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
1187
 
1188
+ ##### General <a id="thread.lock.shared.general">[[thread.lock.shared.general]]</a>
1189
+
1190
  ``` cpp
1191
  namespace std {
1192
  template<class Mutex>
1193
  class shared_lock {
1194
  public:
 
1232
 
1233
  private:
1234
  mutex_type* pm; // exposition only
1235
  bool owns; // exposition only
1236
  };
 
 
 
1237
  }
1238
  ```
1239
 
1240
  An object of type `shared_lock` controls the shared ownership of a
1241
  lockable object within a scope. Shared ownership of the lockable object
 
1243
  transferred, after acquisition, to another `shared_lock` object. Objects
1244
  of type `shared_lock` are not copyable but are movable. The behavior of
1245
  a program is undefined if the contained pointer `pm` is not null and the
1246
  lockable object pointed to by `pm` does not exist for the entire
1247
  remaining lifetime [[basic.life]] of the `shared_lock` object. The
1248
+ supplied `Mutex` type shall meet the *Cpp17SharedLockable* requirements
1249
+ [[thread.req.lockable.shared]].
1250
 
1251
+ [*Note 1*: `shared_lock<Mutex>` meets the *Cpp17Lockable* requirements
1252
+ [[thread.req.lockable.req]]. If `Mutex` meets the
1253
+ *Cpp17SharedTimedLockable* requirements
1254
+ [[thread.req.lockable.shared.timed]], `shared_lock<Mutex>` also meets
1255
+ the *Cpp17TimedLockable* requirements
1256
+ [[thread.req.lockable.timed]]. — *end note*]
1257
 
1258
  ##### Constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
1259
 
1260
  ``` cpp
1261
  shared_lock() noexcept;
 
1265
 
1266
  ``` cpp
1267
  explicit shared_lock(mutex_type& m);
1268
  ```
1269
 
 
 
 
1270
  *Effects:* Calls `m.lock_shared()`.
1271
 
1272
  *Ensures:* `pm == addressof(m)` and `owns == true`.
1273
 
1274
  ``` cpp
 
1279
 
1280
  ``` cpp
1281
  shared_lock(mutex_type& m, try_to_lock_t);
1282
  ```
1283
 
 
 
 
1284
  *Effects:* Calls `m.try_lock_shared()`.
1285
 
1286
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1287
  value returned by the call to `m.try_lock_shared()`.
1288
 
1289
  ``` cpp
1290
  shared_lock(mutex_type& m, adopt_lock_t);
1291
  ```
1292
 
1293
+ *Preconditions:* The calling thread holds a shared lock on `m`.
1294
 
1295
  *Ensures:* `pm == addressof(m)` and `owns == true`.
1296
 
1297
  ``` cpp
1298
  template<class Clock, class Duration>
1299
  shared_lock(mutex_type& m,
1300
  const chrono::time_point<Clock, Duration>& abs_time);
1301
  ```
1302
 
1303
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
1304
+ requirements [[thread.req.lockable.shared.timed]].
1305
 
1306
  *Effects:* Calls `m.try_lock_shared_until(abs_time)`.
1307
 
1308
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1309
  value returned by the call to `m.try_lock_shared_until(abs_time)`.
 
1312
  template<class Rep, class Period>
1313
  shared_lock(mutex_type& m,
1314
  const chrono::duration<Rep, Period>& rel_time);
1315
  ```
1316
 
1317
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
1318
+ requirements [[thread.req.lockable.shared.timed]].
1319
 
1320
  *Effects:* Calls `m.try_lock_shared_for(rel_time)`.
1321
 
1322
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
1323
  value returned by the call to `m.try_lock_shared_for(rel_time)`.
 
1368
  bool try_lock();
1369
  ```
1370
 
1371
  *Effects:* As if by `pm->try_lock_shared()`.
1372
 
 
 
1373
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1374
  to `pm->try_lock_shared()`.
1375
 
1376
+ *Returns:* The value returned by the call to `pm->try_lock_shared()`.
1377
+
1378
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
1379
  `system_error` when an exception is required [[thread.req.exception]].
1380
 
1381
  *Error conditions:*
1382
 
 
1386
  ``` cpp
1387
  template<class Clock, class Duration>
1388
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1389
  ```
1390
 
1391
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
1392
+ requirements [[thread.req.lockable.shared.timed]].
1393
+
1394
  *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
1395
 
 
 
 
1396
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1397
  to `pm->try_lock_shared_until(abs_time)`.
1398
 
1399
+ *Returns:* The value returned by the call to
1400
+ `pm->try_lock_shared_until(abs_time)`.
1401
+
1402
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
1403
  `system_error` when an exception is required [[thread.req.exception]].
1404
 
1405
  *Error conditions:*
1406
 
 
1410
  ``` cpp
1411
  template<class Rep, class Period>
1412
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1413
  ```
1414
 
1415
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
1416
+ requirements [[thread.req.lockable.shared.timed]].
1417
+
1418
  *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
1419
 
 
 
 
1420
  *Ensures:* `owns == res`, where `res` is the value returned by the call
1421
  to `pm->try_lock_shared_for(rel_time)`.
1422
 
1423
+ *Returns:* The value returned by the call to
1424
+ `pm->try_lock_shared_for(rel_time)`.
1425
+
1426
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
1427
  `system_error` when an exception is required [[thread.req.exception]].
1428
 
1429
  *Error conditions:*
1430
 
 
1456
 
1457
  ``` cpp
1458
  mutex_type* release() noexcept;
1459
  ```
1460
 
 
 
1461
  *Ensures:* `pm == nullptr` and `owns == false`.
1462
 
1463
+ *Returns:* The previous value of `pm`.
1464
+
1465
  ``` cpp
1466
  template<class Mutex>
1467
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1468
  ```
1469
 
 
1523
 
1524
  *Effects:* All arguments are locked via a sequence of calls to `lock()`,
1525
  `try_lock()`, or `unlock()` on each argument. The sequence of calls does
1526
  not result in deadlock, but is otherwise unspecified.
1527
 
1528
+ [*Note 3*: A deadlock avoidance algorithm such as try-and-back-off can
1529
  be used, but the specific algorithm is not specified to avoid
1530
  over-constraining implementations. — *end note*]
1531
 
1532
  If a call to `lock()` or `try_lock()` throws an exception, `unlock()` is
1533
  called for any argument that had been locked by a call to `lock()` or
 
1572
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
1573
 
1574
  *Effects:* An execution of `call_once` that does not call its `func` is
1575
  a *passive* execution. An execution of `call_once` that calls its `func`
1576
  is an *active* execution. An active execution calls *INVOKE*(
1577
+ std::forward\<Callable\>(func),
1578
+ std::forward\<Args\>(args)...) [[func.require]]. If such a call to
1579
+ `func` throws an exception the execution is *exceptional*, otherwise it
1580
+ is *returning*. An exceptional execution propagates the exception to the
1581
+ caller of `call_once`. Among all executions of `call_once` for any given
1582
+ `once_flag`: at most one is a returning execution; if there is a
1583
+ returning execution, it is the last active execution; and there are
1584
+ passive executions only if there is a returning execution.
1585
 
1586
  [*Note 1*: Passive executions allow other threads to reliably observe
1587
  the results produced by the earlier returning execution. — *end note*]
1588
 
1589
  *Synchronization:* For any given `once_flag`: all active executions