From Jason Turner

[thread.mutex]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpcn2rr9i_/{from.md → to.md} +457 -277
tmp/tmpcn2rr9i_/{from.md → to.md} RENAMED
@@ -2,48 +2,49 @@
2
 
3
  This section 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
  ``` cpp
8
  namespace std {
9
  class mutex;
10
  class recursive_mutex;
11
  class timed_mutex;
12
  class recursive_timed_mutex;
13
 
14
- struct defer_lock_t { };
15
- struct try_to_lock_t { };
16
- struct adopt_lock_t { };
17
 
18
- constexpr defer_lock_t defer_lock { };
19
- constexpr try_to_lock_t try_to_lock { };
20
- constexpr adopt_lock_t adopt_lock { };
21
 
22
  template <class Mutex> class lock_guard;
 
23
  template <class Mutex> class unique_lock;
24
 
25
  template <class Mutex>
26
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
27
 
28
  template <class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
29
  template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
30
 
31
- struct once_flag {
32
- constexpr once_flag() noexcept;
33
-
34
- once_flag(const once_flag&) = delete;
35
- once_flag& operator=(const once_flag&) = delete;
36
- };
37
 
38
  template<class Callable, class... Args>
39
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
40
  }
41
  ```
42
 
 
 
43
  ``` cpp
44
  namespace std {
 
45
  class shared_timed_mutex;
46
  template <class Mutex> class shared_lock;
47
  template <class Mutex>
48
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
49
  }
@@ -61,15 +62,15 @@ unlock. Mutexes can be either recursive or non-recursive, and can grant
61
  simultaneous ownership to one or many execution agents. Both recursive
62
  and non-recursive mutexes are supplied.
63
 
64
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
65
 
66
- The *mutex types* are the standard library types `std::mutex`,
67
- `std::recursive_mutex`, `std::timed_mutex`,
68
- `std::recursive_timed_mutex`, and `std::shared_timed_mutex`. They shall
69
- meet the requirements set out in this section. In this description, `m`
70
- denotes an object of a mutex type.
71
 
72
  The mutex types shall meet the `Lockable` requirements (
73
  [[thread.req.lockable.req]]).
74
 
75
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
@@ -82,37 +83,39 @@ functions of the mutex types shall be:
82
 
83
  - `resource_unavailable_try_again` — if any native handle type
84
  manipulated is not available.
85
  - `operation_not_permitted` — if the thread does not have the privilege
86
  to perform the operation.
87
- - `device_or_resource_busy` — if any native handle type manipulated is
88
- already locked.
89
  - `invalid_argument` — if any native handle type manipulated as part of
90
  mutex construction is incorrect.
91
 
92
  The implementation shall provide lock and unlock operations, as
93
  described below. For purposes of determining the existence of a data
94
  race, these behave as atomic operations ([[intro.multithread]]). The
95
  lock and unlock operations on a single mutex shall appear to occur in a
96
- single total order. this can be viewed as the modification order (
97
- [[intro.multithread]]) of the mutex. Construction and destruction of an
98
- object of a mutex type need not be thread-safe; other synchronization
99
- should be used to ensure that mutex objects are initialized and visible
100
- to other threads.
 
 
 
 
101
 
102
  The expression `m.lock()` shall be well-formed and have the following
103
  semantics:
104
 
105
- *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
106
- `std::shared_timed_mutex`, the calling thread does not own the mutex.
107
 
108
  *Effects:* Blocks the calling thread until ownership of the mutex can be
109
  obtained for the calling thread.
110
 
111
- The calling thread owns the mutex.
112
 
113
- *Return type:* `void`
114
 
115
  *Synchronization:* Prior `unlock()` operations on the same object shall
116
  *synchronize with* ([[intro.multithread]]) this operation.
117
 
118
  *Throws:* `system_error` when an exception is
@@ -122,51 +125,53 @@ required ([[thread.req.exception]]).
122
 
123
  - `operation_not_permitted` — if the thread does not have the privilege
124
  to perform the operation.
125
  - `resource_deadlock_would_occur` — if the implementation detects that a
126
  deadlock would occur.
127
- - `device_or_resource_busy` — if the mutex is already locked and
128
- blocking is not possible.
129
 
130
  The expression `m.try_lock()` shall be well-formed and have the
131
  following semantics:
132
 
133
- *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
134
- `std::shared_timed_mutex`, the calling thread does not own the mutex.
135
 
136
  *Effects:* Attempts to obtain ownership of the mutex for the calling
137
  thread without blocking. If ownership is not obtained, there is no
138
  effect and `try_lock()` immediately returns. An implementation may fail
139
- to obtain the lock even if it is not held by any other thread. This
140
- spurious failure is normally uncommon, but allows interesting
141
- implementations based on a simple compare and exchange
142
- (Clause  [[atomics]]). An implementation should ensure that `try_lock()`
143
- does not consistently return `false` in the absence of contending mutex
144
- acquisitions.
145
 
146
- *Return type:* `bool`
 
 
 
 
 
 
 
147
 
148
  *Returns:* `true` if ownership of the mutex was obtained for the calling
149
  thread, otherwise `false`.
150
 
151
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
152
  operations on the same object *synchronize
153
- with* ([[intro.multithread]]) this operation. Since `lock()` does not
154
- synchronize with a failed subsequent `try_lock()`, the visibility rules
155
- are weak enough that little would be known about the state after a
156
- failure, even in the absence of spurious failures.
 
 
157
 
158
  *Throws:* Nothing.
159
 
160
  The expression `m.unlock()` shall be well-formed and have the following
161
  semantics:
162
 
163
- The calling thread shall own the mutex.
164
 
165
  *Effects:* Releases the calling thread’s ownership of the mutex.
166
 
167
- *Return type:* `void`
168
 
169
  *Synchronization:* This operation synchronizes
170
  with ([[intro.multithread]]) subsequent lock operations that obtain
171
  ownership on the same object.
172
 
@@ -186,11 +191,11 @@ namespace std {
186
 
187
  void lock();
188
  bool try_lock();
189
  void unlock();
190
 
191
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
192
  native_handle_type native_handle(); // See~[thread.req.native]
193
  };
194
  }
195
  ```
196
 
@@ -198,26 +203,27 @@ The class `mutex` provides a non-recursive mutex with exclusive
198
  ownership semantics. If one thread owns a mutex object, attempts by
199
  another thread to acquire ownership of that object will fail (for
200
  `try_lock()`) or block (for `lock()`) until the owning thread has
201
  released ownership with a call to `unlock()`.
202
 
203
- After a thread `A` has called `unlock()`, releasing a mutex, it is
204
- possible for another thread `B` to lock the same mutex, observe that it
205
- is no longer in use, unlock it, and destroy it, before thread `A`
206
- appears to have returned from its unlock call. Implementations are
207
  required to handle such scenarios correctly, as long as thread `A`
208
  doesn’t access the mutex after the unlock call returns. These cases
209
  typically occur when a reference-counted object contains a mutex that is
210
- used to protect the reference count.
211
 
212
- The class `mutex` shall satisfy all the `Mutex` requirements (
213
  [[thread.mutex.requirements]]). It shall be a standard-layout class
214
  (Clause  [[class]]).
215
 
216
- A program may deadlock if the thread that owns a `mutex` object calls
217
- `lock()` on that object. If the implementation can detect the deadlock,
218
- a `resource_deadlock_would_occur` error condition may be observed.
 
219
 
220
  The behavior of a program is undefined if it destroys a `mutex` object
221
  owned by any thread or a thread terminates while owning a `mutex`
222
  object.
223
 
@@ -235,11 +241,11 @@ namespace std {
235
 
236
  void lock();
237
  bool try_lock() noexcept;
238
  void unlock();
239
 
240
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
241
  native_handle_type native_handle(); // See~[thread.req.native]
242
  };
243
  }
244
  ```
245
 
@@ -247,13 +253,13 @@ The class `recursive_mutex` provides a recursive mutex with exclusive
247
  ownership semantics. If one thread owns a `recursive_mutex` object,
248
  attempts by another thread to acquire ownership of that object will fail
249
  (for `try_lock()`) or block (for `lock()`) until the first thread has
250
  completely released ownership.
251
 
252
- The class `recursive_mutex` shall satisfy all the Mutex requirements (
253
- [[thread.mutex.requirements]]). It shall be a standard-layout class
254
- (Clause  [[class]]).
255
 
256
  A thread that owns a `recursive_mutex` object may acquire additional
257
  levels of ownership by calling `lock()` or `try_lock()` on that object.
258
  It is unspecified how many levels of ownership may be acquired by a
259
  single thread. If a thread has already acquired the maximum level of
@@ -269,38 +275,39 @@ The behavior of a program is undefined if:
269
  - it destroys a `recursive_mutex` object owned by any thread or
270
  - a thread terminates while owning a `recursive_mutex` object.
271
 
272
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
273
 
274
- The *timed mutex types* are the standard library types
275
- `std::timed_mutex`, `std::recursive_timed_mutex`, and
276
- `std::shared_timed_mutex`. They shall meet the requirements set out
277
- below. In this description, `m` denotes an object of a mutex type,
278
- `rel_time` denotes an object of an instantiation of `duration` (
279
- [[time.duration]]), and `abs_time` denotes an object of an instantiation
280
- of `time_point` ([[time.point]]).
281
 
282
  The timed mutex types shall meet the `TimedLockable` requirements (
283
  [[thread.req.lockable.timed]]).
284
 
285
  The expression `m.try_lock_for(rel_time)` shall be well-formed and have
286
  the following semantics:
287
 
288
- If `m` is of type `std::timed_mutex` or `std::shared_timed_mutex`, the
289
  calling thread does not own the mutex.
290
 
291
  *Effects:* The function attempts to obtain ownership of the mutex within
292
  the relative timeout ([[thread.req.timing]]) specified by `rel_time`.
293
  If the time specified by `rel_time` is less than or equal to
294
  `rel_time.zero()`, the function attempts to obtain ownership without
295
  blocking (as if by calling `try_lock()`). The function shall return
296
  within the timeout specified by `rel_time` only if it has obtained
297
- ownership of the mutex object. As with `try_lock()`, there is no
298
- guarantee that ownership will be obtained if the lock is available, but
299
- implementations are expected to make a strong effort to do so.
300
 
301
- *Return type:* `bool`
 
 
 
 
302
 
303
  *Returns:* `true` if ownership was obtained, otherwise `false`.
304
 
305
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
306
  operations on the same object *synchronize
@@ -309,23 +316,24 @@ with* ([[intro.multithread]]) this operation.
309
  *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
310
 
311
  The expression `m.try_lock_until(abs_time)` shall be well-formed and
312
  have the following semantics:
313
 
314
- *Requires:* If `m` is of type `std::timed_mutex` or
315
- `std::shared_timed_mutex`, the calling thread does not own the mutex.
316
 
317
  *Effects:* The function attempts to obtain ownership of the mutex. If
318
  `abs_time` has already passed, the function attempts to obtain ownership
319
  without blocking (as if by calling `try_lock()`). The function shall
320
  return before the absolute timeout ([[thread.req.timing]]) specified by
321
- `abs_time` only if it has obtained ownership of the mutex object. As
322
- with `try_lock()`, there is no guarantee that ownership will be obtained
323
- if the lock is available, but implementations are expected to make a
324
- strong effort to do so.
325
 
326
- *Return type:* `bool`
 
 
 
 
327
 
328
  *Returns:* `true` if ownership was obtained, otherwise `false`.
329
 
330
  *Synchronization:* If `try_lock_until()` returns `true`, prior
331
  `unlock()` operations on the same object *synchronize
@@ -351,11 +359,11 @@ namespace std {
351
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
352
  template <class Clock, class Duration>
353
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
354
  void unlock();
355
 
356
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
357
  native_handle_type native_handle(); // See~[thread.req.native]
358
  };
359
  }
360
  ```
