From Jason Turner

[thread.condition]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp8g4eg4x4/{from.md → to.md} +98 -94
tmp/tmp8g4eg4x4/{from.md → to.md} RENAMED
@@ -1,7 +1,9 @@
1
  ## Condition variables <a id="thread.condition">[[thread.condition]]</a>
2
 
 
 
3
  Condition variables provide synchronization primitives used to block a
4
  thread until notified by some other thread that some condition is met or
5
  until a system time is reached. Class `condition_variable` provides a
6
  condition variable that can only wait on an object of type
7
  `unique_lock<mutex>`, allowing the implementation to be more efficient.
@@ -21,22 +23,25 @@ three atomic parts:
21
  3. the reacquisition of the lock.
22
 
23
  The implementation behaves as if all executions of `notify_one`,
24
  `notify_all`, and each part of the `wait`, `wait_for`, and `wait_until`
25
  executions are executed in a single unspecified total order consistent
26
- with the "happens before" order.
27
 
28
  Condition variable construction and destruction need not be
29
  synchronized.
30
 
31
  ### Header `<condition_variable>` synopsis <a id="condition.variable.syn">[[condition.variable.syn]]</a>
32
 
33
  ``` cpp
34
  namespace std {
 
35
  class condition_variable;
 
36
  class condition_variable_any;
37
 
 
38
  void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
39
 
40
  enum class cv_status { no_timeout, timeout };
41
  }
42
  ```
@@ -67,16 +72,12 @@ cond.notify_all();
67
 
68
  *Synchronization:* The implied `lk.unlock()` call is sequenced after the
69
  destruction of all objects with thread storage duration associated with
70
  the current thread.
71
 
72
- [*Note 1*: The supplied lock will be held until the thread exits, and
73
- care should be taken to ensure that this does not cause deadlock due to
74
- lock ordering issues. After calling `notify_all_at_thread_exit` it is
75
- recommended that the thread should be exited as soon as possible, and
76
- that no blocking or time-consuming tasks are run on that
77
- thread. — *end note*]
78
 
