From Jason Turner

[thread.stoptoken]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpsyupry8r/{from.md → to.md} +441 -0
tmp/tmpsyupry8r/{from.md → to.md} RENAMED
@@ -0,0 +1,441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Stop tokens <a id="thread.stoptoken">[[thread.stoptoken]]</a>
2
+
3
+ ### Introduction <a id="thread.stoptoken.intro">[[thread.stoptoken.intro]]</a>
4
+
5
+ This clause describes components that can be used to asynchonously
6
+ request that an operation stops execution in a timely manner, typically
7
+ because the result is no longer required. Such a request is called a
8
+ *stop request*.
9
+
10
+ `stop_source`, `stop_token`, and `stop_callback` implement semantics of
11
+ shared ownership of a *stop state*. Any `stop_source`, `stop_token`, or
12
+ `stop_callback` that shares ownership of the same stop state is an
13
+ *associated* `stop_source`, `stop_token`, or `stop_callback`,
14
+ respectively. The last remaining owner of the stop state automatically
15
+ releases the resources associated with the stop state.
16
+
17
+ A `stop_token` can be passed to an operation which can either
18
+
19
+ - actively poll the token to check if there has been a stop request, or
20
+ - register a callback using the `stop_callback` class template which
21
+ will be called in the event that a stop request is made.
22
+
23
+ A stop request made via a `stop_source` will be visible to all
24
+ associated `stop_token` and `stop_source` objects. Once a stop request
25
+ has been made it cannot be withdrawn (a subsequent stop request has no
26
+ effect).
27
+
28
+ Callbacks registered via a `stop_callback` object are called when a stop
29
+ request is first made by any associated `stop_source` object.
30
+
31
+ Calls to the functions `request_stop`, `stop_requested`, and
32
+ `stop_possible` do not introduce data races. A call to `request_stop`
33
+ that returns `true` synchronizes with a call to `stop_requested` on an
34
+ associated `stop_token` or `stop_source` object that returns `true`.
35
+ Registration of a callback synchronizes with the invocation of that
36
+ callback.
37
+
38
+ ### Header `<stop_token>` synopsis <a id="thread.stoptoken.syn">[[thread.stoptoken.syn]]</a>
39
+
40
+ ``` cpp
41
+ namespace std {
42
+ // [stoptoken], class stop_token
43
+ class stop_token;
44
+
45
+ // [stopsource], class stop_source
46
+ class stop_source;
47
+
48
+ // no-shared-stop-state indicator
49
+ struct nostopstate_t {
50
+ explicit nostopstate_t() = default;
51
+ };
52
+ inline constexpr nostopstate_t nostopstate{};
53
+
54
+ // [stopcallback], class stop_callback
55
+ template<class Callback>
56
+ class stop_callback;
57
+ }
58
+ ```
59
+
60
+ ### Class `stop_token` <a id="stoptoken">[[stoptoken]]</a>
61
+
62
+ The class `stop_token` provides an interface for querying whether a stop
63
+ request has been made (`stop_requested`) or can ever be made
64
+ (`stop_possible`) using an associated `stop_source` object (
65
+ [[stopsource]]). A `stop_token` can also be passed to a `stop_callback`
66
+ [[stopcallback]] constructor to register a callback to be called when a
67
+ stop request has been made from an associated `stop_source`.
68
+
69
+ ``` cpp
70
+ namespace std {
71
+ class stop_token {
72
+ public:
73
+ // [stoptoken.cons], constructors, copy, and assignment
74
+ stop_token() noexcept;
75
+
76
+ stop_token(const stop_token&) noexcept;
77
+ stop_token(stop_token&&) noexcept;
78
+ stop_token& operator=(const stop_token&) noexcept;
79
+ stop_token& operator=(stop_token&&) noexcept;
80
+ ~stop_token();
81
+ void swap(stop_token&) noexcept;
82
+
83
+ // [stoptoken.mem], stop handling
84
+ [[nodiscard]] bool stop_requested() const noexcept;
85
+ [[nodiscard]] bool stop_possible() const noexcept;
86
+
87
+ [[nodiscard]] friend bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
88
+ friend void swap(stop_token& lhs, stop_token& rhs) noexcept;
89
+ };
90
+ }
91
+ ```
92
+
93
+ #### Constructors, copy, and assignment <a id="stoptoken.cons">[[stoptoken.cons]]</a>
94
+
95
+ ``` cpp
96
+ stop_token() noexcept;
97
+ ```
98
+
99
+ *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
100
+ `false`.
101
+
102
+ [*Note 1*: Because the created `stop_token` object can never receive a
103
+ stop request, no resources are allocated for a stop
104
+ state. — *end note*]
105
+
106
+ ``` cpp
107
+ stop_token(const stop_token& rhs) noexcept;
108
+ ```
109
+
110
+ *Ensures:* `*this == rhs` is `true`.
111
+
112
+ [*Note 2*: `*this` and `rhs` share the ownership of the same stop
113
+ state, if any. — *end note*]
114
+
115
+ ``` cpp
116
+ stop_token(stop_token&& rhs) noexcept;
117
+ ```
118
+
119
+ *Ensures:* `*this` contains the value of `rhs` prior to the start of
120
+ construction and `rhs.stop_possible()` is `false`.
121
+
122
+ ``` cpp
123
+ ~stop_token();
124
+ ```
125
+
126
+ *Effects:* Releases ownership of the stop state, if any.
127
+
128
+ ``` cpp
129
+ stop_token& operator=(const stop_token& rhs) noexcept;
130
+ ```
131
+
132
+ *Effects:* Equivalent to: `stop_token(rhs).swap(*this)`.
133
+
134
+ *Returns:* `*this`.
135
+
136
+ ``` cpp
137
+ stop_token& operator=(stop_token&& rhs) noexcept;
138
+ ```
139
+
140
+ *Effects:* Equivalent to: `stop_token(std::move(rhs)).swap(*this)`.
141
+
142
+ *Returns:* `*this`.
143
+
144
+ ``` cpp
145
+ void swap(stop_token& rhs) noexcept;
146
+ ```
147
+
148
+ *Effects:* Exchanges the values of `*this` and `rhs`.
149
+
150
+ #### Members <a id="stoptoken.mem">[[stoptoken.mem]]</a>
151
+
152
+ ``` cpp
153
+ [[nodiscard]] bool stop_requested() const noexcept;
154
+ ```
155
+
156
+ *Returns:* `true` if `*this` has ownership of a stop state that has
157
+ received a stop request; otherwise, `false`.
158
+
159
+ ``` cpp
160
+ [[nodiscard]] bool stop_possible() const noexcept;
161
+ ```
162
+
163
+ *Returns:* `false` if:
164
+
165
+ - `*this` does not have ownership of a stop state, or
166
+ - a stop request was not made and there are no associated `stop_source`
167
+ objects;
168
+
169
+ otherwise, `true`.
170
+
171
+ #### Non-member functions <a id="stoptoken.nonmembers">[[stoptoken.nonmembers]]</a>
172
+
173
+ ``` cpp
174
+ [[nodiscard]] bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
175
+ ```
176
+
177
+ *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
178
+ state or if both `lhs` and `rhs` do not have ownership of a stop state;
179
+ otherwise `false`.
180
+
181
+ ``` cpp
182
+ friend void swap(stop_token& x, stop_token& y) noexcept;
183
+ ```
184
+
185
+ *Effects:* Equivalent to: `x.swap(y)`.
186
+
187
+ ### Class `stop_source` <a id="stopsource">[[stopsource]]</a>
188
+
189
+ The class `stop_source` implements the semantics of making a stop
190
+ request. A stop request made on a `stop_source` object is visible to all
191
+ associated `stop_source` and `stop_token` ([[stoptoken]]) objects. Once
192
+ a stop request has been made it cannot be withdrawn (a subsequent stop
193
+ request has no effect).
194
+
195
+ ``` cpp
196
+ namespace std {
197
+ // no-shared-stop-state indicator
198
+ struct nostopstate_t {
199
+ explicit nostopstate_t() = default;
200
+ };
201
+ inline constexpr nostopstate_t nostopstate{};
202
+
203
+ class stop_source {
204
+ public:
205
+ // [stopsource.cons], constructors, copy, and assignment
206
+ stop_source();
207
+ explicit stop_source(nostopstate_t) noexcept;
208
+
209
+ stop_source(const stop_source&) noexcept;
210
+ stop_source(stop_source&&) noexcept;
211
+ stop_source& operator=(const stop_source&) noexcept;
212
+ stop_source& operator=(stop_source&&) noexcept;
213
+ ~stop_source();
214
+ void swap(stop_source&) noexcept;
215
+
216
+ // [stopsource.mem], stop handling
217
+ [[nodiscard]] stop_token get_token() const noexcept;
218
+ [[nodiscard]] bool stop_possible() const noexcept;
219
+ [[nodiscard]] bool stop_requested() const noexcept;
220
+ bool request_stop() noexcept;
221
+
222
+ [[nodiscard]] friend bool
223
+ operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
224
+ friend void swap(stop_source& lhs, stop_source& rhs) noexcept;
225
+ };
226
+ }
227
+ ```
228
+
229
+ #### Constructors, copy, and assignment <a id="stopsource.cons">[[stopsource.cons]]</a>
230
+
231
+ ``` cpp
232
+ stop_source();
233
+ ```
234
+
235
+ *Effects:* Initialises `*this` to have ownership of a new stop state.
236
+
237
+ *Ensures:* `stop_possible()` is `true` and `stop_requested()` is
238
+ `false`.
239
+
240
+ *Throws:* `bad_alloc` if memory could not be allocated for the stop
241
+ state.
242
+
243
+ ``` cpp
244
+ explicit stop_source(nostopstate_t) noexcept;
245
+ ```
246
+
247
+ *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
248
+ `false`.
249
+
250
+ [*Note 1*: No resources are allocated for the state. — *end note*]
251
+
252
+ ``` cpp
253
+ stop_source(const stop_source& rhs) noexcept;
254
+ ```
255
+
256
+ *Ensures:* `*this == rhs` is `true`.
257
+
258
+ [*Note 2*: `*this` and `rhs` share the ownership of the same stop
259
+ state, if any. — *end note*]
260
+
261
+ ``` cpp
262
+ stop_source(stop_source&& rhs) noexcept;
263
+ ```
264
+
265
+ *Ensures:* `*this` contains the value of `rhs` prior to the start of
266
+ construction and `rhs.stop_possible()` is `false`.
267
+
268
+ ``` cpp
269
+ ~stop_source();
270
+ ```
271
+
272
+ *Effects:* Releases ownership of the stop state, if any.
273
+
274
+ ``` cpp
275
+ stop_source& operator=(const stop_source& rhs) noexcept;
276
+ ```
277
+
278
+ *Effects:* Equivalent to: `stop_source(rhs).swap(*this)`.
279
+
280
+ *Returns:* `*this`.
281
+
282
+ ``` cpp
283
+ stop_source& operator=(stop_source&& rhs) noexcept;
284
+ ```
285
+
286
+ *Effects:* Equivalent to: `stop_source(std::move(rhs)).swap(*this)`.
287
+
288
+ *Returns:* `*this`.
289
+
290
+ ``` cpp
291
+ void swap(stop_source& rhs) noexcept;
292
+ ```
293
+
294
+ *Effects:* Exchanges the values of `*this` and `rhs`.
295
+
296
+ #### Members <a id="stopsource.mem">[[stopsource.mem]]</a>
297
+
298
+ ``` cpp
299
+ [[nodiscard]] stop_token get_token() const noexcept;
300
+ ```
301
+
302
+ *Returns:* `stop_token()` if `stop_possible()` is `false`; otherwise a
303
+ new associated `stop_token` object.
304
+
305
+ ``` cpp
306
+ [[nodiscard]] bool stop_possible() const noexcept;
307
+ ```
308
+
309
+ *Returns:* `true` if `*this` has ownership of a stop state; otherwise,
310
+ `false`.
311
+
312
+ ``` cpp
313
+ [[nodiscard]] bool stop_requested() const noexcept;
314
+ ```
315
+
316
+ *Returns:* `true` if `*this` has ownership of a stop state that has
317
+ received a stop request; otherwise, `false`.
318
+
319
+ ``` cpp
320
+ bool request_stop() noexcept;
321
+ ```
322
+
323
+ *Effects:* If `*this` does not have ownership of a stop state, returns
324
+ `false`. Otherwise, atomically determines whether the owned stop state
325
+ has received a stop request, and if not, makes a stop request. The
326
+ determination and making of the stop request are an atomic
327
+ read-modify-write operation [[intro.races]]. If the request was made,
328
+ the callbacks registered by associated `stop_callback` objects are
329
+ synchronously called. If an invocation of a callback exits via an
330
+ exception then `terminate` is called [[except.terminate]].
331
+
332
+ [*Note 1*: A stop request includes notifying all condition variables of
333
+ type `condition_variable_any` temporarily registered during an
334
+ interruptible wait [[thread.condvarany.intwait]]. — *end note*]
335
+
336
+ *Ensures:* `stop_possible()` is `false` or `stop_requested()` is `true`.
337
+
338
+ *Returns:* `true` if this call made a stop request; otherwise `false`.
339
+
340
+ #### Non-member functions <a id="stopsource.nonmembers">[[stopsource.nonmembers]]</a>
341
+
342
+ ``` cpp
343
+ [[nodiscard]] friend bool
344
+ operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
345
+ ```
346
+
347
+ *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
348
+ state or if both `lhs` and `rhs` do not have ownership of a stop state;
349
+ otherwise `false`.
350
+
351
+ ``` cpp
352
+ friend void swap(stop_source& x, stop_source& y) noexcept;
353
+ ```
354
+
355
+ *Effects:* Equivalent to: `x.swap(y)`.
356
+
357
+ ### Class template `stop_callback` <a id="stopcallback">[[stopcallback]]</a>
358
+
359
+ ``` cpp
360
+ namespace std {
361
+ template<class Callback>
362
+ class stop_callback {
363
+ public:
364
+ using callback_type = Callback;
365
+
366
+ // [stopcallback.cons], constructors and destructor
367
+ template<class C>
368
+ explicit stop_callback(const stop_token& st, C&& cb)
369
+ noexcept(is_nothrow_constructible_v<Callback, C>);
370
+ template<class C>
371
+ explicit stop_callback(stop_token&& st, C&& cb)
372
+ noexcept(is_nothrow_constructible_v<Callback, C>);
373
+ ~stop_callback();
374
+
375
+ stop_callback(const stop_callback&) = delete;
376
+ stop_callback(stop_callback&&) = delete;
377
+ stop_callback& operator=(const stop_callback&) = delete;
378
+ stop_callback& operator=(stop_callback&&) = delete;
379
+
380
+ private:
381
+ Callback callback; // exposition only
382
+ };
383
+
384
+ template<class Callback>
385
+ stop_callback(stop_token, Callback) -> stop_callback<Callback>;
386
+ }
387
+ ```
388
+
389
+ *Mandates:* `stop_callback` is instantiated with an argument for the
390
+ template parameter `Callback` that satisfies both `invocable` and
391
+ `destructible`.
392
+
393
+ *Preconditions:* `stop_callback` is instantiated with an argument for
394
+ the template parameter `Callback` that models both `invocable` and
395
+ `destructible`.
396
+
397
+ #### Constructors and destructor <a id="stopcallback.cons">[[stopcallback.cons]]</a>
398
+
399
+ ``` cpp
400
+ template<class C>
401
+ explicit stop_callback(const stop_token& st, C&& cb)
402
+ noexcept(is_nothrow_constructible_v<Callback, C>);
403
+ template<class C>
404
+ explicit stop_callback(stop_token&& st, C&& cb)
405
+ noexcept(is_nothrow_constructible_v<Callback, C>);
406
+ ```
407
+
408
+ *Constraints:* `Callback` and `C` satisfy
409
+ `constructible_from<Callback, C>`.
410
+
411
+ *Preconditions:* `Callback` and `C` model
412
+ `constructible_from<Callback, C>`.
413
+
414
+ *Effects:* Initializes `callback` with `std::forward<C>(cb)`. If
415
+ `st.stop_requested()` is `true`, then
416
+ `std::forward<Callback>(callback)()` is evaluated in the current thread
417
+ before the constructor returns. Otherwise, if `st` has ownership of a
418
+ stop state, acquires shared ownership of that stop state and registers
419
+ the callback with that stop state such that
420
+ `std::forward<Callback>(callback)()` is evaluated by the first call to
421
+ `request_stop()` on an associated `stop_source`.
422
+
423
+ *Remarks:* If evaluating `std::forward<Callback>(callback)()` exits via
424
+ an exception, then `terminate` is called [[except.terminate]].
425
+
426
+ *Throws:* Any exception thrown by the initialization of `callback`.
427
+
428
+ ``` cpp
429
+ ~stop_callback();
430
+ ```
431
+
432
+ *Effects:* Unregisters the callback from the owned stop state, if any.
433
+ The destructor does not block waiting for the execution of another
434
+ callback registered by an associated `stop_callback`. If `callback` is
435
+ concurrently executing on another thread, then the return from the
436
+ invocation of `callback` strongly happens before [[intro.races]]
437
+ `callback` is destroyed. If `callback` is executing on the current
438
+ thread, then the destructor does not block [[defns.block]] waiting for
439
+ the return from the invocation of `callback`. Releases ownership of the
440
+ stop state, if any.
441
+