361
 
@@ -365,11 +373,11 @@ by another thread to acquire ownership of that object will fail (for
365
  `try_lock()`) or block (for `lock()`, `try_lock_for()`, and
366
  `try_lock_until()`) until the owning thread has released ownership with
367
  a call to `unlock()` or the call to `try_lock_for()` or
368
  `try_lock_until()` times out (having failed to obtain ownership).
369
 
370
- The class `timed_mutex` shall satisfy all of the `TimedMutex`
371
  requirements ([[thread.timedmutex.requirements]]). It shall be a
372
  standard-layout class (Clause  [[class]]).
373
 
374
  The behavior of a program is undefined if:
375
 
@@ -397,11 +405,11 @@ namespace std {
397
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
398
  template <class Clock, class Duration>
399
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
400
  void unlock();
401
 
402
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
403
  native_handle_type native_handle(); // See~[thread.req.native]
404
  };
405
  }
406
  ```
407
 
@@ -411,11 +419,11 @@ exclusive ownership semantics. If one thread owns a
411
  ownership of that object will fail (for `try_lock()`) or block (for
412
  `lock()`, `try_lock_for()`, and `try_lock_until()`) until the owning
413
  thread has completely released ownership or the call to `try_lock_for()`
414
  or `try_lock_until()` times out (having failed to obtain ownership).
415
 
416
- The class `recursive_timed_mutex` shall satisfy all of the `TimedMutex`
417
  requirements ([[thread.timedmutex.requirements]]). It shall be a
418
  standard-layout class (Clause  [[class]]).
419
 
420
  A thread that owns a `recursive_timed_mutex` object may acquire
421
  additional levels of ownership by calling `lock()`, `try_lock()`,
@@ -433,20 +441,17 @@ the object be acquired by another thread.
433
  The behavior of a program is undefined if:
434
 
435
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
436
  - a thread terminates while owning a `recursive_timed_mutex` object.
437
 
438
- #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
439
 
440
- The standard library type `std::shared_timed_mutex` is a *shared timed
441
- mutex type*. Shared timed mutex types shall meet the requirements of
442
- timed mutex types ([[thread.timedmutex.requirements]]), and
443
- additionally shall meet the requirements set out below. In this
444
- description, `m` denotes an object of a mutex type, `rel_type` denotes
445
- an object of an instantiation of `duration` ([[time.duration]]), and
446
- `abs_time` denotes an object of an instantiation of `time_point` (
447
- [[time.point]]).
448
 
449
  In addition to the exclusive lock ownership mode specified in 
450
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
451
  *shared lock* ownership mode. Multiple execution agents can
452
  simultaneously hold a shared lock ownership of a shared mutex type. But
@@ -466,28 +471,26 @@ following semantics:
466
 
467
  *Effects:* Blocks the calling thread until shared ownership of the mutex
468
  can be obtained for the calling thread. If an exception is thrown then a
469
  shared lock shall not have been acquired for the current thread.
470
 
471
- The calling thread has a shared lock on the mutex.
472
 
473
  *Return type:* `void`.
474
 
475
  *Synchronization:* Prior `unlock()` operations on the same object shall
476
  synchronize with ([[intro.multithread]]) this operation.
477
 
478
- *Throws:* `system_error` when an exception is required
479
-  ([[thread.req.exception]]).
480
 
481
  *Error conditions:*
482
 
483
  - `operation_not_permitted` — if the thread does not have the privilege
484
  to perform the operation.
485
  - `resource_deadlock_would_occur` — if the implementation detects that a
486
  deadlock would occur.
487
- - `device_or_resource_busy` — if the mutex is already locked and
488
- blocking is not possible.
489
 
490
  The expression `m.unlock_shared()` shall be well-formed and have the
491
  following semantics:
492
 
493
  *Requires:* The calling thread shall hold a shared lock on the mutex.
@@ -518,15 +521,71 @@ other thread.
518
 
519
  *Returns:* `true` if the shared ownership lock was acquired, `false`
520
  otherwise.
521
 
522
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
523
- `unlock()` operations on the same object synchronize with
524
-  ([[intro.multithread]]) this operation.
525
 
526
  *Throws:* Nothing.
527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  The expression `m.try_lock_shared_for(rel_time)` shall be well-formed
529
  and have the following semantics:
530
 
531
  *Requires:* The calling thread has no ownership of the mutex.
532
 
@@ -534,14 +593,17 @@ and have the following semantics:
534
  thread within the relative timeout ([[thread.req.timing]]) specified by
535
  `rel_time`. If the time specified by `rel_time` is less than or equal to
536
  `rel_time.zero()`, the function attempts to obtain ownership without
537
  blocking (as if by calling `try_lock_shared()`). The function shall
538
  return within the timeout specified by `rel_time` only if it has
539
- obtained shared ownership of the mutex object. As with `try_lock()`,
540
- there is no guarantee that ownership will be obtained if the lock is
541
- available, but implementations are expected to make a strong effort to
542
- do so. If an exception is thrown then a shared lock shall not have been
 
 
 
543
  acquired for the current thread.
544
 
545
  *Return type:* `bool`.
546
 
547
  *Returns:* `true` if the shared lock was acquired, `false` otherwise.
@@ -560,14 +622,17 @@ and have the following semantics:
560
  *Effects:* The function attempts to obtain shared ownership of the
561
  mutex. If `abs_time` has already passed, the function attempts to obtain
562
  shared ownership without blocking (as if by calling
563
  `try_lock_shared()`). The function shall return before the absolute
564
  timeout ([[thread.req.timing]]) specified by `abs_time` only if it has
565
- obtained shared ownership of the mutex object. As with `try_lock()`,
566
- there is no guarantee that ownership will be obtained if the lock is
567
- available, but implementations are expected to make a strong effort to
568
- do so. If an exception is thrown then a shared lock shall not have been
 
 
 
569
  acquired for the current thread.
570
 
571
  *Return type:* `bool`.
572
 
573
  *Returns:* `true` if the shared lock was acquired, `false` otherwise.
@@ -614,14 +679,13 @@ namespace std {
614
  ```
615
 
616
  The class `shared_timed_mutex` provides a non-recursive mutex with
617
  shared ownership semantics.
618
 
619
- The class `shared_timed_mutex` shall satisfy all of the
620
- `SharedTimedMutex` requirements (
621
- [[thread.sharedtimedmutex.requirements]]). It shall be a standard-layout
622
- class (Clause  [[class]]).
623
 
624
  The behavior of a program is undefined if:
625
 
626
  - it destroys a `shared_timed_mutex` object owned by any thread,
627
  - a thread attempts to recursively gain any ownership of a
@@ -635,13 +699,15 @@ A *lock* is an object that holds a reference to a lockable object and
635
  may unlock the lockable object during the lock’s destruction (such as
636
  when leaving block scope). An execution agent may use a lock to aid in
637
  managing ownership of a lockable object in an exception safe manner. A
638
  lock is said to *own* a lockable object if it is currently managing the
639
  ownership of that lockable object for an execution agent. A lock does
640
- not manage the lifetime of the lockable object it references. Locks are
641
- intended to ease the burden of unlocking the lockable object under both
642
- normal and exceptional circumstances.
 
 
643
 
644
  Some lock constructors take tag types which describe what should be done
645
  with the lockable object during the lock’s construction.
646
 
647
  ``` cpp
@@ -650,35 +716,37 @@ namespace std {
650
  struct try_to_lock_t { }; // try to acquire ownership of the mutex
651
  // without blocking
652
  struct adopt_lock_t { }; // assume the calling thread has already
653
  // obtained mutex ownership and manage it
654
 
655
- constexpr defer_lock_t defer_lock { };
656
- constexpr try_to_lock_t try_to_lock { };
657
- constexpr adopt_lock_t adopt_lock { };
658
  }
659
  ```
660
 
661
  #### Class template `lock_guard` <a id="thread.lock.guard">[[thread.lock.guard]]</a>
662
 
663
  ``` cpp
664
  namespace std {
665
  template <class Mutex>
666
  class lock_guard {
667
  public:
668
- typedef Mutex mutex_type;
669
 
670
  explicit lock_guard(mutex_type& m);
671
  lock_guard(mutex_type& m, adopt_lock_t);
672
  ~lock_guard();
673
 
674
- lock_guard(lock_guard const&) = delete;
675
- lock_guard& operator=(lock_guard const&) = delete;
676
 
677
  private:
678
  mutex_type& pm; // exposition only
679
  };
 
 
680
  }
681
  ```
682
 
683
  An object of type `lock_guard` controls the ownership of a lockable
684
  object within a scope. A `lock_guard` object maintains ownership of a
@@ -690,43 +758,107 @@ object referenced by `pm` does not exist for the entire lifetime of the
690
 
691
  ``` cpp
692
  explicit lock_guard(mutex_type& m);
693
  ```
694
 
695
- If `mutex_type` is not a recursive mutex, the calling thread does not
696
- own the mutex `m`.
697
 
698
- *Effects:* `m.lock()`
699
 
700
- `&pm == &m`
701
 
702
  ``` cpp
703
  lock_guard(mutex_type& m, adopt_lock_t);
704
  ```
705
 
706
- The calling thread owns the mutex `m`.
707
 
708
- `&pm == &m`
709
 
710
  *Throws:* Nothing.
711
 
712
  ``` cpp
713
  ~lock_guard();
714
  ```
715
 
716
- *Effects:* `pm.unlock()`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717
 
718
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
719
 
720
  ``` cpp
721
  namespace std {
722
  template <class Mutex>
723
  class unique_lock {
724
  public:
725
- typedef Mutex mutex_type;
726
 
727
- // [thread.lock.unique.cons], construct/copy/destroy:
728
  unique_lock() noexcept;
729
  explicit unique_lock(mutex_type& m);
730
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
731
  unique_lock(mutex_type& m, try_to_lock_t);
732
  unique_lock(mutex_type& m, adopt_lock_t);
@@ -734,41 +866,43 @@ namespace std {
734
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
735
  template <class Rep, class Period>
736
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
737
  ~unique_lock();
738
 
739
- unique_lock(unique_lock const&) = delete;
740
- unique_lock& operator=(unique_lock const&) = delete;
741
 
742
  unique_lock(unique_lock&& u) noexcept;
743
  unique_lock& operator=(unique_lock&& u);
744
 
745
- // [thread.lock.unique.locking], locking:
746
  void lock();
747
  bool try_lock();
748
 
749
  template <class Rep, class Period>
750
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
751
  template <class Clock, class Duration>
752
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
753
 
754
  void unlock();
755
 
756
- // [thread.lock.unique.mod], modifiers:
757
  void swap(unique_lock& u) noexcept;
758
  mutex_type* release() noexcept;
759
 
760
- // [thread.lock.unique.obs], observers:
761
  bool owns_lock() const noexcept;
762
  explicit operator bool () const noexcept;
763
  mutex_type* mutex() const noexcept;
764
 
765
  private:
766
  mutex_type* pm; // exposition only
767
  bool owns; // exposition only
768
  };
769
 
 
 
770
  template <class Mutex>
771
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
772
  }
773
  ```
774
 
@@ -781,15 +915,16 @@ program is undefined if the contained pointer `pm` is not null and the
781
  lockable object pointed to by `pm` does not exist for the entire
782
  remaining lifetime ([[basic.life]]) of the `unique_lock` object. The
783
  supplied `Mutex` type shall meet the `BasicLockable` requirements (
784
  [[thread.req.lockable.basic]]).
785
 
786
- `unique_lock<Mutex>` meets the `BasicLockable` requirements. If `Mutex`
787
- meets the `Lockable` requirements ([[thread.req.lockable.req]]),
788
- `unique_lock<Mutex>` also meets the `Lockable` requirements; if `Mutex`
789
- meets the `TimedLockable` requirements ([[thread.req.lockable.timed]]),
790
- `unique_lock<Mutex>` also meets the `TimedLockable` requirements.
 
