From Jason Turner

[thread.condition.condvarany]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpz4jb_ft9/{from.md → to.md} +132 -39
tmp/tmpz4jb_ft9/{from.md → to.md} RENAMED
@@ -1,14 +1,14 @@
1
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
2
 
3
- A `Lock` type shall meet the `BasicLockable` requirements (
4
- [[thread.req.lockable.basic]]).
5
 
6
  [*Note 1*: All of the standard mutex types meet this requirement. If a
7
  `Lock` type other than one of the standard mutex types or a
8
  `unique_lock` wrapper for a standard mutex type is used with
9
- `condition_variable_any`, the user must ensure that any necessary
10
  synchronization is in place with respect to the predicate associated
11
  with the `condition_variable_any` instance. — *end note*]
12
 
13
  ``` cpp
14
  namespace std {
@@ -20,10 +20,12 @@ namespace std {
20
  condition_variable_any(const condition_variable_any&) = delete;
21
  condition_variable_any& operator=(const condition_variable_any&) = delete;
22
 
23
  void notify_one() noexcept;
24
  void notify_all() noexcept;
 
 
25
  template<class Lock>
26
  void wait(Lock& lock);
27
  template<class Lock, class Predicate>
28
  void wait(Lock& lock, Predicate pred);
29
 
@@ -33,24 +35,31 @@ namespace std {
33
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time,
34
  Predicate pred);
35
  template<class Lock, class Rep, class Period>
36
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
37
  template<class Lock, class Rep, class Period, class Predicate>
38
- bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time,
39
- Predicate pred);
 
 
 
 
 
 
 
 
 
40
  };
41
  }
42
  ```
43
 
44
  ``` cpp
45
  condition_variable_any();
46
  ```
47
 
48
- *Effects:* Constructs an object of type `condition_variable_any`.
49
-
50
  *Throws:* `bad_alloc` or `system_error` when an exception is
51
- required ([[thread.req.exception]]).
52
 
53
  *Error conditions:*
54
 
55
  - `resource_unavailable_try_again` — if some non-memory resource
56
  limitation prevents initialization.
@@ -59,24 +68,22 @@ required ([[thread.req.exception]]).
59
 
60
  ``` cpp
61
  ~condition_variable_any();
62
  ```
63
 
64
- *Requires:* There shall be no thread blocked on `*this`.
65
 
66
- [*Note 1*: That is, all threads shall have been notified; they may
67
  subsequently block on the lock specified in the wait. This relaxes the
68
  usual rules, which would have required all wait calls to happen before
69
- destruction. Only the notification to unblock the wait must happen
70
- before destruction. The user must take care to ensure that no threads
71
  wait on `*this` once the destructor has been started, especially when
72
  the waiting threads are calling the wait functions in a loop or using
73
  the overloads of `wait`, `wait_for`, or `wait_until` that take a
74
  predicate. — *end note*]
75
 
76
- *Effects:* Destroys the object.
77
-
78
  ``` cpp
79
  void notify_one() noexcept;
80
  ```
81
 
82
  *Effects:* If any threads are blocked waiting for `*this`, unblocks one
@@ -86,34 +93,32 @@ of those threads.
86
  void notify_all() noexcept;
87
  ```
88
 
89
  *Effects:* Unblocks all threads that are blocked waiting for `*this`.
90
 
 
 
91
  ``` cpp
92
  template<class Lock>
93
  void wait(Lock& lock);
94
  ```
95
 
96
- [*Note 2*: If any of the `wait` functions exits via an exception, it is
97
- unspecified whether the `Lock` is held. One can use a `Lock` type that
98
- allows to query that, such as the `unique_lock` wrapper. — *end note*]
99
-
100
  *Effects:*
101
 
102
  - Atomically calls `lock.unlock()` and blocks on `*this`.
103
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
104
  and returns.
105
  - The function will unblock when signaled by a call to `notify_one()`, a
106
  call to `notify_all()`, or spuriously.
107
 
108
  *Remarks:* If the function fails to meet the postcondition,
109
- `terminate()` shall be called ([[except.terminate]]).
110
 
111
- [*Note 3*: This can happen if the re-locking of the mutex throws an
112
  exception. — *end note*]
113
 
114
- *Postconditions:* `lock` is locked by the calling thread.
115
 
116
  *Throws:* Nothing.
117
 
118
  ``` cpp
119
  template<class Lock, class Predicate>