79
  [*Note 2*: It is the user’s responsibility to ensure that waiting
80
  threads do not erroneously assume that the thread has finished if they
81
  experience spurious wakeups. This typically requires that the condition
82
  being waited for is satisfied while holding the lock on `lk`, and that
@@ -140,18 +141,18 @@ required [[thread.req.exception]].
140
  ~condition_variable();
141
  ```
142
 
143
  *Preconditions:* There is no thread blocked on `*this`.
144
 
145
- [*Note 1*: That is, all threads have been notified; they could
146
  subsequently block on the lock specified in the wait. This relaxes the
147
  usual rules, which would have required all wait calls to happen before
148
  destruction. Only the notification to unblock the wait needs to happen
149
- before destruction. The user should take care to ensure that no threads
150
- wait on `*this` once the destructor has been started, especially when
151
- the waiting threads are calling the wait functions in a loop or using
152
- the overloads of `wait`, `wait_for`, or `wait_until` that take a
153
  predicate. — *end note*]
154
 
155
  ``` cpp
156
  void notify_one() noexcept;
157
  ```
@@ -183,21 +184,21 @@ locked by the calling thread, and either
183
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock),
184
  then returns.
185
  - The function will unblock when signaled by a call to `notify_one()` or
186
  a call to `notify_all()`, or spuriously.
187
 
188
- *Remarks:* If the function fails to meet the postcondition,
189
- `terminate()` is called [[except.terminate]].
190
-
191
- [*Note 2*: This can happen if the re-locking of the mutex throws an
192
- exception. — *end note*]
193
-
194
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
195
  the calling thread.
196
 
197
  *Throws:* Nothing.
198
 
 
 
 
 
 
 
199
  ``` cpp
200
  template<class Predicate>
201
  void wait(unique_lock<mutex>& lock, Predicate pred);
202
  ```
203
 
@@ -214,21 +215,21 @@ locked by the calling thread, and either
214
  ``` cpp
215
  while (!pred())
216
  wait(lock);
217
  ```
218
 
219
- *Remarks:* If the function fails to meet the postcondition,
220
- `terminate()` is called [[except.terminate]].
221
-
222
- [*Note 3*: This can happen if the re-locking of the mutex throws an
223
- exception. — *end note*]
224
-
225
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
226
  the calling thread.
227
 
228
  *Throws:* Any exception thrown by `pred`.
229
 
 
 
 
 
 
 
230
  ``` cpp
231
  template<class Clock, class Duration>
232
  cv_status wait_until(unique_lock<mutex>& lock,
233
  const chrono::time_point<Clock, Duration>& abs_time);
234
  ```
@@ -250,25 +251,25 @@ locked by the calling thread, and either
250
  call to `notify_all()`, expiration of the absolute
251
  timeout [[thread.req.timing]] specified by `abs_time`, or spuriously.
252
  - If the function exits via an exception, `lock.lock()` is called prior
253
  to exiting the function.
254
 
 
 
 
 
 
 
 
 
 
255
  *Remarks:* If the function fails to meet the postcondition,
256
- `terminate()` is called [[except.terminate]].
257
 
258
  [*Note 4*: This can happen if the re-locking of the mutex throws an
259
  exception. — *end note*]
260
 
261
- *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
262
- the calling thread.
263
-
264
- *Returns:* `cv_status::timeout` if the absolute
265
- timeout [[thread.req.timing]] specified by `abs_time` expired, otherwise
266
- `cv_status::no_timeout`.
267
-
268
- *Throws:* Timeout-related exceptions [[thread.req.timing]].
269
-
270
  ``` cpp
271
  template<class Rep, class Period>
272
  cv_status wait_for(unique_lock<mutex>& lock,
273
  const chrono::duration<Rep, Period>& rel_time);
274
  ```
@@ -285,25 +286,25 @@ locked by the calling thread, and either
285
 
286
  ``` cpp
287
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
288
  ```
289
 
 
 
 
290
  *Returns:* `cv_status::timeout` if the relative
291
  timeout [[thread.req.timing]] specified by `rel_time` expired, otherwise
292
  `cv_status::no_timeout`.
293
 
294
- *Remarks:* If the function fails to meet the postcondition,
295
- `terminate()` is called [[except.terminate]].
 
 
296
 
297
  [*Note 5*: This can happen if the re-locking of the mutex throws an
298
  exception. — *end note*]
299
 
300
- *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
301
- the calling thread.
302
-
303
- *Throws:* Timeout-related exceptions [[thread.req.timing]].
304
-
305
  ``` cpp
306
  template<class Clock, class Duration, class Predicate>
307
  bool wait_until(unique_lock<mutex>& lock,
308
  const chrono::time_point<Clock, Duration>& abs_time,
309
  Predicate pred);
@@ -324,26 +325,26 @@ while (!pred())
324
  if (wait_until(lock, abs_time) == cv_status::timeout)
325
  return pred();
326
  return true;
327
  ```
328
 
329
- *Remarks:* If the function fails to meet the postcondition,
330
- `terminate()` is called [[except.terminate]].
331
-
332
- [*Note 6*: This can happen if the re-locking of the mutex throws an
333
- exception. — *end note*]
334
-
335
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
336
  the calling thread.
337
 
338
- [*Note 7*: The returned value indicates whether the predicate evaluated
339
  to `true` regardless of whether the timeout was
340
  triggered. — *end note*]
341
 
342
  *Throws:* Timeout-related exceptions [[thread.req.timing]] or any
343
  exception thrown by `pred`.
344
 
 
 
 
 
 
 
345
  ``` cpp
346
  template<class Rep, class Period, class Predicate>
347
  bool wait_for(unique_lock<mutex>& lock,
348
  const chrono::duration<Rep, Period>& rel_time,
349
  Predicate pred);
@@ -364,37 +365,40 @@ return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred))
364
  ```
365
 
366
  [*Note 8*: There is no blocking if `pred()` is initially `true`, even
367
  if the timeout has already expired. — *end note*]
368
 
369
- *Remarks:* If the function fails to meet the postcondition,
370
- `terminate()` is called [[except.terminate]].
371
-
372
- [*Note 9*: This can happen if the re-locking of the mutex throws an
373
- exception. — *end note*]
374
-
375
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
376
  the calling thread.
377
 
378
- [*Note 10*: The returned value indicates whether the predicate
379
- evaluates to `true` regardless of whether the timeout was
380
  triggered. — *end note*]
381
 
382
  *Throws:* Timeout-related exceptions [[thread.req.timing]] or any
383
  exception thrown by `pred`.
384
 
 
 
 
 
 
 
385
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
386
 
387
- A `Lock` type shall meet the *Cpp17BasicLockable* requirements
388
- [[thread.req.lockable.basic]].
 
 
 
389
 
390
  [*Note 1*: All of the standard mutex types meet this requirement. If a
391
- `Lock` type other than one of the standard mutex types or a
392
- `unique_lock` wrapper for a standard mutex type is used with
393
- `condition_variable_any`, the user should ensure that any necessary
394
- synchronization is in place with respect to the predicate associated
395
- with the `condition_variable_any` instance. — *end note*]
396
 
397
  ``` cpp