791
 
792
  ##### `unique_lock` constructors, destructor, and assignment <a id="thread.lock.unique.cons">[[thread.lock.unique.cons]]</a>
793
 
794
  ``` cpp
795
  unique_lock() noexcept;
@@ -801,81 +936,81 @@ unique_lock() noexcept;
801
 
802
  ``` cpp
803
  explicit unique_lock(mutex_type& m);
804
  ```
805
 
806
- If `mutex_type` is not a recursive mutex the calling thread does not own
807
- the mutex.
808
 
809
  *Effects:* Constructs an object of type `unique_lock` and calls
810
  `m.lock()`.
811
 
812
- *Postconditions:* `pm == &m` and `owns == true`.
813
 
814
  ``` cpp
815
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
816
  ```
817
 
818
  *Effects:* Constructs an object of type `unique_lock`.
819
 
820
- *Postconditions:* `pm == &m` and `owns == false`.
821
 
822
  ``` cpp
823
  unique_lock(mutex_type& m, try_to_lock_t);
824
  ```
825
 
826
- The supplied `Mutex` type shall meet the `Lockable`
827
  requirements ([[thread.req.lockable.req]]). If `mutex_type` is not a
828
  recursive mutex the calling thread does not own the mutex.
829
 
830
  *Effects:* Constructs an object of type `unique_lock` and calls
831
  `m.try_lock()`.
832
 
833
- *Postconditions:* `pm == &m` and `owns == res`, where `res` is the value
834
- returned by the call to `m.try_lock()`.
835
 
836
  ``` cpp
837
  unique_lock(mutex_type& m, adopt_lock_t);
838
  ```
839
 
840
- The calling thread own the mutex.
841
 
842
  *Effects:* Constructs an object of type `unique_lock`.
843
 
844
- *Postconditions:* `pm == &m` and `owns == true`.
845
 
846
  *Throws:* Nothing.
847
 
848
  ``` cpp
849
  template <class Clock, class Duration>
850
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
851
  ```
852
 
853
- If `mutex_type` is not a recursive mutex the calling thread does not own
854
- the mutex. The supplied `Mutex` type shall meet the `TimedLockable`
855
- requirements ([[thread.req.lockable.timed]]).
856
 
857
  *Effects:* Constructs an object of type `unique_lock` and calls
858
  `m.try_lock_until(abs_time)`.
859
 
860
- *Postconditions:* `pm == &m` and `owns == res`, where `res` is the value
861
- returned by the call to `m.try_lock_until(abs_time)`.
862
 
863
  ``` cpp
864
  template <class Rep, class Period>
865
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
866
  ```
867
 
868
- If `mutex_type` is not a recursive mutex the calling thread does not own
869
- the mutex. The supplied `Mutex` type shall meet the `TimedLockable`
870
- requirements ([[thread.req.lockable.timed]]).
871
 
872
  *Effects:* Constructs an object of type `unique_lock` and calls
873
  `m.try_lock_for(rel_time)`.
874
 
875
- *Postconditions:* `pm == &m` and `owns == res`, where `res` is the value
876
- returned by the call to `m.try_lock_for(rel_time)`.
877
 
878
  ``` cpp
879
  unique_lock(unique_lock&& u) noexcept;
880
  ```
881
 
@@ -891,13 +1026,13 @@ unique_lock& operator=(unique_lock&& u);
891
 
892
  *Postconditions:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is
893
  the state of `u` just prior to this construction), `u.pm == 0` and
894
  `u.owns == false`.
895
 
896
- With a recursive mutex it is possible for both `*this` and `u` to own
897
- the same mutex before the assignment. In this case, `*this` will own the
898
- mutex after the assignment and `u` will not.
899
 
900
  *Throws:* Nothing.
901
 
902
  ``` cpp
903
  ~unique_lock();
@@ -909,96 +1044,104 @@ mutex after the assignment and `u` will not.
909
 
910
  ``` cpp
911
  void lock();
912
  ```
913
 
914
- *Effects:* `pm->lock()`
915
 
916
- `owns == true`
917
 
918
- *Throws:* Any exception thrown by `pm->lock()`. `system_error` if an
919
- exception is required ([[thread.req.exception]]). `system_error` with
920
- an error condition of `operation_not_permitted` if `pm` is 0.
921
- `system_error` with an error condition of
922
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
923
 
924
  ``` cpp
925
  bool try_lock();
926
  ```
927
 
928
- The supplied `Mutex` shall meet the `Lockable`
929
  requirements ([[thread.req.lockable.req]]).
930
 
931
- *Effects:* `pm->try_lock()`
932
 
933
  *Returns:* The value returned by the call to `try_lock()`.
934
 
935
- `owns == res`, where `res` is the value returned by the call to
936
- `try_lock()`.
937
 
938
- *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` if an
939
- exception is required ([[thread.req.exception]]). `system_error` with
940
- an error condition of `operation_not_permitted` if `pm` is 0.
941
- `system_error` with an error condition of
942
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
943
 
944
  ``` cpp
945
  template <class Clock, class Duration>
946
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
947
  ```
948
 
949
  *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
950
  requirements ([[thread.req.lockable.timed]]).
951
 
952
- *Effects:* `pm->try_lock_until(abs_time)`
953
 
954
  *Returns:* The value returned by the call to `try_lock_until(abs_time)`.
955
 
956
- `owns == res`, where `res` is the value returned by the call to
957
- `try_lock_until(abs_time)`.
958
 
959
  *Throws:* Any exception thrown by `pm->try_lock_until()`. `system_error`
960
- if an exception is required ([[thread.req.exception]]). `system_error`
961
- with an error condition of `operation_not_permitted` if `pm` is 0.
962
- `system_error` with an error condition of
963
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
964
 
965
  ``` cpp
966
  template <class Rep, class Period>
967
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
968
  ```
969
 
970
  *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
971
  requirements ([[thread.req.lockable.timed]]).
972
 
973
- *Effects:* `pm->try_lock_for(rel_time)`.
974
 
975
  *Returns:* The value returned by the call to `try_lock_until(rel_time)`.
976
 
977
- `owns == res`, where `res` is the value returned by the call to
978
- `try_lock_for(rel_time)`.
979
 
980
  *Throws:* Any exception thrown by `pm->try_lock_for()`. `system_error`
981
- if an exception is required ([[thread.req.exception]]). `system_error`
982
- with an error condition of `operation_not_permitted` if `pm` is 0.
983
- `system_error` with an error condition of
984
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
985
 
986
  ``` cpp
987
  void unlock();
988
  ```
989
 
990
- *Effects:* `pm->unlock()`
991
 
992
- `owns == false`
993
 
994
  *Throws:* `system_error` when an exception is
995
  required ([[thread.req.exception]]).
996
 
997
  *Error conditions:*
998
 
999
- - `operation_not_permitted` — if on entry `owns` is false.
1000
 
1001
  ##### `unique_lock` modifiers <a id="thread.lock.unique.mod">[[thread.lock.unique.mod]]</a>
1002
 
1003
  ``` cpp
1004
  void swap(unique_lock& u) noexcept;
@@ -1017,43 +1160,42 @@ mutex_type* release() noexcept;
1017
  ``` cpp
1018
  template <class Mutex>
1019
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1020
  ```
1021
 
1022
- *Effects:* `x.swap(y)`
1023
 
1024
  ##### `unique_lock` observers <a id="thread.lock.unique.obs">[[thread.lock.unique.obs]]</a>
1025
 
1026
  ``` cpp
1027
  bool owns_lock() const noexcept;
1028
  ```
1029
 
1030
- *Returns:* `owns`
1031
 
1032
  ``` cpp
1033
  explicit operator bool() const noexcept;
1034
  ```
1035
 
1036
- *Returns:* `owns`
1037
 
1038
  ``` cpp
1039
  mutex_type *mutex() const noexcept;
1040
  ```
1041
 
1042
- *Returns:* `pm`
1043
 
1044
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
1045
 
1046
  ``` cpp
1047
  namespace std {
1048
-
1049
  template <class Mutex>
1050
  class shared_lock {
1051
  public:
1052
- typedef Mutex mutex_type;
1053
 
1054
- // Shared locking
1055
  shared_lock() noexcept;
1056
  explicit shared_lock(mutex_type& m); // blocking
1057
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
1058
  shared_lock(mutex_type& m, try_to_lock_t);
1059
  shared_lock(mutex_type& m, adopt_lock_t);
@@ -1063,42 +1205,44 @@ public:
1063
  template <class Rep, class Period>
1064
  shared_lock(mutex_type& m,
1065
  const chrono::duration<Rep, Period>& rel_time);
1066
  ~shared_lock();
1067
 
1068
- shared_lock(shared_lock const&) = delete;
1069
- shared_lock& operator=(shared_lock const&) = delete;
1070
 
1071
  shared_lock(shared_lock&& u) noexcept;
1072
  shared_lock& operator=(shared_lock&& u) noexcept;
1073
 
 
1074
  void lock(); // blocking
1075
  bool try_lock();
1076
  template <class Rep, class Period>
1077
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1078
  template <class Clock, class Duration>
1079
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1080
  void unlock();
1081
 
1082
- // Setters
1083
  void swap(shared_lock& u) noexcept;
1084
  mutex_type* release() noexcept;
1085
 
1086
- // Getters
1087
  bool owns_lock() const noexcept;
1088
  explicit operator bool () const noexcept;
1089
  mutex_type* mutex() const noexcept;
1090
 
1091
  private:
1092
  mutex_type* pm; // exposition only
1093
  bool owns; // exposition only
1094
  };
1095
 
 
 
1096
  template <class Mutex>
1097
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1098
-
1099
- } // std
1100
  ```
1101
 
1102
  An object of type `shared_lock` controls the shared ownership of a
1103
  lockable object within a scope. Shared ownership of the lockable object
1104
  may be acquired at construction or after construction, and may be
@@ -1108,12 +1252,12 @@ a program is undefined if the contained pointer `pm` is not null and the
1108
  lockable object pointed to by `pm` does not exist for the entire
1109
  remaining lifetime ([[basic.life]]) of the `shared_lock` object. The
1110
  supplied `Mutex` type shall meet the shared mutex requirements (
1111
  [[thread.sharedtimedmutex.requirements]]).
1112
 
1113
- `shared_lock<Mutex>` meets the `TimedLockable` requirements (
1114
- [[thread.req.lockable.timed]]).
1115
 
1116
  ##### `shared_lock` constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
1117
 
1118
  ``` cpp
1119
  shared_lock() noexcept;
@@ -1131,19 +1275,19 @@ explicit shared_lock(mutex_type& m);
1131
  mode.
1132
 
1133
  *Effects:* Constructs an object of type `shared_lock` and calls
1134
  `m.lock_shared()`.
1135
 
1136
- *Postconditions:* `pm == &m` and `owns == true`.
1137
 
1138
  ``` cpp
1139
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
1140
  ```
1141
 
1142
  *Effects:* Constructs an object of type `shared_lock`.
1143
 
1144
- *Postconditions:* `pm == &m` and `owns == false`.
1145
 
1146
  ``` cpp
1147
  shared_lock(mutex_type& m, try_to_lock_t);
1148
  ```
1149
 
@@ -1151,22 +1295,22 @@ shared_lock(mutex_type& m, try_to_lock_t);
1151
  mode.
1152
 
1153
  *Effects:* Constructs an object of type `shared_lock` and calls
1154
  `m.try_lock_shared()`.
1155
 
1156
- *Postconditions:* `pm == &m` and `owns == res` where `res` is the value
1157
- returned by the call to `m.try_lock_shared()`.
1158
 
1159
  ``` cpp
1160
  shared_lock(mutex_type& m, adopt_lock_t);