@@ -137,28 +142,27 @@ template <class Lock, class Clock, class Duration>
137
  - Atomically calls `lock.unlock()` and blocks on `*this`.
138
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
139
  and returns.
140
  - The function will unblock when signaled by a call to `notify_one()`, a
141
  call to `notify_all()`, expiration of the absolute
142
- timeout ([[thread.req.timing]]) specified by `abs_time`, or
143
- spuriously.
144
- - If the function exits via an exception, `lock.lock()` shall be called
145
- prior to exiting the function.
146
 
147
  *Remarks:* If the function fails to meet the postcondition,
148
- `terminate()` shall be called ([[except.terminate]]).
149
 
150
- [*Note 4*: This can happen if the re-locking of the mutex throws an
151
  exception. — *end note*]
152
 
153
- *Postconditions:* `lock` is locked by the calling thread.
154
 
155
  *Returns:* `cv_status::timeout` if the absolute
156
- timeout ([[thread.req.timing]]) specified by `abs_time` expired,
157
- otherwise `cv_status::no_timeout`.
158
 
159
- *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
160
 
161
  ``` cpp
162
  template<class Lock, class Rep, class Period>
163
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
164
  ```
@@ -168,22 +172,22 @@ template <class Lock, class Rep, class Period>
168
  ``` cpp
169
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
170
  ```
171
 
172
  *Returns:* `cv_status::timeout` if the relative
173
- timeout ([[thread.req.timing]]) specified by `rel_time` expired,
174
- otherwise `cv_status::no_timeout`.
175
 
176
  *Remarks:* If the function fails to meet the postcondition,
177
- `terminate()` shall be called ([[except.terminate]]).
178
 
179
- [*Note 5*: This can happen if the re-locking of the mutex throws an
180
  exception. — *end note*]
181
 
182
- *Postconditions:* `lock` is locked by the calling thread.
183
 
184
- *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
185
 
186
  ``` cpp
187
  template<class Lock, class Clock, class Duration, class Predicate>
188
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
189
  ```
@@ -195,14 +199,14 @@ while (!pred())
195
  if (wait_until(lock, abs_time) == cv_status::timeout)
196
  return pred();
197
  return true;
198
  ```
199
 
200
- [*Note 6*: There is no blocking if `pred()` is initially `true`, or if
201
  the timeout has already expired. — *end note*]
202
 
203
- [*Note 7*: The returned value indicates whether the predicate evaluates
204
  to `true` regardless of whether the timeout was
205
  triggered. — *end note*]
206
 
207
  ``` cpp
208
  template<class Lock, class Rep, class Period, class Predicate>
@@ -213,5 +217,94 @@ template <class Lock, class Rep, class Period, class Predicate>
213
 
214
  ``` cpp
215
  return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
216
  ```
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
2
 
3
+ A `Lock` type shall meet the *Cpp17BasicLockable* requirements
4
+ [[thread.req.lockable.basic]].
5
 
6
  [*Note 1*: All of the standard mutex types meet this requirement. If a
7
  `Lock` type other than one of the standard mutex types or a
8
  `unique_lock` wrapper for a standard mutex type is used with
9
+ `condition_variable_any`, the user should ensure that any necessary
10
  synchronization is in place with respect to the predicate associated
11
  with the `condition_variable_any` instance. — *end note*]
12
 
13
  ``` cpp
14
  namespace std {
 
20
  condition_variable_any(const condition_variable_any&) = delete;
21
  condition_variable_any& operator=(const condition_variable_any&) = delete;
22
 
23
  void notify_one() noexcept;
24
  void notify_all() noexcept;
25
+
26
+ // [thread.condvarany.wait], noninterruptible waits
27
  template<class Lock>
28
  void wait(Lock& lock);
29
  template<class Lock, class Predicate>
30
  void wait(Lock& lock, Predicate pred);
31
 
 
35
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time,
36
  Predicate pred);
37
  template<class Lock, class Rep, class Period>
38
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
39
  template<class Lock, class Rep, class Period, class Predicate>
40
+ bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
41
+
42
+ // [thread.condvarany.intwait], interruptible waits
43
+ template<class Lock, class Predicate>
44
+ bool wait(Lock& lock, stop_token stoken, Predicate pred);
45
+ template<class Lock, class Clock, class Duration, class Predicate>
46
+ bool wait_until(Lock& lock, stop_token stoken,
47
+ const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
48
+ template<class Lock, class Rep, class Period, class Predicate>
49
+ bool wait_for(Lock& lock, stop_token stoken,
50
+ const chrono::duration<Rep, Period>& rel_time, Predicate pred);
51
  };
52
  }
53
  ```