398
  namespace std {
399
  class condition_variable_any {
400
  public:
@@ -454,18 +458,18 @@ required [[thread.req.exception]].
454
  ~condition_variable_any();
455
  ```
456
 
457
  *Preconditions:* There is no thread blocked on `*this`.
458
 
459
- [*Note 1*: That is, all threads have been notified; they could
460
  subsequently block on the lock specified in the wait. This relaxes the
461
  usual rules, which would have required all wait calls to happen before
462
  destruction. Only the notification to unblock the wait needs to happen
463
- before destruction. The user should take care to ensure that no threads
464
- wait on `*this` once the destructor has been started, especially when
465
- the waiting threads are calling the wait functions in a loop or using
466
- the overloads of `wait`, `wait_for`, or `wait_until` that take a
467
  predicate. — *end note*]
468
 
469
  ``` cpp
470
  void notify_one() noexcept;
471
  ```
@@ -492,20 +496,20 @@ template<class Lock>
492
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
493
  and returns.
494
  - The function will unblock when signaled by a call to `notify_one()`, a
495
  call to `notify_all()`, or spuriously.
496
 
 
 
 
 
497
  *Remarks:* If the function fails to meet the postcondition,
498
- `terminate()` is called [[except.terminate]].
499
 
500
  [*Note 1*: This can happen if the re-locking of the mutex throws an
501
  exception. — *end note*]
502
 
503
- *Ensures:* `lock` is locked by the calling thread.
504
-
505
- *Throws:* Nothing.
506
-
507
  ``` cpp
508
  template<class Lock, class Predicate>
509
  void wait(Lock& lock, Predicate pred);
510
  ```
511
 
@@ -530,24 +534,24 @@ template<class Lock, class Clock, class Duration>
530
  call to `notify_all()`, expiration of the absolute
531
  timeout [[thread.req.timing]] specified by `abs_time`, or spuriously.
532
  - If the function exits via an exception, `lock.lock()` is called prior
533
  to exiting the function.
534
 
535
- *Remarks:* If the function fails to meet the postcondition,
536
- `terminate()` is called [[except.terminate]].
537
-
538
- [*Note 2*: This can happen if the re-locking of the mutex throws an
539
- exception. — *end note*]
540
-
541
  *Ensures:* `lock` is locked by the calling thread.
542
 
543
  *Returns:* `cv_status::timeout` if the absolute
544
  timeout [[thread.req.timing]] specified by `abs_time` expired, otherwise
545
  `cv_status::no_timeout`.
546
 
547
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
548
 
 
 
 
 
 
 
549
  ``` cpp
550
  template<class Lock, class Rep, class Period>
551
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
552
  ```
553
 
@@ -555,24 +559,24 @@ template<class Lock, class Rep, class Period>
555
 
556
  ``` cpp
557
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
558
  ```
559
 
 
 
560
  *Returns:* `cv_status::timeout` if the relative
561
  timeout [[thread.req.timing]] specified by `rel_time` expired, otherwise
562
  `cv_status::no_timeout`.
563
 
564
- *Remarks:* If the function fails to meet the postcondition,
565
- `terminate()` is called [[except.terminate]].
 
 
566
 
567
  [*Note 3*: This can happen if the re-locking of the mutex throws an
568
  exception. — *end note*]
569
 
570
- *Ensures:* `lock` is locked by the calling thread.
571
-
572
- *Throws:* Timeout-related exceptions [[thread.req.timing]].
573
-
574
  ``` cpp
575
  template<class Lock, class Clock, class Duration, class Predicate>
576
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
577
  ```
578
 
@@ -630,18 +634,18 @@ return pred();
630
  [*Note 1*: The returned value indicates whether the predicate evaluated
631
  to `true` regardless of whether there was a stop request. — *end note*]
632
 
633
  *Ensures:* `lock` is locked by the calling thread.
634
 
 
 
635
  *Remarks:* If the function fails to meet the postcondition, `terminate`
636
  is called [[except.terminate]].
637
 
638
  [*Note 2*: This can happen if the re-locking of the mutex throws an
639
  exception. — *end note*]
640
 
641
- *Throws:* Any exception thrown by `pred`.
642
-
643
  ``` cpp
644
  template<class Lock, class Clock, class Duration, class Predicate>
645
  bool wait_until(Lock& lock, stop_token stoken,
646
  const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
647
  ```
@@ -652,11 +656,11 @@ equivalent to:
652
 
653
  ``` cpp
654
  while (!stoken.stop_requested()) {
655
  if (pred())
656
  return true;
657
- if (cv.wait_until(lock, abs_time) == cv_status::timeout)
658
  return pred();
659
  }
660
  return pred();
661
  ```
662
 
@@ -668,19 +672,19 @@ expired. — *end note*]
668
  to `true` regardless of whether the timeout was triggered or a stop
669
  request was made. — *end note*]
670
 
671
  *Ensures:* `lock` is locked by the calling thread.
672
 
673
- *Remarks:* If the function fails to meet the postcondition, `terminate`
674
- is called [[except.terminate]].
675
-
676
- [*Note 5*: This can happen if the re-locking of the mutex throws an
677
- exception. — *end note*]
678
-
679
  *Throws:* Timeout-related exceptions [[thread.req.timing]], or any
680
  exception thrown by `pred`.
681
 
 
 
 
 
 
 
682
  ``` cpp
683
  template<class Lock, class Rep, class Period, class Predicate>
684
  bool wait_for(Lock& lock, stop_token stoken,
685
  const chrono::duration<Rep, Period>& rel_time, Predicate pred);
686
  ```
 
1
  ## Condition variables <a id="thread.condition">[[thread.condition]]</a>
2
 
3
+ ### General <a id="thread.condition.general">[[thread.condition.general]]</a>
4
+
5
  Condition variables provide synchronization primitives used to block a
6
  thread until notified by some other thread that some condition is met or
7
  until a system time is reached. Class `condition_variable` provides a
8
  condition variable that can only wait on an object of type
9
  `unique_lock<mutex>`, allowing the implementation to be more efficient.
 
23
  3. the reacquisition of the lock.
24
 
25
  The implementation behaves as if all executions of `notify_one`,
26
  `notify_all`, and each part of the `wait`, `wait_for`, and `wait_until`
27
  executions are executed in a single unspecified total order consistent
28
+ with the happens before order.
29
 
30
  Condition variable construction and destruction need not be
31
  synchronized.
32
 
33
  ### Header `<condition_variable>` synopsis <a id="condition.variable.syn">[[condition.variable.syn]]</a>
34
 
35
  ``` cpp
36
  namespace std {
37
+ // [thread.condition.condvar], class condition_variable
38
  class condition_variable;
39
+ // [thread.condition.condvarany], class condition_variable_any
40
  class condition_variable_any;
41
 
42
+ // [thread.condition.nonmember], non-member functions
43
  void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
44
 
45
  enum class cv_status { no_timeout, timeout };
46
  }
47
  ```
 
72
 
73
  *Synchronization:* The implied `lk.unlock()` call is sequenced after the
74
  destruction of all objects with thread storage duration associated with
75
  the current thread.
76
 
77
+ [*Note 1*: The supplied lock is held until the thread exits, which
78
+ might cause deadlock due to lock ordering issues. *end note*]
 
 
 
 
79
 
80
  [*Note 2*: It is the user’s responsibility to ensure that waiting
81
  threads do not erroneously assume that the thread has finished if they
82
  experience spurious wakeups. This typically requires that the condition
83
  being waited for is satisfied while holding the lock on `lk`, and that
 
141
  ~condition_variable();
142
  ```
143
 
144
  *Preconditions:* There is no thread blocked on `*this`.
145
 
146
+ [*Note 1*: That is, all threads have been notified; they can
147
  subsequently block on the lock specified in the wait. This relaxes the
148
  usual rules, which would have required all wait calls to happen before
149
  destruction. Only the notification to unblock the wait needs to happen
150
+ before destruction. Undefined behavior ensues if a thread waits on
151
+ `*this` once the destructor has been started, especially when the
152
+ waiting threads are calling the wait functions in a loop or using the
153
+ overloads of `wait`, `wait_for`, or `wait_until` that take a
154
  predicate. — *end note*]
155
 
156
  ``` cpp
157
  void notify_one() noexcept;
158
  ```
 
184
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock),
185
  then returns.
186
  - The function will unblock when signaled by a call to `notify_one()` or
187
  a call to `notify_all()`, or spuriously.
188
 
 
 
 
 
 
 
189
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
190
  the calling thread.
191
 
192
  *Throws:* Nothing.
193
 
194
+ *Remarks:* If the function fails to meet the postcondition,
195
+ `terminate()` is invoked [[except.terminate]].
196
+
197
+ [*Note 2*: This can happen if the re-locking of the mutex throws an
198
+ exception. — *end note*]
199
+
200
  ``` cpp
201
  template<class Predicate>
202
  void wait(unique_lock<mutex>& lock, Predicate pred);
203
  ```
204
 
 
215
  ``` cpp
216
  while (!pred())
217
  wait(lock);
218
  ```
219
 
 
 
 
 
 
 
220
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
221
  the calling thread.
222
 
223
  *Throws:* Any exception thrown by `pred`.
224
 
225
+ *Remarks:* If the function fails to meet the postcondition,
226
+ `terminate()` is invoked [[except.terminate]].
227
+
228
+ [*Note 3*: This can happen if the re-locking of the mutex throws an
229
+ exception. — *end note*]
230
+
231
  ``` cpp
232
  template<class Clock, class Duration>
233
  cv_status wait_until(unique_lock<mutex>& lock,
234
  const chrono::time_point<Clock, Duration>& abs_time);
235
  ```
 
251
  call to `notify_all()`, expiration of the absolute
252
  timeout [[thread.req.timing]] specified by `abs_time`, or spuriously.
253
  - If the function exits via an exception, `lock.lock()` is called prior
254
  to exiting the function.
255
 
256
+ *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
257
+ the calling thread.
258
+
259
+ *Returns:* `cv_status::timeout` if the absolute
260
+ timeout [[thread.req.timing]] specified by `abs_time` expired, otherwise
261
+ `cv_status::no_timeout`.
262
+
263
+ *Throws:* Timeout-related exceptions [[thread.req.timing]].
264
+
265
  *Remarks:* If the function fails to meet the postcondition,
266
+ `terminate()` is invoked [[except.terminate]].
267
 
268
  [*Note 4*: This can happen if the re-locking of the mutex throws an
269
  exception. — *end note*]
270
 
 
 
 
 
 
 
 
 
 
271
  ``` cpp
272
  template<class Rep, class Period>
273
  cv_status wait_for(unique_lock<mutex>& lock,
274
  const chrono::duration<Rep, Period>& rel_time);
275
  ```
 
286
 
287
  ``` cpp
288
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
289
  ```
290
 
291
+ *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
292
+ the calling thread.
293
+
294
  *Returns:* `cv_status::timeout` if the relative
295
  timeout [[thread.req.timing]] specified by `rel_time` expired, otherwise
296
  `cv_status::no_timeout`.
297
 
298
+ *Throws:* Timeout-related exceptions [[thread.req.timing]].
299
+
300
+ *Remarks:* If the function fails to meet the postcondition, `terminate`
301
+ is invoked [[except.terminate]].
302
 
303
  [*Note 5*: This can happen if the re-locking of the mutex throws an
304
  exception. — *end note*]
305
 
 
 
 
 
 
306
  ``` cpp
307
  template<class Clock, class Duration, class Predicate>
308
  bool wait_until(unique_lock<mutex>& lock,
309
  const chrono::time_point<Clock, Duration>& abs_time,
310
  Predicate pred);
 
325
  if (wait_until(lock, abs_time) == cv_status::timeout)
326
  return pred();
327
  return true;
328
  ```
329
 
 
 
 
 
 
 
330
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
331
  the calling thread.
332
 
333
+ [*Note 6*: The returned value indicates whether the predicate evaluated
334
  to `true` regardless of whether the timeout was
335
  triggered. — *end note*]
336
 
337
  *Throws:* Timeout-related exceptions [[thread.req.timing]] or any
338
  exception thrown by `pred`.
339
 
340
+ *Remarks:* If the function fails to meet the postcondition,
341
+ `terminate()` is invoked [[except.terminate]].
342
+
343
+ [*Note 7*: This can happen if the re-locking of the mutex throws an
344
+ exception. — *end note*]
345
+
346
  ``` cpp
347
  template<class Rep, class Period, class Predicate>
348
  bool wait_for(unique_lock<mutex>& lock,
349
  const chrono::duration<Rep, Period>& rel_time,
350
  Predicate pred);
 
365
  ```
366
 
367
  [*Note 8*: There is no blocking if `pred()` is initially `true`, even
368
  if the timeout has already expired. — *end note*]
369
 
 
 
 
 
 
 
370
  *Ensures:* `lock.owns_lock()` is `true` and `lock.mutex()` is locked by
371
  the calling thread.
372
 
373
+ [*Note 9*: The returned value indicates whether the predicate evaluates
374
+ to `true` regardless of whether the timeout was
375
  triggered. — *end note*]
376
 
377
  *Throws:* Timeout-related exceptions [[thread.req.timing]] or any
378
  exception thrown by `pred`.
379
 
380
+ *Remarks:* If the function fails to meet the postcondition,
381
+ `terminate()` is invoked [[except.terminate]].
382
+
383
+ [*Note 10*: This can happen if the re-locking of the mutex throws an
384
+ exception. — *end note*]
385
+
386
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
387
 
388
+ #### General <a id="thread.condition.condvarany.general">[[thread.condition.condvarany.general]]</a>
389
+
390
+ In this subclause [[thread.condition.condvarany]], template arguments
391
+ for template parameters named `Lock` shall meet the *Cpp17BasicLockable*
392
+ requirements [[thread.req.lockable.basic]].
393
 
394
  [*Note 1*: All of the standard mutex types meet this requirement. If a
395
+ type other than one of the standard mutex types or a `unique_lock`
396
+ wrapper for a standard mutex type is used with `condition_variable_any`,
397
+ any necessary synchronization is assumed to be in place with respect to
398
+ the predicate associated with the `condition_variable_any`
399
+ instance. — *end note*]
400
 
401
  ``` cpp
402
  namespace std {
403
  class condition_variable_any {
404
  public:
 
458
  ~condition_variable_any();
459
  ```
460
 
461
  *Preconditions:* There is no thread blocked on `*this`.
462
 
463
+ [*Note 1*: That is, all threads have been notified; they can
464
  subsequently block on the lock specified in the wait. This relaxes the
465
  usual rules, which would have required all wait calls to happen before
466
  destruction. Only the notification to unblock the wait needs to happen
467
+ before destruction. Undefined behavior ensues if a thread waits on
468
+ `*this` once the destructor has been started, especially when the
469
+ waiting threads are calling the wait functions in a loop or using the
470
+ overloads of `wait`, `wait_for`, or `wait_until` that take a
471
  predicate. — *end note*]
472
 
473
  ``` cpp
474
  void notify_one() noexcept;
475
  ```
 
496
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
497
  and returns.
498
  - The function will unblock when signaled by a call to `notify_one()`, a
499
  call to `notify_all()`, or spuriously.
500
 
501
+ *Ensures:* `lock` is locked by the calling thread.
502
+
503
+ *Throws:* Nothing.
504
+
505
  *Remarks:* If the function fails to meet the postcondition,
506
+ `terminate()` is invoked [[except.terminate]].
507
 
508
  [*Note 1*: This can happen if the re-locking of the mutex throws an
509
  exception. — *end note*]
510
 
 
 
 
 
511
  ``` cpp
512
  template<class Lock, class Predicate>
513
  void wait(Lock& lock, Predicate pred);
514
  ```
515
 
 
534
  call to `notify_all()`, expiration of the absolute
535
  timeout [[thread.req.timing]] specified by `abs_time`, or spuriously.
536
  - If the function exits via an exception, `lock.lock()` is called prior
537
  to exiting the function.
538
 
 
 
 
 
 
 
539
  *Ensures:* `lock` is locked by the calling thread.
540
 
541
  *Returns:* `cv_status::timeout` if the absolute
542
  timeout [[thread.req.timing]] specified by `abs_time` expired, otherwise
543
  `cv_status::no_timeout`.
544
 
545
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
546
 
547
+ *Remarks:* If the function fails to meet the postcondition,
548
+ `terminate()` is invoked [[except.terminate]].
549
+
550
+ [*Note 2*: This can happen if the re-locking of the mutex throws an
551
+ exception. — *end note*]
552
+
553
  ``` cpp
554
  template<class Lock, class Rep, class Period>
555
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
556
  ```
557
 
 
559
 
560
  ``` cpp
561
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
562
  ```
563
 
564
+ *Ensures:* `lock` is locked by the calling thread.
565
+
566
  *Returns:* `cv_status::timeout` if the relative
567
  timeout [[thread.req.timing]] specified by `rel_time` expired, otherwise
568
  `cv_status::no_timeout`.
569
 
570
+ *Throws:* Timeout-related exceptions [[thread.req.timing]].
571
+
572
+ *Remarks:* If the function fails to meet the postcondition, `terminate`
573
+ is invoked [[except.terminate]].
574
 
575
  [*Note 3*: This can happen if the re-locking of the mutex throws an
576
  exception. — *end note*]
577
 
 
 
 
 
578
  ``` cpp
579
  template<class Lock, class Clock, class Duration, class Predicate>
580
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
581
  ```
582
 
 
634
  [*Note 1*: The returned value indicates whether the predicate evaluated
635
  to `true` regardless of whether there was a stop request. — *end note*]
636
 
637
  *Ensures:* `lock` is locked by the calling thread.
638
 
639
+ *Throws:* Any exception thrown by `pred`.
640
+
641
  *Remarks:* If the function fails to meet the postcondition, `terminate`
642
  is called [[except.terminate]].
643
 
644
  [*Note 2*: This can happen if the re-locking of the mutex throws an
645
  exception. — *end note*]
646
 
 
 
647
  ``` cpp
648
  template<class Lock, class Clock, class Duration, class Predicate>
649
  bool wait_until(Lock& lock, stop_token stoken,
650
  const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
651
  ```
 
656
 
657
  ``` cpp
658
  while (!stoken.stop_requested()) {
659
  if (pred())
660
  return true;
661
+ if (wait_until(lock, abs_time) == cv_status::timeout)
662
  return pred();
663
  }
664
  return pred();
665
  ```
666
 
 
672
  to `true` regardless of whether the timeout was triggered or a stop
673
  request was made. — *end note*]
674
 
675
  *Ensures:* `lock` is locked by the calling thread.
676
 
 
 
 
 
 
 
677
  *Throws:* Timeout-related exceptions [[thread.req.timing]], or any
678
  exception thrown by `pred`.
679
 
680
+ *Remarks:* If the function fails to meet the postcondition, `terminate`
681
+ is called [[except.terminate]].
682
+
683
+ [*Note 5*: This can happen if the re-locking of the mutex throws an
684
+ exception. — *end note*]
685
+
686
  ``` cpp
687
  template<class Lock, class Rep, class Period, class Predicate>
688
  bool wait_for(Lock& lock, stop_token stoken,
689
  const chrono::duration<Rep, Period>& rel_time, Predicate pred);
690
  ```