1161
  ```
1162
 
1163
  *Requires:* The calling thread has shared ownership of the mutex.
1164
 
1165
  *Effects:* Constructs an object of type `shared_lock`.
1166
 
1167
- *Postconditions:* `pm == &m` and `owns == true`.
1168
 
1169
  ``` cpp
1170
  template <class Clock, class Duration>
1171
  shared_lock(mutex_type& m,
1172
  const chrono::time_point<Clock, Duration>& abs_time);
@@ -1176,12 +1320,12 @@ template <class Clock, class Duration>
1176
  mode.
1177
 
1178
  *Effects:* Constructs an object of type `shared_lock` and calls
1179
  `m.try_lock_shared_until(abs_time)`.
1180
 
1181
- *Postconditions:* `pm == &m` and `owns == res` where `res` is the value
1182
- returned by the call to `m.try_lock_shared_until(abs_time)`.
1183
 
1184
  ``` cpp
1185
  template <class Rep, class Period>
1186
  shared_lock(mutex_type& m,
1187
  const chrono::duration<Rep, Period>& rel_time);
@@ -1191,12 +1335,12 @@ template <class Rep, class Period>
1191
  mode.
1192
 
1193
  *Effects:* Constructs an object of type `shared_lock` and calls
1194
  `m.try_lock_shared_for(rel_time)`.
1195
 
1196
- *Postconditions:* `pm == &m` and `owns == res` where `res` is the value
1197
- returned by the call to `m.try_lock_shared_for(rel_time)`.
1198
 
1199
  ``` cpp
1200
  ~shared_lock();
1201
  ```
1202
 
@@ -1204,106 +1348,117 @@ returned by the call to `m.try_lock_shared_for(rel_time)`.
1204
 
1205
  ``` cpp
1206
  shared_lock(shared_lock&& sl) noexcept;
1207
  ```
1208
 
1209
- *Postconditions:* `pm == &sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
1210
  is the state of `sl` just prior to this construction),
1211
  `sl.pm == nullptr` and `sl.owns == false`.
1212
 
1213
  ``` cpp
1214
  shared_lock& operator=(shared_lock&& sl) noexcept;
1215
  ```
1216
 
1217
  *Effects:* If `owns` calls `pm->unlock_shared()`.
1218
 
1219
- *Postconditions:* `pm == &sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
1220
  is the state of `sl` just prior to this assignment), `sl.pm == nullptr`
1221
  and `sl.owns == false`.
1222
 
1223
  ##### `shared_lock` locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
1224
 
1225
  ``` cpp
1226
  void lock();
1227
  ```
1228
 
1229
- *Effects:* `pm->lock_shared()`.
1230
 
1231
  *Postconditions:* `owns == true`.
1232
 
1233
- *Throws:* Any exception thrown by `pm->lock_shared()`. `system_error` if
1234
- an exception is required ([[thread.req.exception]]). `system_error`
1235
- with an error condition of `operation_not_permitted` if `pm` is
1236
- `nullptr`. `system_error` with an error condition of
1237
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
1238
 
1239
  ``` cpp
1240
  bool try_lock();
1241
  ```
1242
 
1243
- *Effects:* `pm->try_lock_shared()`.
1244
 
1245
  *Returns:* The value returned by the call to `pm->try_lock_shared()`.
1246
 
1247
  *Postconditions:* `owns == res`, where `res` is the value returned by
1248
  the call to `pm->try_lock_shared()`.
1249
 
1250
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
1251
- `system_error` if an exception is required ([[thread.req.exception]]).
1252
- `system_error` with an error condition of `operation_not_permitted` if
1253
- `pm` is `nullptr`. `system_error` with an error condition of
1254
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
 
1255
 
1256
  ``` cpp
1257
  template <class Clock, class Duration>
1258
  bool
1259
  try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1260
  ```
1261
 
1262
- *Effects:* `pm->try_lock_shared_until(abs_time)`.
1263
 
1264
  *Returns:* The value returned by the call to
1265
  `pm->try_lock_shared_until(abs_time)`.
1266
 
1267
  *Postconditions:* `owns == res`, where `res` is the value returned by
1268
  the call to `pm->try_lock_shared_until(abs_time)`.
1269
 
1270
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
1271
- `system_error` if an exception is required ([[thread.req.exception]]).
1272
- `system_error` with an error condition of `operation_not_permitted` if
1273
- `pm` is `nullptr`. `system_error` with an error condition of
1274
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
 
1275
 
1276
  ``` cpp
1277
  template <class Rep, class Period>
1278
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1279
  ```
1280
 
1281
- *Effects:* `pm->try_lock_shared_for(rel_time)`.
1282
 
1283
  *Returns:* The value returned by the call to
1284
  `pm->try_lock_shared_for(rel_time)`.
1285
 
1286
  *Postconditions:* `owns == res`, where `res` is the value returned by
1287
  the call to `pm->try_lock_shared_for(rel_time)`.
1288
 
1289
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
1290
- `system_error` if an exception is required  ([[thread.req.exception]]).
1291
- `system_error` with an error condition of `operation_not_permitted` if
1292
- `pm` is `nullptr`. `system_error` with an error condition of
1293
- `resource_deadlock_would_occur` if on entry `owns` is `true`.
 
 
 
1294
 
1295
  ``` cpp
1296
  void unlock();
1297
  ```
1298
 
1299
- *Effects:* `pm->unlock_shared()`.
1300
 
1301
  *Postconditions:* `owns == false`.
1302
 
1303
- *Throws:* `system_error` when an exception is required
1304
-  ([[thread.req.exception]]).
1305
 
1306
  *Error conditions:*
1307
 
1308
  - `operation_not_permitted` — if on entry `owns` is `false`.
1309
 
@@ -1326,11 +1481,11 @@ mutex_type* release() noexcept;
1326
  ``` cpp
1327
  template <class Mutex>
1328
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1329
  ```
1330
 
1331
- *Effects:* `x.swap(y)`.
1332
 
1333
  ##### `shared_lock` observers <a id="thread.lock.shared.obs">[[thread.lock.shared.obs]]</a>
1334
 
1335
  ``` cpp
1336
  bool owns_lock() const noexcept;
@@ -1355,97 +1510,120 @@ mutex_type* mutex() const noexcept;
1355
  ``` cpp
1356
  template <class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
1357
  ```
1358
 
1359
  *Requires:* Each template parameter type shall meet the `Lockable`
1360
- requirements. The `unique_lock` class template meets these requirements
1361
- when suitably instantiated.
 
 
1362
 
1363
  *Effects:* Calls `try_lock()` for each argument in order beginning with
1364
  the first until all arguments have been processed or a call to
1365
  `try_lock()` fails, either by returning `false` or by throwing an
1366
  exception. If a call to `try_lock()` fails, `unlock()` shall be called
1367
  for all prior arguments and there shall be no further calls to
1368
  `try_lock()`.
1369
 
1370
  *Returns:* `-1` if all calls to `try_lock()` returned `true`, otherwise
1371
- a 0-based index value that indicates the argument for which `try_lock()`
1372
- returned `false`.
1373
 
1374
  ``` cpp
1375
  template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
1376
  ```
1377
 
1378
  *Requires:* Each template parameter type shall meet the `Lockable`
1379
- requirements, The `unique_lock` class template meets these requirements
1380
- when suitably instantiated.
 
 
1381
 
1382
  *Effects:* All arguments are locked via a sequence of calls to `lock()`,
1383
  `try_lock()`, or `unlock()` on each argument. The sequence of calls
1384
- shall not result in deadlock, but is otherwise unspecified. A deadlock
1385
- avoidance algorithm such as try-and-back-off must be used, but the
1386
- specific algorithm is not specified to avoid over-constraining
1387
- implementations. If a call to `lock()` or `try_lock()` throws an
1388
- exception, `unlock()` shall be called for any argument that had been
1389
- locked by a call to `lock()` or `try_lock()`.
 
 
 
1390
 
1391
  ### Call once <a id="thread.once">[[thread.once]]</a>
1392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
  The class `once_flag` is an opaque data structure that `call_once` uses
1394
  to initialize data without causing a data race or deadlock.
1395
 
1396
- #### Struct `once_flag` <a id="thread.once.onceflag">[[thread.once.onceflag]]</a>
1397
-
1398
  ``` cpp
1399
  constexpr once_flag() noexcept;
1400
  ```
1401
 
1402
  *Effects:* Constructs an object of type `once_flag`.
1403
 
1404
  *Synchronization:* The construction of a `once_flag` object is not
1405
  synchronized.
1406
 
1407
- The object’s internal state is set to indicate to an invocation of
1408
- `call_once` with the object as its initial argument that no function has
1409
- been called.
1410
 
1411
  #### Function `call_once` <a id="thread.once.callonce">[[thread.once.callonce]]</a>
1412
 
1413
  ``` cpp
1414
  template<class Callable, class... Args>
1415
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
1416
  ```
1417
 
1418
- *Requires:* `Callable` and each `Ti` in `Args` shall satisfy the
1419
- `MoveConstructible` requirements. *`INVOKE`*`(`*`DECAY_COPY`*`(`
1420
- `std::forward<Callable>(func)), `*`DECAY_COPY`*`(std::forward<Args>(args))...)`
1421
- ([[func.require]]) shall be a valid expression.
 
 
 
1422
 
1423
  *Effects:* An execution of `call_once` that does not call its `func` is
1424
  a *passive* execution. An execution of `call_once` that calls its `func`
1425
- is an *active* execution. An active execution shall call
1426
- *`INVOKE`*`(`*`DECAY_COPY`*`(`
1427
- `std::forward<Callable>(func)), `*`DECAY_COPY`*`(std::forward<Args>(args))...)`.
1428
- If such a call to `func` throws an exception the execution is
1429
- *exceptional*, otherwise it is *returning*. An exceptional execution
1430
- shall propagate the exception to the caller of `call_once`. Among all
1431
- executions of `call_once` for any given `once_flag`: at most one shall
1432
- be a returning execution; if there is a returning execution, it shall be
1433
- the last active execution; and there are passive executions only if
1434
- there is a returning execution. passive executions allow other threads
1435
- to reliably observe the results produced by the earlier returning
1436
- execution.
1437
 
1438
  *Synchronization:* For any given `once_flag`: all active executions
1439
  occur in a total order; completion of an active execution synchronizes
1440
  with ([[intro.multithread]]) the start of the next one in this total
1441
  order; and the returning execution synchronizes with the return from all
1442
  passive executions.
1443
 
1444
  *Throws:* `system_error` when an exception is
1445
  required ([[thread.req.exception]]), or any exception thrown by `func`.
1446
 
 
 
1447
  ``` cpp
1448
  // global flag, regular function
1449
  void init();
1450
  std::once_flag flag;
1451
 
@@ -1470,5 +1648,7 @@ class information {
1470
  public:
1471
  void verify() { std::call_once(verified, &information::verifier, *this); }
1472
  };
1473
  ```
1474
 
 
 
 
2
 
3
  This section 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
 
36
  template<class Callable, class... Args>
37
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
38
  }