54
 
55
  ``` cpp
56
  condition_variable_any();
57
  ```
58
 
 
 
59
  *Throws:* `bad_alloc` or `system_error` when an exception is
60
+ required [[thread.req.exception]].
61
 
62
  *Error conditions:*
63
 
64
  - `resource_unavailable_try_again` — if some non-memory resource
65
  limitation prevents initialization.
 
68
 
69
  ``` cpp
70
  ~condition_variable_any();
71
  ```
72
 
73
+ *Preconditions:* There is no thread blocked on `*this`.
74
 
75
+ [*Note 1*: That is, all threads have been notified; they could
76
  subsequently block on the lock specified in the wait. This relaxes the
77
  usual rules, which would have required all wait calls to happen before
78
+ destruction. Only the notification to unblock the wait needs to happen
79
+ before destruction. The user should take care to ensure that no threads
80
  wait on `*this` once the destructor has been started, especially when
81
  the waiting threads are calling the wait functions in a loop or using
82
  the overloads of `wait`, `wait_for`, or `wait_until` that take a
83
  predicate. — *end note*]
84
 
 
 
85
  ``` cpp
86
  void notify_one() noexcept;
87
  ```
88
 
89
  *Effects:* If any threads are blocked waiting for `*this`, unblocks one
 
93
  void notify_all() noexcept;
94
  ```
95
 
96
  *Effects:* Unblocks all threads that are blocked waiting for `*this`.
97
 
98
+ #### Noninterruptible waits <a id="thread.condvarany.wait">[[thread.condvarany.wait]]</a>
99
+
100
  ``` cpp
101
  template<class Lock>
102
  void wait(Lock& lock);
103
  ```
104
 
 
 
 
 
105
  *Effects:*
106
 
107
  - Atomically calls `lock.unlock()` and blocks on `*this`.
108
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
109
  and returns.
110
  - The function will unblock when signaled by a call to `notify_one()`, a
111
  call to `notify_all()`, or spuriously.
112
 
113
  *Remarks:* If the function fails to meet the postcondition,
114
+ `terminate()` is called [[except.terminate]].
115
 
116
+ [*Note 1*: This can happen if the re-locking of the mutex throws an
117
  exception. — *end note*]
118
 
119
+ *Ensures:* `lock` is locked by the calling thread.
120
 
121
  *Throws:* Nothing.
122
 
123
  ``` cpp
124
  template<class Lock, class Predicate>
 
142
  - Atomically calls `lock.unlock()` and blocks on `*this`.
143
  - When unblocked, calls `lock.lock()` (possibly blocking on the lock)
144
  and returns.
145
  - The function will unblock when signaled by a call to `notify_one()`, a
146
  call to `notify_all()`, expiration of the absolute
147
+ timeout [[thread.req.timing]] specified by `abs_time`, or spuriously.
148
+ - If the function exits via an exception, `lock.lock()` is called prior
149
+ to exiting the function.
 
150
 
151
  *Remarks:* If the function fails to meet the postcondition,
152
+ `terminate()` is called [[except.terminate]].
153
 
154
+ [*Note 2*: This can happen if the re-locking of the mutex throws an
155
  exception. — *end note*]
156
 
157
+ *Ensures:* `lock` is locked by the calling thread.
158
 
159
  *Returns:* `cv_status::timeout` if the absolute
160
+ timeout [[thread.req.timing]] specified by `abs_time` expired, otherwise
161
+ `cv_status::no_timeout`.
162
 
163
+ *Throws:* Timeout-related exceptions [[thread.req.timing]].
164
 
165
  ``` cpp
166
  template<class Lock, class Rep, class Period>
167
  cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
168
  ```
 
172
  ``` cpp
173
  return wait_until(lock, chrono::steady_clock::now() + rel_time);
174
  ```
175
 
176
  *Returns:* `cv_status::timeout` if the relative
177
+ timeout [[thread.req.timing]] specified by `rel_time` expired, otherwise
178
+ `cv_status::no_timeout`.
179
 
180
  *Remarks:* If the function fails to meet the postcondition,
181
+ `terminate()` is called [[except.terminate]].
182
 
183
+ [*Note 3*: This can happen if the re-locking of the mutex throws an
184
  exception. — *end note*]