39
  ```
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
  }
 
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 shall meet the
70
+ requirements set out in this section. In this description, `m` denotes
71
+ an object of a mutex type.
72
 
73
  The mutex types shall meet the `Lockable` requirements (
74
  [[thread.req.lockable.req]]).
75
 
76
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
 
83
 
84
  - `resource_unavailable_try_again` — if any native handle type
85
  manipulated is not available.
86
  - `operation_not_permitted` — if the thread does not have the privilege
87
  to perform the operation.
 
 
88
  - `invalid_argument` — if any native handle type manipulated as part of
89
  mutex construction is incorrect.
90
 
91
  The implementation shall provide lock and unlock operations, as
92
  described below. For purposes of determining the existence of a data
93
  race, these behave as atomic operations ([[intro.multithread]]). The
94
  lock and unlock operations on a single mutex shall appear to occur in a
95
+ single total order.
96
+
97
+ [*Note 1*: This can be viewed as the modification order (
98
+ [[intro.multithread]]) of the mutex. *end note*]
99
+
100
+ [*Note 2*: Construction and destruction of an object of a mutex type
101
+ need not be thread-safe; other synchronization should be used to ensure
102
+ that mutex objects are initialized and visible to other
103
+ threads. — *end note*]
104
 
105
  The expression `m.lock()` shall be well-formed and have the following
106
  semantics:
107
 
108
+ *Requires:* If `m` is of type `mutex`, `timed_mutex`, `shared_mutex`, or
109
+ `shared_timed_mutex`, the calling thread does not own the mutex.
110
 
111
  *Effects:* Blocks the calling thread until ownership of the mutex can be
112
  obtained for the calling thread.
113
 
114
+ *Postconditions:* The calling thread owns the mutex.
115
 
116
+ *Return type:* `void`.
117
 
118
  *Synchronization:* Prior `unlock()` operations on the same object shall
119
  *synchronize with* ([[intro.multithread]]) this operation.
120
 
121
  *Throws:* `system_error` when an exception is
 
125
 
126
  - `operation_not_permitted` — if the thread does not have the privilege
127
  to perform the operation.
128
  - `resource_deadlock_would_occur` — if the implementation detects that a
129
  deadlock would occur.
 
 
130
 
131
  The expression `m.try_lock()` shall be well-formed and have the
132
  following semantics:
133
 
134
+ *Requires:* If `m` is of type `mutex`, `timed_mutex`, `shared_mutex`, or
135
+ `shared_timed_mutex`, the calling thread does not own the mutex.
136
 
137
  *Effects:* Attempts to obtain ownership of the mutex for the calling
138
  thread without blocking. If ownership is not obtained, there is no
139
  effect and `try_lock()` immediately returns. An implementation may fail
140
+ to obtain the lock even if it is not held by any other thread.
 
 
 
 
 
141
 
142
+ [*Note 1*: This spurious failure is normally uncommon, but allows
143
+ interesting implementations based on a simple compare and exchange
144
+ (Clause  [[atomics]]). — *end note*]
145
+
146
+ An implementation should ensure that `try_lock()` does not consistently
147
+ return `false` in the absence of contending mutex acquisitions.
148
+
149
+ *Return type:* `bool`.
150
 
151
  *Returns:* `true` if ownership of the mutex was obtained for the calling
152
  thread, otherwise `false`.
153
 
154
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
155
  operations on the same object *synchronize
156
+ with* ([[intro.multithread]]) this operation.
157
+
158
+ [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
159
+ `try_lock()`, the visibility rules are weak enough that little would be
160
+ known about the state after a failure, even in the absence of spurious
161
+ failures. — *end note*]
162
 
163
  *Throws:* Nothing.
164
 
165
  The expression `m.unlock()` shall be well-formed and have the following
166
  semantics:
167
 
168
+ *Requires:* The calling thread shall own the mutex.
169
 
170
  *Effects:* Releases the calling thread’s ownership of the mutex.
171
 
172
+ *Return type:* `void`.
173
 
174
  *Synchronization:* This operation synchronizes
175
  with ([[intro.multithread]]) subsequent lock operations that obtain
176
  ownership on the same object.
177
 
 
191
 
192
  void lock();
193
  bool try_lock();
194
  void unlock();
195
 
196
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
197
  native_handle_type native_handle(); // See~[thread.req.native]
198
  };
199
  }
200
  ```
201
 
 
203
  ownership semantics. If one thread owns a mutex object, attempts by
204
  another thread to acquire ownership of that object will fail (for
205
  `try_lock()`) or block (for `lock()`) until the owning thread has
206
  released ownership with a call to `unlock()`.
207
 
208
+ [*Note 3*: After a thread `A` has called `unlock()`, releasing a mutex,
209
+ it is possible for another thread `B` to lock the same mutex, observe
210
+ that it is no longer in use, unlock it, and destroy it, before thread
211
+ `A` appears to have returned from its unlock call. Implementations are
212
  required to handle such scenarios correctly, as long as thread `A`
213
  doesn’t access the mutex after the unlock call returns. These cases
214
  typically occur when a reference-counted object contains a mutex that is
215
+ used to protect the reference count. — *end note*]
216
 
217
+ The class `mutex` shall satisfy all of the mutex requirements (
218
  [[thread.mutex.requirements]]). It shall be a standard-layout class
219
  (Clause  [[class]]).
220
 
221
+ [*Note 4*: A program may deadlock if the thread that owns a `mutex`
222
+ object calls `lock()` on that object. If the implementation can detect
223
+ the deadlock, a `resource_deadlock_would_occur` error condition may be
224
+ observed. — *end note*]
225
 
226
  The behavior of a program is undefined if it destroys a `mutex` object
227
  owned by any thread or a thread terminates while owning a `mutex`
228
  object.
229
 
 
241
 
242
  void lock();
243
  bool try_lock() noexcept;
244
  void unlock();
245
 
246
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
247
  native_handle_type native_handle(); // See~[thread.req.native]
248
  };
249
  }
250
  ```
251
 
 
253
  ownership semantics. If one thread owns a `recursive_mutex` object,
254
  attempts by another thread to acquire ownership of that object will fail
255
  (for `try_lock()`) or block (for `lock()`) until the first thread has
256
  completely released ownership.
257
 
258
+ The class `recursive_mutex` shall satisfy all of the mutex
259
+ requirements ([[thread.mutex.requirements]]). It shall be a
260
+ standard-layout class (Clause  [[class]]).
261
 
262
  A thread that owns a `recursive_mutex` object may acquire additional
263
  levels of ownership by calling `lock()` or `try_lock()` on that object.
264
  It is unspecified how many levels of ownership may be acquired by a
265
  single thread. If a thread has already acquired the maximum level of
 
275
  - it destroys a `recursive_mutex` object owned by any thread or
276
  - a thread terminates while owning a `recursive_mutex` object.
277
 
278
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
279
 
280
+ The *timed mutex types* are the standard library types `timed_mutex`,
281
+ `recursive_timed_mutex`, and `shared_timed_mutex`. They shall meet the
282
+ requirements set out below. In this description, `m` denotes an object
283
+ of a mutex type, `rel_time` denotes an object of an instantiation of
284
+ `duration` ([[time.duration]]), and `abs_time` denotes an object of an
285
+ instantiation of `time_point` ([[time.point]]).
 
286
 
287
  The timed mutex types shall meet the `TimedLockable` requirements (
288
  [[thread.req.lockable.timed]]).
289
 
290
  The expression `m.try_lock_for(rel_time)` shall be well-formed and have
291
  the following semantics:
292
 
293
+ *Requires:* If `m` is of type `timed_mutex` or `shared_timed_mutex`, the
294
  calling thread does not own the mutex.
295
 
296
  *Effects:* The function attempts to obtain ownership of the mutex within
297
  the relative timeout ([[thread.req.timing]]) specified by `rel_time`.
298
  If the time specified by `rel_time` is less than or equal to
299
  `rel_time.zero()`, the function attempts to obtain ownership without
300
  blocking (as if by calling `try_lock()`). The function shall return
301
  within the timeout specified by `rel_time` only if it has obtained
302
+ ownership of the mutex object.
 
 
303
 
304
+ [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
305
+ will be obtained if the lock is available, but implementations are
306
+ expected to make a strong effort to do so. — *end note*]
307
+
308
+ *Return type:* `bool`.
309
 
310
  *Returns:* `true` if ownership was obtained, otherwise `false`.
311
 
312
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
313
  operations on the same object *synchronize
 
316
  *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
317
 
318
  The expression `m.try_lock_until(abs_time)` shall be well-formed and
319
  have the following semantics:
320
 
321
+ *Requires:* If `m` is of type `timed_mutex` or `shared_timed_mutex`, the
322
+ calling thread does not own the mutex.
323
 
324
  *Effects:* The function attempts to obtain ownership of the mutex. If
325
  `abs_time` has already passed, the function attempts to obtain ownership
326
  without blocking (as if by calling `try_lock()`). The function shall
327
  return before the absolute timeout ([[thread.req.timing]]) specified by
328
+ `abs_time` only if it has obtained ownership of the mutex object.
 
 
 
329
 
330
+ [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
331
+ will be obtained if the lock is available, but implementations are
332
+ expected to make a strong effort to do so. — *end note*]
333
+
334
+ *Return type:* `bool`.
335
 
336
  *Returns:* `true` if ownership was obtained, otherwise `false`.
337
 
338
  *Synchronization:* If `try_lock_until()` returns `true`, prior
339
  `unlock()` operations on the same object *synchronize
 
359
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
360
  template <class Clock, class Duration>
361
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
362
  void unlock();
363
 
364
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
365
  native_handle_type native_handle(); // See~[thread.req.native]
366
  };
367
  }
368
  ```
369
 
 
373
  `try_lock()`) or block (for `lock()`, `try_lock_for()`, and
374
  `try_lock_until()`) until the owning thread has released ownership with
375
  a call to `unlock()` or the call to `try_lock_for()` or
376
  `try_lock_until()` times out (having failed to obtain ownership).
377
 
378
+ The class `timed_mutex` shall satisfy all of the timed mutex
379
  requirements ([[thread.timedmutex.requirements]]). It shall be a
380
  standard-layout class (Clause  [[class]]).
381
 
382
  The behavior of a program is undefined if:
383
 
 
405
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
406
  template <class Clock, class Duration>
407
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
408
  void unlock();
409
 
410
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
411
  native_handle_type native_handle(); // See~[thread.req.native]
412
  };
413
  }
414
  ```
415
 
 
419
  ownership of that object will fail (for `try_lock()`) or block (for
420
  `lock()`, `try_lock_for()`, and `try_lock_until()`) until the owning
421
  thread has completely released ownership or the call to `try_lock_for()`
422
  or `try_lock_until()` times out (having failed to obtain ownership).
423
 
424
+ The class `recursive_timed_mutex` shall satisfy all of the timed mutex
425
  requirements ([[thread.timedmutex.requirements]]). It shall be a
426
  standard-layout class (Clause  [[class]]).
427
 
428
  A thread that owns a `recursive_timed_mutex` object may acquire
429
  additional levels of ownership by calling `lock()`, `try_lock()`,
 
441
  The behavior of a program is undefined if:
442
 
443
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
444
  - a thread terminates while owning a `recursive_timed_mutex` object.
445
 
446
+ #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
447
 
448
+ The standard library types `shared_mutex` and `shared_timed_mutex` are
449
+ *shared mutex types*. Shared mutex types shall meet the requirements of
450
+ mutex types ([[thread.mutex.requirements.mutex]]), and additionally
451
+ shall meet the requirements set out below. In this description, `m`
452
+ denotes an object of a shared mutex type.
 
 
 
453
 
454
  In addition to the exclusive lock ownership mode specified in 
455
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
456
  *shared lock* ownership mode. Multiple execution agents can
457
  simultaneously hold a shared lock ownership of a shared mutex type. But
 
471
 
472
  *Effects:* Blocks the calling thread until shared ownership of the mutex
473
  can be obtained for the calling thread. If an exception is thrown then a
474
  shared lock shall not have been acquired for the current thread.
475
 
476
+ *Postconditions:* The calling thread has a shared lock on the mutex.
477
 
478
  *Return type:* `void`.
479
 
480
  *Synchronization:* Prior `unlock()` operations on the same object shall
481
  synchronize with ([[intro.multithread]]) this operation.
482
 
483
+ *Throws:* `system_error` when an exception is
484
+ required ([[thread.req.exception]]).
485
 
486
  *Error conditions:*
487
 
488
  - `operation_not_permitted` — if the thread does not have the privilege
489
  to perform the operation.
490
  - `resource_deadlock_would_occur` — if the implementation detects that a
491
  deadlock would occur.
 
 
492
 
493
  The expression `m.unlock_shared()` shall be well-formed and have the
494
  following semantics:
495
 
496
  *Requires:* The calling thread shall hold a shared lock on the mutex.
 
521
 
522
  *Returns:* `true` if the shared ownership lock was acquired, `false`
523
  otherwise.
524
 
525
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
526
+ `unlock()` operations on the same object synchronize
527
+ with ([[intro.multithread]]) this operation.
528
 
529
  *Throws:* Nothing.
530
 
531
+ ##### Class shared_mutex <a id="thread.sharedmutex.class">[[thread.sharedmutex.class]]</a>
532
+
533
+ ``` cpp
534
+ namespace std {
535
+ class shared_mutex {
536
+ public:
537
+ shared_mutex();
538
+ ~shared_mutex();
539
+
540
+ shared_mutex(const shared_mutex&) = delete;
541
+ shared_mutex& operator=(const shared_mutex&) = delete;
542
+
543
+ // Exclusive ownership
544
+ void lock(); // blocking
545
+ bool try_lock();
546
+ void unlock();
547
+
548
+ // Shared ownership
549
+ void lock_shared(); // blocking
550
+ bool try_lock_shared();
551
+ void unlock_shared();
552
+
553
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
554
+ native_handle_type native_handle(); // See~[thread.req.native]
555
+ };
556
+ }
557
+ ```
558
+
559
+ The class `shared_mutex` provides a non-recursive mutex with shared
560
+ ownership semantics.
561
+
562
+ The class `shared_mutex` shall satisfy all of the shared mutex
563
+ requirements ([[thread.sharedmutex.requirements]]). It shall be a
564
+ standard-layout class (Clause  [[class]]).
565
+
566
+ The behavior of a program is undefined if:
567
+
568
+ - it destroys a `shared_mutex` object owned by any thread,
569
+ - a thread attempts to recursively gain any ownership of a
570
+ `shared_mutex`, or
571
+ - a thread terminates while possessing any ownership of a
572
+ `shared_mutex`.
573
+
574
+ `shared_mutex` may be a synonym for `shared_timed_mutex`.
575
+
576
+ #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
577
+
578
+ The standard library type `shared_timed_mutex` is a *shared timed mutex
579
+ type*. Shared timed mutex types shall meet the requirements of timed
580
+ mutex types ([[thread.timedmutex.requirements]]), shared mutex types (
581
+ [[thread.sharedmutex.requirements]]), and additionally shall meet the
582
+ requirements set out below. In this description, `m` denotes an object
583
+ of a shared timed mutex type, `rel_type` denotes an object of an
584
+ instantiation of `duration` ([[time.duration]]), and `abs_time` denotes
585
+ an object of an instantiation of `time_point` ([[time.point]]).
586
+
587
  The expression `m.try_lock_shared_for(rel_time)` shall be well-formed
588
  and have the following semantics:
589
 
590
  *Requires:* The calling thread has no ownership of the mutex.
591
 
 
593
  thread within the relative timeout ([[thread.req.timing]]) specified by
594
  `rel_time`. If the time specified by `rel_time` is less than or equal to
595
  `rel_time.zero()`, the function attempts to obtain ownership without
596
  blocking (as if by calling `try_lock_shared()`). The function shall
597
  return within the timeout specified by `rel_time` only if it has
598
+ obtained shared ownership of the mutex object.
599
+
600
+ [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
601
+ will be obtained if the lock is available, but implementations are
602
+ expected to make a strong effort to do so. — *end note*]
603
+
604
+ If an exception is thrown then a shared lock shall not have been
605
  acquired for the current thread.
606
 
607
  *Return type:* `bool`.
608
 
609
  *Returns:* `true` if the shared lock was acquired, `false` otherwise.
 
622
  *Effects:* The function attempts to obtain shared ownership of the
623
  mutex. If `abs_time` has already passed, the function attempts to obtain
624
  shared ownership without blocking (as if by calling
625
  `try_lock_shared()`). The function shall return before the absolute
626
  timeout ([[thread.req.timing]]) specified by `abs_time` only if it has
627
+ obtained shared ownership of the mutex object.
628
+
629
+ [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
630
+ will be obtained if the lock is available, but implementations are
631
+ expected to make a strong effort to do so. — *end note*]
632
+
633
+ If an exception is thrown then a shared lock shall not have been
634
  acquired for the current thread.
635
 
636
  *Return type:* `bool`.
637
 
638
  *Returns:* `true` if the shared lock was acquired, `false` otherwise.
 
679
  ```
680
 
681
  The class `shared_timed_mutex` provides a non-recursive mutex with
682
  shared ownership semantics.
683
 
684
+ The class `shared_timed_mutex` shall satisfy all of the shared timed
685
+ mutex requirements ([[thread.sharedtimedmutex.requirements]]). It shall
686
+ be a standard-layout class (Clause  [[class]]).
 
687
 
688
  The behavior of a program is undefined if:
689
 
690
  - it destroys a `shared_timed_mutex` object owned by any thread,
691
  - a thread attempts to recursively gain any ownership of a
 
699
  may unlock the lockable object during the lock’s destruction (such as
700
  when leaving block scope). An execution agent may use a lock to aid in
701
  managing ownership of a lockable object in an exception safe manner. A
702
  lock is said to *own* a lockable object if it is currently managing the
703
  ownership of that lockable object for an execution agent. A lock does
704
+ not manage the lifetime of the lockable object it references.
705
+
706
+ [*Note 1*: Locks are intended to ease the burden of unlocking the
707
+ lockable object under both normal and exceptional
708
+ circumstances. — *end note*]
709
 
710
  Some lock constructors take tag types which describe what should be done
711
  with the lockable object during the lock’s construction.
712
 
713
  ``` cpp
 
716
  struct try_to_lock_t { }; // try to acquire ownership of the mutex
717
  // without blocking
718
  struct adopt_lock_t { }; // assume the calling thread has already
719
  // obtained mutex ownership and manage it
720
 
721
+ inline constexpr defer_lock_t defer_lock { };
722
+ inline constexpr try_to_lock_t try_to_lock { };
723
+ inline constexpr adopt_lock_t adopt_lock { };
724
  }
725
  ```
726
 
727
  #### Class template `lock_guard` <a id="thread.lock.guard">[[thread.lock.guard]]</a>
728
 
729
  ``` cpp
730
  namespace std {
731
  template <class Mutex>
732
  class lock_guard {
733
  public:
734
+ using mutex_type = Mutex;
735
 
736
  explicit lock_guard(mutex_type& m);
737
  lock_guard(mutex_type& m, adopt_lock_t);
738
  ~lock_guard();
739
 
740
+ lock_guard(const lock_guard&) = delete;
741
+ lock_guard& operator=(const lock_guard&) = delete;
742
 
743
  private:
744
  mutex_type& pm; // exposition only
745
  };
746
+
747
+ template<class Mutex> lock_guard(lock_guard<Mutex>) -> lock_guard<Mutex>;
748
  }
749
  ```
750
 
751
  An object of type `lock_guard` controls the ownership of a lockable
752
  object within a scope. A `lock_guard` object maintains ownership of a
 
758
 
759
  ``` cpp
760
  explicit lock_guard(mutex_type& m);
761
  ```
762
 
763
+ *Requires:* If `mutex_type` is not a recursive mutex, the calling thread
764
+ does not own the mutex `m`.
765
 
766
+ *Effects:* As if by `m.lock()`.
767
 
768
+ *Postconditions:* `&pm == &m`
769
 
770
  ``` cpp
771
  lock_guard(mutex_type& m, adopt_lock_t);
772
  ```
773
 
774
+ *Requires:* The calling thread owns the mutex `m`.
775
 
776
+ *Postconditions:* `&pm == &m`
777
 
778
  *Throws:* Nothing.
779
 
780
  ``` cpp
781
  ~lock_guard();
782
  ```
783
 
784
+ *Effects:* As if by `pm.unlock()`.
785
+
786
+ #### Class template `scoped_lock` <a id="thread.lock.scoped">[[thread.lock.scoped]]</a>
787
+
788
+ ``` cpp
789
+ namespace std {
790
+ template <class... MutexTypes>
791
+ class scoped_lock {
792
+ public:
793
+ using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
794
+
795
+ explicit scoped_lock(MutexTypes&... m);
796
+ explicit scoped_lock(MutexTypes&... m, adopt_lock_t);
797
+ ~scoped_lock();
798
+
799
+ scoped_lock(const scoped_lock&) = delete;
800
+ scoped_lock& operator=(const scoped_lock&) = delete;
801
+
802
+ private:
803
+ tuple<MutexTypes&...> pm; // exposition only
804
+ };
805
+
806
+ template<class... MutexTypes>
807
+ scoped_lock(scoped_lock<MutexTypes...>) -> scoped_lock<MutexTypes...>;
808
+ }
809
+ ```
810
+
811
+ An object of type `scoped_lock` controls the ownership of lockable
812
+ objects within a scope. A `scoped_lock` object maintains ownership of
813
+ lockable objects throughout the `scoped_lock` object’s lifetime (
814
+ [[basic.life]]). The behavior of a program is undefined if the lockable
815
+ objects referenced by `pm` do not exist for the entire lifetime of the
816
+ `scoped_lock` object. When `sizeof...(MutexTypes)` is `1`, the supplied
817
+ `Mutex` type shall meet the `BasicLockable` requirements (
818
+ [[thread.req.lockable.basic]]). Otherwise, each of the mutex types shall
819
+ meet the `Lockable` requirements ([[thread.req.lockable.req]]).
820
+
821
+ ``` cpp
822
+ explicit scoped_lock(MutexTypes&... m);
823
+ ```
824
+
825
+ *Requires:* If a `MutexTypes` type is not a recursive mutex, the calling
826
+ thread does not own the corresponding mutex element of `m`.
827
+
828
+ *Effects:* Initializes `pm` with `tie(m...)`. Then if
829
+ `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
830
+ `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
831
+ `lock(m...)`.
832
+
833
+ ``` cpp
834
+ explicit scoped_lock(MutexTypes&... m, adopt_lock_t);
835
+ ```
836
+
837
+ *Requires:* The calling thread owns all the mutexes in `m`.
838
+
839
+ *Effects:* Initializes `pm` with `tie(m...)`.
840
+
841
+ *Throws:* Nothing.
842
+
843
+ ``` cpp
844
+ ~scoped_lock();
845
+ ```
846
+
847
+ *Effects:* For all `i` in \[`0`, `sizeof...(MutexTypes)`),
848
+ `get<i>(pm).unlock()`.
849
 
850
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
851
 
852
  ``` cpp
853
  namespace std {
854
  template <class Mutex>
855
  class unique_lock {
856
  public:
857
+ using mutex_type = Mutex;
858
 
859
+ // [thread.lock.unique.cons], construct/copy/destroy
860
  unique_lock() noexcept;
861
  explicit unique_lock(mutex_type& m);
862
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
863
  unique_lock(mutex_type& m, try_to_lock_t);
864
  unique_lock(mutex_type& m, adopt_lock_t);
 
866
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
867
  template <class Rep, class Period>
868
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
869
  ~unique_lock();
870
 
871
+ unique_lock(const unique_lock&) = delete;
872
+ unique_lock& operator=(const unique_lock&) = delete;
873
 
874
  unique_lock(unique_lock&& u) noexcept;
875
  unique_lock& operator=(unique_lock&& u);
876
 
877
+ // [thread.lock.unique.locking], locking
878
  void lock();
879
  bool try_lock();
880
 
881
  template <class Rep, class Period>
882
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
883
  template <class Clock, class Duration>
884
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
885
 
886
  void unlock();
887
 
888
+ // [thread.lock.unique.mod], modifiers
889
  void swap(unique_lock& u) noexcept;
890
  mutex_type* release() noexcept;
891
 
892
+ // [thread.lock.unique.obs], observers
893
  bool owns_lock() const noexcept;
894
  explicit operator bool () const noexcept;
895
  mutex_type* mutex() const noexcept;
896
 
897
  private:
898
  mutex_type* pm; // exposition only
899
  bool owns; // exposition only
900
  };
901
 
902
+ template<class Mutex> unique_lock(unique_lock<Mutex>) -> unique_lock<Mutex>;
903
+
904
  template <class Mutex>
905
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
906
  }
907
  ```