185
 
186
+ *Ensures:* `lock` is locked by the calling thread.
187
 
188
+ *Throws:* Timeout-related exceptions [[thread.req.timing]].
189
 
190
  ``` cpp
191
  template<class Lock, class Clock, class Duration, class Predicate>
192
  bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
193
  ```
 
199
  if (wait_until(lock, abs_time) == cv_status::timeout)
200
  return pred();
201
  return true;
202
  ```
203
 
204
+ [*Note 4*: There is no blocking if `pred()` is initially `true`, or if
205
  the timeout has already expired. — *end note*]
206
 
207
+ [*Note 5*: The returned value indicates whether the predicate evaluates
208
  to `true` regardless of whether the timeout was
209
  triggered. — *end note*]
210
 
211
  ``` cpp
212
  template<class Lock, class Rep, class Period, class Predicate>
 
217
 
218
  ``` cpp
219
  return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
220
  ```
221
 
222
+ #### Interruptible waits <a id="thread.condvarany.intwait">[[thread.condvarany.intwait]]</a>
223
+
224
+ The following wait functions will be notified when there is a stop
225
+ request on the passed `stop_token`. In that case the functions return
226
+ immediately, returning `false` if the predicate evaluates to `false`.
227
+
228
+ ``` cpp
229
+ template<class Lock, class Predicate>
230
+ bool wait(Lock& lock, stop_token stoken, Predicate pred);
231
+ ```
232
+
233
+ *Effects:* Registers for the duration of this call `*this` to get
234
+ notified on a stop request on `stoken` during this call and then
235
+ equivalent to:
236
+
237
+ ``` cpp
238
+ while (!stoken.stop_requested()) {
239
+ if (pred())
240
+ return true;
241
+ wait(lock);
242
+ }
243
+ return pred();
244
+ ```
245
+
246
+ [*Note 1*: The returned value indicates whether the predicate evaluated
247
+ to `true` regardless of whether there was a stop request. — *end note*]
248
+
249
+ *Ensures:* `lock` is locked by the calling thread.
250
+
251
+ *Remarks:* If the function fails to meet the postcondition, `terminate`
252
+ is called [[except.terminate]].
253
+
254
+ [*Note 2*: This can happen if the re-locking of the mutex throws an
255
+ exception. — *end note*]
256
+
257
+ *Throws:* Any exception thrown by `pred`.
258
+
259
+ ``` cpp
260
+ template<class Lock, class Clock, class Duration, class Predicate>
261
+ bool wait_until(Lock& lock, stop_token stoken,
262
+ const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
263
+ ```
264
+
265
+ *Effects:* Registers for the duration of this call `*this` to get
266
+ notified on a stop request on `stoken` during this call and then
267
+ equivalent to:
268
+
269
+ ``` cpp
270
+ while (!stoken.stop_requested()) {
271
+ if (pred())
272
+ return true;
273
+ if (cv.wait_until(lock, abs_time) == cv_status::timeout)
274
+ return pred();
275
+ }
276
+ return pred();
277
+ ```
278
+
279
+ [*Note 3*: There is no blocking if `pred()` is initially `true`,
280
+ `stoken.stop_requested()` was already `true` or the timeout has already
281
+ expired. — *end note*]
282
+
283
+ [*Note 4*: The returned value indicates whether the predicate evaluated
284
+ to `true` regardless of whether the timeout was triggered or a stop
285
+ request was made. — *end note*]
286
+
287
+ *Ensures:* `lock` is locked by the calling thread.
288
+
289
+ *Remarks:* If the function fails to meet the postcondition, `terminate`
290
+ is called [[except.terminate]].
291
+
292
+ [*Note 5*: This can happen if the re-locking of the mutex throws an
293
+ exception. — *end note*]
294
+
295
+ *Throws:* Timeout-related exceptions [[thread.req.timing]], or any
296
+ exception thrown by `pred`.
297
+
298
+ ``` cpp
299
+ template<class Lock, class Rep, class Period, class Predicate>
300
+ bool wait_for(Lock& lock, stop_token stoken,
301
+ const chrono::duration<Rep, Period>& rel_time, Predicate pred);
302
+ ```
303
+
304
+ *Effects:* Equivalent to:
305
+
306
+ ``` cpp
307
+ return wait_until(lock, std::move(stoken), chrono::steady_clock::now() + rel_time,
308
+ std::move(pred));
309
+ ```
310
+