908
 
 
915
  lockable object pointed to by `pm` does not exist for the entire
916
  remaining lifetime ([[basic.life]]) of the `unique_lock` object. The
917
  supplied `Mutex` type shall meet the `BasicLockable` requirements (
918
  [[thread.req.lockable.basic]]).
919
 
920
+ [*Note 1*: `unique_lock<Mutex>` meets the `BasicLockable` requirements.
921
+ If `Mutex` meets the `Lockable` requirements (
922
+ [[thread.req.lockable.req]]), `unique_lock<Mutex>` also meets the
923
+ `Lockable` requirements; if `Mutex` meets the `TimedLockable`
924
+ requirements ([[thread.req.lockable.timed]]), `unique_lock<Mutex>` also
925
+ meets the `TimedLockable` requirements. — *end note*]
926
 
927
  ##### `unique_lock` constructors, destructor, and assignment <a id="thread.lock.unique.cons">[[thread.lock.unique.cons]]</a>
928
 
929
  ``` cpp
930
  unique_lock() noexcept;
 
936
 
937
  ``` cpp
938
  explicit unique_lock(mutex_type& m);
939
  ```
940
 
941
+ *Requires:* If `mutex_type` is not a recursive mutex the calling thread
942
+ does not own the mutex.
943
 
944
  *Effects:* Constructs an object of type `unique_lock` and calls
945
  `m.lock()`.
946
 
947
+ *Postconditions:* `pm == addressof(m)` and `owns == true`.
948
 
949
  ``` cpp
950
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
951
  ```
952
 
953
  *Effects:* Constructs an object of type `unique_lock`.
954
 
955
+ *Postconditions:* `pm == addressof(m)` and `owns == false`.
956
 
957
  ``` cpp
958
  unique_lock(mutex_type& m, try_to_lock_t);
959
  ```
960
 
961
+ *Requires:* The supplied `Mutex` type shall meet the `Lockable`
962
  requirements ([[thread.req.lockable.req]]). If `mutex_type` is not a
963
  recursive mutex the calling thread does not own the mutex.
964
 
965
  *Effects:* Constructs an object of type `unique_lock` and calls
966
  `m.try_lock()`.
967
 
968
+ *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
969
+ the value returned by the call to `m.try_lock()`.
970
 
971
  ``` cpp
972
  unique_lock(mutex_type& m, adopt_lock_t);
973
  ```
974
 
975
+ *Requires:* The calling thread owns the mutex.
976
 
977
  *Effects:* Constructs an object of type `unique_lock`.
978
 
979
+ *Postconditions:* `pm == addressof(m)` and `owns == true`.
980
 
981
  *Throws:* Nothing.
982
 
983
  ``` cpp
984
  template <class Clock, class Duration>
985
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
986
  ```
987
 
988
+ *Requires:* If `mutex_type` is not a recursive mutex the calling thread
989
+ does not own the mutex. The supplied `Mutex` type shall meet the
990
+ `TimedLockable` requirements ([[thread.req.lockable.timed]]).
991
 
992
  *Effects:* Constructs an object of type `unique_lock` and calls
993
  `m.try_lock_until(abs_time)`.
994
 
995
+ *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
996
+ the value returned by the call to `m.try_lock_until(abs_time)`.
997
 
998
  ``` cpp
999
  template <class Rep, class Period>
1000
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
1001
  ```
1002
 
1003
+ *Requires:* If `mutex_type` is not a recursive mutex the calling thread
1004
+ does not own the mutex. The supplied `Mutex` type shall meet the
1005
+ `TimedLockable` requirements ([[thread.req.lockable.timed]]).
1006
 
1007
  *Effects:* Constructs an object of type `unique_lock` and calls
1008
  `m.try_lock_for(rel_time)`.
1009
 
1010
+ *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
1011
+ the value returned by the call to `m.try_lock_for(rel_time)`.
1012
 
1013
  ``` cpp
1014
  unique_lock(unique_lock&& u) noexcept;
1015
  ```
1016
 
 
1026
 
1027
  *Postconditions:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is
1028
  the state of `u` just prior to this construction), `u.pm == 0` and
1029
  `u.owns == false`.
1030
 
1031
+ [*Note 1*: With a recursive mutex it is possible for both `*this` and
1032
+ `u` to own the same mutex before the assignment. In this case, `*this`
1033
+ will own the mutex after the assignment and `u` will not. — *end note*]
1034
 
1035
  *Throws:* Nothing.
1036
 
1037
  ``` cpp
1038
  ~unique_lock();
 
1044
 
1045
  ``` cpp
1046
  void lock();
1047
  ```
1048
 
1049
+ *Effects:* As if by `pm->lock()`.
1050
 
1051
+ *Postconditions:* `owns == true`.
1052
 
1053
+ *Throws:* Any exception thrown by `pm->lock()`. `system_error` when an
1054
+ exception is required ([[thread.req.exception]]).
1055
+
1056
+ *Error conditions:*
1057
+
1058
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1059
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1060
 
1061
  ``` cpp
1062
  bool try_lock();
1063
  ```
1064
 
1065
+ *Requires:* The supplied `Mutex` shall meet the `Lockable`
1066
  requirements ([[thread.req.lockable.req]]).
1067
 
1068
+ *Effects:* As if by `pm->try_lock()`.
1069
 
1070
  *Returns:* The value returned by the call to `try_lock()`.
1071
 
1072
+ *Postconditions:* `owns == res`, where `res` is the value returned by
1073
+ the call to `try_lock()`.
1074
 
1075
+ *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
1076
+ an exception is required ([[thread.req.exception]]).
1077
+
1078
+ *Error conditions:*
1079
+
1080
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1081
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1082
 
1083
  ``` cpp
1084
  template <class Clock, class Duration>
1085
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1086
  ```
1087
 
1088
  *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
1089
  requirements ([[thread.req.lockable.timed]]).
1090
 
1091
+ *Effects:* As if by `pm->try_lock_until(abs_time)`.
1092
 
1093
  *Returns:* The value returned by the call to `try_lock_until(abs_time)`.
1094
 
1095
+ *Postconditions:* `owns == res`, where `res` is the value returned by
1096
+ the call to `try_lock_until(abs_time)`.
1097
 
1098
  *Throws:* Any exception thrown by `pm->try_lock_until()`. `system_error`
1099
+ when an exception is required ([[thread.req.exception]]).
1100
+
1101
+ *Error conditions:*
1102
+
1103
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1104
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1105
 
1106
  ``` cpp
1107
  template <class Rep, class Period>
1108
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1109
  ```
1110
 
1111
  *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
1112
  requirements ([[thread.req.lockable.timed]]).
1113
 
1114
+ *Effects:* As if by `pm->try_lock_for(rel_time)`.
1115
 
1116
  *Returns:* The value returned by the call to `try_lock_until(rel_time)`.
1117
 
1118
+ *Postconditions:* `owns == res`, where `res` is the value returned by
1119
+ the call to `try_lock_for(rel_time)`.
1120
 
1121
  *Throws:* Any exception thrown by `pm->try_lock_for()`. `system_error`
1122
+ when an exception is required ([[thread.req.exception]]).
1123
+
1124
+ *Error conditions:*
1125
+
1126
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1127
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1128
 
1129
  ``` cpp
1130
  void unlock();
1131
  ```
1132
 
1133
+ *Effects:* As if by `pm->unlock()`.
1134
 
1135
+ *Postconditions:* `owns == false`.
1136
 
1137
  *Throws:* `system_error` when an exception is
1138
  required ([[thread.req.exception]]).
1139
 
1140
  *Error conditions:*
1141
 
1142
+ - `operation_not_permitted` — if on entry `owns` is `false`.
1143
 
1144
  ##### `unique_lock` modifiers <a id="thread.lock.unique.mod">[[thread.lock.unique.mod]]</a>
1145
 
1146
  ``` cpp
1147
  void swap(unique_lock& u) noexcept;
 
1160
  ``` cpp
1161
  template <class Mutex>
1162
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1163
  ```
1164
 
1165
+ *Effects:* As if by `x.swap(y)`.
1166
 
1167
  ##### `unique_lock` observers <a id="thread.lock.unique.obs">[[thread.lock.unique.obs]]</a>
1168
 
1169
  ``` cpp
1170
  bool owns_lock() const noexcept;
1171
  ```
1172
 
1173
+ *Returns:* `owns`.
1174
 
1175
  ``` cpp
1176
  explicit operator bool() const noexcept;
1177
  ```
1178
 
1179
+ *Returns:* `owns`.
1180
 
1181
  ``` cpp
1182
  mutex_type *mutex() const noexcept;
1183
  ```
1184
 
1185
+ *Returns:* `pm`.
1186
 
1187
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
1188
 
1189
  ``` cpp
1190
  namespace std {
 
1191
  template <class Mutex>
1192
  class shared_lock {
1193
  public:
1194
+ using mutex_type = Mutex;
1195
 
1196
+ // [thread.lock.shared.cons], construct/copy/destroy
1197
  shared_lock() noexcept;
1198
  explicit shared_lock(mutex_type& m); // blocking
1199
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
1200
  shared_lock(mutex_type& m, try_to_lock_t);
1201
  shared_lock(mutex_type& m, adopt_lock_t);
 
1205
  template <class Rep, class Period>
1206
  shared_lock(mutex_type& m,
1207
  const chrono::duration<Rep, Period>& rel_time);
1208
  ~shared_lock();
1209
 
1210
+ shared_lock(const shared_lock&) = delete;
1211
+ shared_lock& operator=(const shared_lock&) = delete;
1212
 
1213
  shared_lock(shared_lock&& u) noexcept;
1214
  shared_lock& operator=(shared_lock&& u) noexcept;
1215
 
1216
+ // [thread.lock.shared.locking], locking
1217
  void lock(); // blocking
1218
  bool try_lock();
1219
  template <class Rep, class Period>
1220
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1221
  template <class Clock, class Duration>
1222
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1223
  void unlock();
1224
 
1225
+ // [thread.lock.shared.mod], modifiers
1226
  void swap(shared_lock& u) noexcept;
1227
  mutex_type* release() noexcept;
1228
 
1229
+ // [thread.lock.shared.obs], observers
1230
  bool owns_lock() const noexcept;
1231
  explicit operator bool () const noexcept;
1232
  mutex_type* mutex() const noexcept;
1233
 
1234
  private:
1235
  mutex_type* pm; // exposition only
1236
  bool owns; // exposition only
1237
  };
1238
 
1239
+ template<class Mutex> shared_lock(shared_lock<Mutex>) -> shared_lock<Mutex>;
1240
+
1241
  template <class Mutex>
1242
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1243
+ }
 
1244
  ```
1245
 
1246
  An object of type `shared_lock` controls the shared ownership of a
1247
  lockable object within a scope. Shared ownership of the lockable object
1248
  may be acquired at construction or after construction, and may be
 
1252
  lockable object pointed to by `pm` does not exist for the entire
1253
  remaining lifetime ([[basic.life]]) of the `shared_lock` object. The
1254
  supplied `Mutex` type shall meet the shared mutex requirements (
1255
  [[thread.sharedtimedmutex.requirements]]).
1256
 
1257
+ [*Note 1*: `shared_lock<Mutex>` meets the `TimedLockable`
1258
+ requirements ([[thread.req.lockable.timed]]). — *end note*]
1259
 
1260
  ##### `shared_lock` constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
1261
 
1262
  ``` cpp
1263
  shared_lock() noexcept;
 
1275
  mode.
1276
 
1277
  *Effects:* Constructs an object of type `shared_lock` and calls
1278
  `m.lock_shared()`.
1279
 
1280
+ *Postconditions:* `pm == addressof(m)` and `owns == true`.
1281
 
1282
  ``` cpp
1283
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
1284
  ```
1285
 
1286
  *Effects:* Constructs an object of type `shared_lock`.
1287
 
1288
+ *Postconditions:* `pm == addressof(m)` and `owns == false`.
1289
 
1290
  ``` cpp
1291
  shared_lock(mutex_type& m, try_to_lock_t);
1292
  ```
1293
 
 
1295
  mode.
1296
 
1297
  *Effects:* Constructs an object of type `shared_lock` and calls
1298
  `m.try_lock_shared()`.
1299
 
1300
+ *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
1301
+ the value returned by the call to `m.try_lock_shared()`.
1302
 
1303
  ``` cpp
1304
  shared_lock(mutex_type& m, adopt_lock_t);
1305
  ```
1306
 
1307
  *Requires:* The calling thread has shared ownership of the mutex.
1308
 
1309
  *Effects:* Constructs an object of type `shared_lock`.
1310
 
1311
+ *Postconditions:* `pm == addressof(m)` and `owns == true`.
1312
 
1313
  ``` cpp
1314
  template <class Clock, class Duration>
1315
  shared_lock(mutex_type& m,
1316
  const chrono::time_point<Clock, Duration>& abs_time);
 
1320
  mode.
1321
 
1322
  *Effects:* Constructs an object of type `shared_lock` and calls
1323
  `m.try_lock_shared_until(abs_time)`.
1324
 
1325
+ *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
1326
+ the value returned by the call to `m.try_lock_shared_until(abs_time)`.
1327
 
1328
  ``` cpp
1329
  template <class Rep, class Period>
1330
  shared_lock(mutex_type& m,
1331
  const chrono::duration<Rep, Period>& rel_time);
 
1335
  mode.
1336
 
1337
  *Effects:* Constructs an object of type `shared_lock` and calls
1338
  `m.try_lock_shared_for(rel_time)`.
1339
 
1340
+ *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
1341
+ the value returned by the call to `m.try_lock_shared_for(rel_time)`.
1342
 
1343
  ``` cpp
1344
  ~shared_lock();
1345
  ```
1346
 
 
1348
 
1349
  ``` cpp
1350
  shared_lock(shared_lock&& sl) noexcept;
1351
  ```
1352
 
1353
+ *Postconditions:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
1354
  is the state of `sl` just prior to this construction),
1355
  `sl.pm == nullptr` and `sl.owns == false`.
1356
 
1357
  ``` cpp
1358
  shared_lock& operator=(shared_lock&& sl) noexcept;
1359
  ```
1360
 
1361
  *Effects:* If `owns` calls `pm->unlock_shared()`.
1362
 
1363
+ *Postconditions:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
1364
  is the state of `sl` just prior to this assignment), `sl.pm == nullptr`
1365
  and `sl.owns == false`.
1366
 
1367
  ##### `shared_lock` locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
1368
 
1369
  ``` cpp
1370
  void lock();
1371
  ```
1372
 
1373
+ *Effects:* As if by `pm->lock_shared()`.
1374
 
1375
  *Postconditions:* `owns == true`.
1376
 
1377
+ *Throws:* Any exception thrown by `pm->lock_shared()`. `system_error`
1378
+ when an exception is required ([[thread.req.exception]]).
1379
+
1380
+ *Error conditions:*
1381
+
1382
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1383
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1384
 
1385
  ``` cpp
1386
  bool try_lock();
1387
  ```
1388
 
1389
+ *Effects:* As if by `pm->try_lock_shared()`.
1390
 
1391
  *Returns:* The value returned by the call to `pm->try_lock_shared()`.
1392
 
1393
  *Postconditions:* `owns == res`, where `res` is the value returned by
1394
  the call to `pm->try_lock_shared()`.
1395
 
1396
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
1397
+ `system_error` when an exception is
1398
+ required ([[thread.req.exception]]).
1399
+
1400
+ *Error conditions:*
1401
+
1402
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1403
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1404
 
1405
  ``` cpp
1406
  template <class Clock, class Duration>
1407
  bool
1408
  try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1409
  ```
1410
 
1411
+ *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
1412
 
1413
  *Returns:* The value returned by the call to
1414
  `pm->try_lock_shared_until(abs_time)`.
1415
 
1416
  *Postconditions:* `owns == res`, where `res` is the value returned by
1417
  the call to `pm->try_lock_shared_until(abs_time)`.
1418
 
1419
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
1420
+ `system_error` when an exception is
1421
+ required ([[thread.req.exception]]).
1422
+
1423
+ *Error conditions:*
1424
+
1425
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1426
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1427
 
1428
  ``` cpp
1429
  template <class Rep, class Period>
1430
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1431
  ```
1432
 
1433
+ *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
1434
 
1435
  *Returns:* The value returned by the call to
1436
  `pm->try_lock_shared_for(rel_time)`.
1437
 
1438
  *Postconditions:* `owns == res`, where `res` is the value returned by
1439
  the call to `pm->try_lock_shared_for(rel_time)`.
1440
 
1441
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
1442
+ `system_error` when an exception is
1443
+ required ([[thread.req.exception]]).
1444
+
1445
+ *Error conditions:*
1446
+
1447
+ - `operation_not_permitted` — if `pm` is `nullptr`.
1448
+ - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
1449
 
1450
  ``` cpp
1451
  void unlock();
1452
  ```
1453
 
1454
+ *Effects:* As if by `pm->unlock_shared()`.
1455
 
1456
  *Postconditions:* `owns == false`.
1457
 
1458
+ *Throws:* `system_error` when an exception is
1459
+ required ([[thread.req.exception]]).
1460
 
1461
  *Error conditions:*
1462
 
1463
  - `operation_not_permitted` — if on entry `owns` is `false`.
1464
 
 
1481
  ``` cpp
1482
  template <class Mutex>
1483
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1484
  ```
1485
 
1486
+ *Effects:* As if by `x.swap(y)`.
1487
 
1488
  ##### `shared_lock` observers <a id="thread.lock.shared.obs">[[thread.lock.shared.obs]]</a>
1489
 
1490
  ``` cpp
1491
  bool owns_lock() const noexcept;
 
1510
  ``` cpp
1511
  template <class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
1512
  ```
1513
 
1514
  *Requires:* Each template parameter type shall meet the `Lockable`
1515
+ requirements.
1516
+
1517
+ [*Note 1*: The `unique_lock` class template meets these requirements
1518
+ when suitably instantiated. — *end note*]
1519
 
1520
  *Effects:* Calls `try_lock()` for each argument in order beginning with
1521
  the first until all arguments have been processed or a call to
1522
  `try_lock()` fails, either by returning `false` or by throwing an
1523
  exception. If a call to `try_lock()` fails, `unlock()` shall be called
1524
  for all prior arguments and there shall be no further calls to
1525
  `try_lock()`.
1526
 
1527
  *Returns:* `-1` if all calls to `try_lock()` returned `true`, otherwise
1528
+ a zero-based index value that indicates the argument for which
1529
+ `try_lock()` returned `false`.
1530
 
1531
  ``` cpp
1532
  template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
1533
  ```
1534
 
1535
  *Requires:* Each template parameter type shall meet the `Lockable`
1536
+ requirements,
1537
+
1538
+ [*Note 2*: The `unique_lock` class template meets these requirements
1539
+ when suitably instantiated. — *end note*]
1540
 
1541
  *Effects:* All arguments are locked via a sequence of calls to `lock()`,
1542
  `try_lock()`, or `unlock()` on each argument. The sequence of calls
1543
+ shall not result in deadlock, but is otherwise unspecified.
1544
+
1545
+ [*Note 3*: A deadlock avoidance algorithm such as try-and-back-off must
1546
+ be used, but the specific algorithm is not specified to avoid
1547
+ over-constraining implementations. *end note*]
1548
+
1549
+ If a call to `lock()` or `try_lock()` throws an exception, `unlock()`
1550
+ shall be called for any argument that had been locked by a call to
1551
+ `lock()` or `try_lock()`.
1552
 
1553
  ### Call once <a id="thread.once">[[thread.once]]</a>
1554
 
1555
+ #### Struct `once_flag` <a id="thread.once.onceflag">[[thread.once.onceflag]]</a>
1556
+
1557
+ ``` cpp
1558
+ namespace std {
1559
+ struct once_flag {
1560
+ constexpr once_flag() noexcept;
1561
+
1562
+ once_flag(const once_flag&) = delete;
1563
+ once_flag& operator=(const once_flag&) = delete;
1564
+ };
1565
+ }
1566
+ ```
1567
+
1568
  The class `once_flag` is an opaque data structure that `call_once` uses
1569
  to initialize data without causing a data race or deadlock.
1570
 
 
 
1571
  ``` cpp
1572
  constexpr once_flag() noexcept;
1573
  ```
1574
 
1575
  *Effects:* Constructs an object of type `once_flag`.
1576
 
1577
  *Synchronization:* The construction of a `once_flag` object is not
1578
  synchronized.
1579
 
1580
+ *Postconditions:* The object’s internal state is set to indicate to an
1581
+ invocation of `call_once` with the object as its initial argument that
1582
+ no function has been called.
1583
 
1584
  #### Function `call_once` <a id="thread.once.callonce">[[thread.once.callonce]]</a>
1585
 
1586
  ``` cpp
1587
  template<class Callable, class... Args>
1588
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
1589
  ```
1590
 
1591
+ *Requires:*
1592
+
1593
+ ``` cpp
1594
+ INVOKE(std::forward<Callable>(func), std::forward<Args>(args)...)
1595
+ ```
1596
+
1597
+ (see [[func.require]]) shall be a valid expression.
1598
 
1599
  *Effects:* An execution of `call_once` that does not call its `func` is
1600
  a *passive* execution. An execution of `call_once` that calls its `func`
1601
+ is an *active* execution. An active execution shall call *INVOKE*(
1602
+ std::forward\<Callable\>(func), std::forward\<Args\>(args)...). If such
1603
+ a call to `func` throws an exception the execution is *exceptional*,
1604
+ otherwise it is *returning*. An exceptional execution shall propagate
1605
+ the exception to the caller of `call_once`. Among all executions of
1606
+ `call_once` for any given `once_flag`: at most one shall be a returning
1607
+ execution; if there is a returning execution, it shall be the last
1608
+ active execution; and there are passive executions only if there is a
1609
+ returning execution.
1610
+
1611
+ [*Note 1*: Passive executions allow other threads to reliably observe
1612
+ the results produced by the earlier returning execution. — *end note*]
1613
 
1614
  *Synchronization:* For any given `once_flag`: all active executions
1615
  occur in a total order; completion of an active execution synchronizes
1616
  with ([[intro.multithread]]) the start of the next one in this total
1617
  order; and the returning execution synchronizes with the return from all
1618
  passive executions.
1619
 
1620
  *Throws:* `system_error` when an exception is
1621
  required ([[thread.req.exception]]), or any exception thrown by `func`.
1622
 
1623
+ [*Example 1*:
1624
+
1625
  ``` cpp
1626
  // global flag, regular function
1627
  void init();
1628
  std::once_flag flag;
1629
 
 
1648
  public:
1649
  void verify() { std::call_once(verified, &information::verifier, *this); }
1650
  };
1651
  ```
1652
 
1653
+ — *end example*]
1654
+