From Jason Turner

[thread.stoptoken]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpgrizozx1/{from.md → to.md} +559 -274
tmp/tmpgrizozx1/{from.md → to.md} RENAMED
@@ -5,42 +5,64 @@
5
  Subclause [[thread.stoptoken]] describes components that can be used to
6
  asynchronously request that an operation stops execution in a timely
7
  manner, typically because the result is no longer required. Such a
8
  request is called a *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;
@@ -52,395 +74,658 @@ namespace std {
52
  inline constexpr nostopstate_t nostopstate{};
53
 
54
  // [stopcallback], class template stop_callback
55
  template<class Callback>
56
  class stop_callback;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
  ```
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  ### Class `stop_token` <a id="stoptoken">[[stoptoken]]</a>
61
 
62
  #### General <a id="stoptoken.general">[[stoptoken.general]]</a>
63
 
64
- The class `stop_token` provides an interface for querying whether a stop
65
- request has been made (`stop_requested`) or can ever be made
66
- (`stop_possible`) using an associated `stop_source` object
67
- [[stopsource]]. A `stop_token` can also be passed to a `stop_callback`
68
- [[stopcallback]] constructor to register a callback to be called when a
69
- stop request has been made from an associated `stop_source`.
70
 
71
  ``` cpp
72
  namespace std {
73
  class stop_token {
74
  public:
75
- // [stoptoken.cons], constructors, copy, and assignment
76
- stop_token() noexcept;
77
 
78
- stop_token(const stop_token&) noexcept;
79
- stop_token(stop_token&&) noexcept;
80
- stop_token& operator=(const stop_token&) noexcept;
81
- stop_token& operator=(stop_token&&) noexcept;
82
- ~stop_token();
83
  void swap(stop_token&) noexcept;
84
 
85
- // [stoptoken.mem], stop handling
86
- [[nodiscard]] bool stop_requested() const noexcept;
87
- [[nodiscard]] bool stop_possible() const noexcept;
88
 
89
- [[nodiscard]] friend bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
90
- friend void swap(stop_token& lhs, stop_token& rhs) noexcept;
 
 
91
  };
92
  }
93
  ```
94
 
95
- #### Constructors, copy, and assignment <a id="stoptoken.cons">[[stoptoken.cons]]</a>
 
96
 
97
- ``` cpp
98
- stop_token() noexcept;
99
- ```
100
-
101
- *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
102
- `false`.
103
-
104
- [*Note 1*: Because the created `stop_token` object can never receive a
105
- stop request, no resources are allocated for a stop
106
- state. — *end note*]
107
-
108
- ``` cpp
109
- stop_token(const stop_token& rhs) noexcept;
110
- ```
111
-
112
- *Ensures:* `*this == rhs` is `true`.
113
-
114
- [*Note 2*: `*this` and `rhs` share the ownership of the same stop
115
- state, if any. — *end note*]
116
-
117
- ``` cpp
118
- stop_token(stop_token&& rhs) noexcept;
119
- ```
120
-
121
- *Ensures:* `*this` contains the value of `rhs` prior to the start of
122
- construction and `rhs.stop_possible()` is `false`.
123
-
124
- ``` cpp
125
- ~stop_token();
126
- ```
127
-
128
- *Effects:* Releases ownership of the stop state, if any.
129
-
130
- ``` cpp
131
- stop_token& operator=(const stop_token& rhs) noexcept;
132
- ```
133
-
134
- *Effects:* Equivalent to: `stop_token(rhs).swap(*this)`.
135
-
136
- *Returns:* `*this`.
137
-
138
- ``` cpp
139
- stop_token& operator=(stop_token&& rhs) noexcept;
140
- ```
141
-
142
- *Effects:* Equivalent to: `stop_token(std::move(rhs)).swap(*this)`.
143
-
144
- *Returns:* `*this`.
145
 
146
  ``` cpp
147
  void swap(stop_token& rhs) noexcept;
148
  ```
149
 
150
- *Effects:* Exchanges the values of `*this` and `rhs`.
151
 
152
- #### Members <a id="stoptoken.mem">[[stoptoken.mem]]</a>
 
 
153
 
154
  ``` cpp
155
- [[nodiscard]] bool stop_requested() const noexcept;
156
  ```
157
 
158
- *Returns:* `true` if `*this` has ownership of a stop state that has
159
  received a stop request; otherwise, `false`.
160
 
161
  ``` cpp
162
- [[nodiscard]] bool stop_possible() const noexcept;
163
  ```
164
 
165
- *Returns:* `false` if:
166
 
167
- - `*this` does not have ownership of a stop state, or
168
  - a stop request was not made and there are no associated `stop_source`
169
  objects;
170
 
171
  otherwise, `true`.
172
 
173
- #### Non-member functions <a id="stoptoken.nonmembers">[[stoptoken.nonmembers]]</a>
174
-
175
- ``` cpp
176
- [[nodiscard]] bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
177
- ```
178
-
179
- *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
180
- state or if both `lhs` and `rhs` do not have ownership of a stop state;
181
- otherwise `false`.
182
-
183
- ``` cpp
184
- friend void swap(stop_token& x, stop_token& y) noexcept;
185
- ```
186
-
187
- *Effects:* Equivalent to: `x.swap(y)`.
188
-
189
  ### Class `stop_source` <a id="stopsource">[[stopsource]]</a>
190
 
191
  #### General <a id="stopsource.general">[[stopsource.general]]</a>
192
 
193
- The class `stop_source` implements the semantics of making a stop
194
- request. A stop request made on a `stop_source` object is visible to all
195
- associated `stop_source` and `stop_token` [[stoptoken]] objects. Once a
196
- stop request has been made it cannot be withdrawn (a subsequent stop
197
- request has no effect).
198
-
199
  ``` cpp
200
  namespace std {
201
- // no-shared-stop-state indicator
202
- struct nostopstate_t {
203
- explicit nostopstate_t() = default;
204
- };
205
- inline constexpr nostopstate_t nostopstate{};
206
-
207
  class stop_source {
208
  public:
209
  // [stopsource.cons], constructors, copy, and assignment
210
  stop_source();
211
- explicit stop_source(nostopstate_t) noexcept;
212
 
213
- stop_source(const stop_source&) noexcept;
214
- stop_source(stop_source&&) noexcept;
215
- stop_source& operator=(const stop_source&) noexcept;
216
- stop_source& operator=(stop_source&&) noexcept;
217
- ~stop_source();
218
  void swap(stop_source&) noexcept;
219
 
220
- // [stopsource.mem], stop handling
221
- [[nodiscard]] stop_token get_token() const noexcept;
222
- [[nodiscard]] bool stop_possible() const noexcept;
223
- [[nodiscard]] bool stop_requested() const noexcept;
224
  bool request_stop() noexcept;
225
 
226
- [[nodiscard]] friend bool
227
- operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
228
- friend void swap(stop_source& lhs, stop_source& rhs) noexcept;
 
229
  };
230
  }
231
  ```
232
 
 
 
 
 
 
 
233
  #### Constructors, copy, and assignment <a id="stopsource.cons">[[stopsource.cons]]</a>
234
 
235
  ``` cpp
236
  stop_source();
237
  ```
238
 
239
- *Effects:* Initialises `*this` to have ownership of a new stop state.
240
 
241
  *Ensures:* `stop_possible()` is `true` and `stop_requested()` is
242
  `false`.
243
 
244
  *Throws:* `bad_alloc` if memory cannot be allocated for the stop state.
245
 
246
- ``` cpp
247
- explicit stop_source(nostopstate_t) noexcept;
248
- ```
249
-
250
- *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
251
- `false`.
252
-
253
- [*Note 1*: No resources are allocated for the state. — *end note*]
254
-
255
- ``` cpp
256
- stop_source(const stop_source& rhs) noexcept;
257
- ```
258
-
259
- *Ensures:* `*this == rhs` is `true`.
260
-
261
- [*Note 2*: `*this` and `rhs` share the ownership of the same stop
262
- state, if any. — *end note*]
263
-
264
- ``` cpp
265
- stop_source(stop_source&& rhs) noexcept;
266
- ```
267
-
268
- *Ensures:* `*this` contains the value of `rhs` prior to the start of
269
- construction and `rhs.stop_possible()` is `false`.
270
-
271
- ``` cpp
272
- ~stop_source();
273
- ```
274
-
275
- *Effects:* Releases ownership of the stop state, if any.
276
-
277
- ``` cpp
278
- stop_source& operator=(const stop_source& rhs) noexcept;
279
- ```
280
-
281
- *Effects:* Equivalent to: `stop_source(rhs).swap(*this)`.
282
-
283
- *Returns:* `*this`.
284
-
285
- ``` cpp
286
- stop_source& operator=(stop_source&& rhs) noexcept;
287
- ```
288
-
289
- *Effects:* Equivalent to: `stop_source(std::move(rhs)).swap(*this)`.
290
-
291
- *Returns:* `*this`.
292
 
293
  ``` cpp
294
  void swap(stop_source& rhs) noexcept;
295
  ```
296
 
297
- *Effects:* Exchanges the values of `*this` and `rhs`.
298
 
299
- #### Members <a id="stopsource.mem">[[stopsource.mem]]</a>
 
 
300
 
301
  ``` cpp
302
- [[nodiscard]] stop_token get_token() const noexcept;
303
  ```
304
 
305
  *Returns:* `stop_token()` if `stop_possible()` is `false`; otherwise a
306
- new associated `stop_token` object.
 
307
 
308
  ``` cpp
309
- [[nodiscard]] bool stop_possible() const noexcept;
310
  ```
311
 
312
- *Returns:* `true` if `*this` has ownership of a stop state; otherwise,
313
- `false`.
314
 
315
  ``` cpp
316
- [[nodiscard]] bool stop_requested() const noexcept;
317
  ```
318
 
319
- *Returns:* `true` if `*this` has ownership of a stop state that has
320
  received a stop request; otherwise, `false`.
321
 
322
  ``` cpp
323
  bool request_stop() noexcept;
324
  ```
325
 
326
- *Effects:* If `*this` does not have ownership of a stop state, returns
327
- `false`. Otherwise, atomically determines whether the owned stop state
328
- has received a stop request, and if not, makes a stop request. The
329
- determination and making of the stop request are an atomic
330
- read-modify-write operation [[intro.races]]. If the request was made,
331
- the callbacks registered by associated `stop_callback` objects are
332
- synchronously called. If an invocation of a callback exits via an
333
- exception then `terminate` is invoked [[except.terminate]].
334
-
335
- [*Note 1*: A stop request includes notifying all condition variables of
336
- type `condition_variable_any` temporarily registered during an
337
- interruptible wait [[thread.condvarany.intwait]]. — *end note*]
338
-
339
- *Ensures:* `stop_possible()` is `false` or `stop_requested()` is `true`.
340
-
341
- *Returns:* `true` if this call made a stop request; otherwise `false`.
342
-
343
- #### Non-member functions <a id="stopsource.nonmembers">[[stopsource.nonmembers]]</a>
344
-
345
- ``` cpp
346
- [[nodiscard]] friend bool
347
- operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
348
- ```
349
-
350
- *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
351
- state or if both `lhs` and `rhs` do not have ownership of a stop state;
352
- otherwise `false`.
353
-
354
- ``` cpp
355
- friend void swap(stop_source& x, stop_source& y) noexcept;
356
- ```
357
-
358
- *Effects:* Equivalent to: `x.swap(y)`.
359
 
360
  ### Class template `stop_callback` <a id="stopcallback">[[stopcallback]]</a>
361
 
362
  #### General <a id="stopcallback.general">[[stopcallback.general]]</a>
363
 
364
  ``` cpp
365
  namespace std {
366
- template<class Callback>
367
  class stop_callback {
368
  public:
369
- using callback_type = Callback;
370
 
371
  // [stopcallback.cons], constructors and destructor
372
- template<class C>
373
- explicit stop_callback(const stop_token& st, C&& cb)
374
- noexcept(is_nothrow_constructible_v<Callback, C>);
375
- template<class C>
376
- explicit stop_callback(stop_token&& st, C&& cb)
377
- noexcept(is_nothrow_constructible_v<Callback, C>);
378
  ~stop_callback();
379
 
380
  stop_callback(const stop_callback&) = delete;
381
  stop_callback(stop_callback&&) = delete;
382
  stop_callback& operator=(const stop_callback&) = delete;
383
  stop_callback& operator=(stop_callback&&) = delete;
384
 
385
  private:
386
- Callback callback; // exposition only
387
  };
388
 
389
- template<class Callback>
390
- stop_callback(stop_token, Callback) -> stop_callback<Callback>;
391
  }
392
  ```
393
 
394
  *Mandates:* `stop_callback` is instantiated with an argument for the
395
- template parameter `Callback` that satisfies both `invocable` and
396
  `destructible`.
397
 
398
- *Preconditions:* `stop_callback` is instantiated with an argument for
399
- the template parameter `Callback` that models both `invocable` and
400
- `destructible`.
 
 
 
 
401
 
402
  #### Constructors and destructor <a id="stopcallback.cons">[[stopcallback.cons]]</a>
403
 
404
  ``` cpp
405
- template<class C>
406
- explicit stop_callback(const stop_token& st, C&& cb)
407
- noexcept(is_nothrow_constructible_v<Callback, C>);
408
- template<class C>
409
- explicit stop_callback(stop_token&& st, C&& cb)
410
- noexcept(is_nothrow_constructible_v<Callback, C>);
 
411
  ```
412
 
413
- *Constraints:* `Callback` and `C` satisfy
414
- `constructible_from<Callback, C>`.
415
-
416
- *Preconditions:* `Callback` and `C` model
417
- `constructible_from<Callback, C>`.
418
-
419
- *Effects:* Initializes `callback` with `std::forward<C>(cb)`. If
420
- `st.stop_requested()` is `true`, then
421
- `std::forward<Callback>(callback)()` is evaluated in the current thread
422
- before the constructor returns. Otherwise, if `st` has ownership of a
423
- stop state, acquires shared ownership of that stop state and registers
424
- the callback with that stop state such that
425
- `std::forward<Callback>(callback)()` is evaluated by the first call to
426
- `request_stop()` on an associated `stop_source`.
427
-
428
- *Throws:* Any exception thrown by the initialization of `callback`.
429
-
430
- *Remarks:* If evaluating `std::forward<Callback>(callback)()` exits via
431
- an exception, then `terminate` is invoked [[except.terminate]].
432
 
433
  ``` cpp
434
  ~stop_callback();
435
  ```
436
 
437
- *Effects:* Unregisters the callback from the owned stop state, if any.
438
- The destructor does not block waiting for the execution of another
439
- callback registered by an associated `stop_callback`. If `callback` is
440
- concurrently executing on another thread, then the return from the
441
- invocation of `callback` strongly happens before [[intro.races]]
442
- `callback` is destroyed. If `callback` is executing on the current
443
- thread, then the destructor does not block [[defns.block]] waiting for
444
- the return from the invocation of `callback`. Releases ownership of the
445
- stop state, if any.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
 
 
5
  Subclause [[thread.stoptoken]] describes components that can be used to
6
  asynchronously request that an operation stops execution in a timely
7
  manner, typically because the result is no longer required. Such a
8
  request is called a *stop request*.
9
 
10
+ The concepts `stoppable-source`, `stoppable_token`, and
11
+ `stoppable-callback-for` specify the required syntax and semantics of
12
+ shared access to a *stop state*. Any object modeling `stoppable-source`,
13
+ `stoppable_token`, or `stoppable-callback-for` that refers to the same
14
+ stop state is an *associated* `stoppable-source`, `stoppable_token`, or
15
+ `stoppable-callback-for`, respectively.
16
 
17
+ An object of a type that models `stoppable_token` can be passed to an
18
+ operation that can either
19
 
20
  - actively poll the token to check if there has been a stop request, or
21
+ - register a callback that will be called in the event that a stop
22
+ request is made.
23
 
24
+ A stop request made via an object whose type models `stoppable-source`
25
+ will be visible to all associated `stoppable_token` and
26
+ `stoppable-source` objects. Once a stop request has been made it cannot
27
+ be withdrawn (a subsequent stop request has no effect).
28
 
29
+ Callbacks registered via an object whose type models
30
+ `stoppable-callback-for` are called when a stop request is first made by
31
+ any associated `stoppable-source` object.
32
 
33
+ The types `stop_source` and `stop_token` and the class template
34
+ `stop_callback` implement the semantics of shared ownership of a stop
35
+ state. The last remaining owner of the stop state automatically releases
36
+ the resources associated with the stop state.
37
+
38
+ An object of type `inplace_stop_source` is the sole owner of its stop
39
+ state. An object of type `inplace_stop_token` or of a specialization of
40
+ the class template `inplace_stop_callback` does not participate in
41
+ ownership of its associated stop state.
42
+
43
+ [*Note 1*: They are for use when all uses of the associated token and
44
+ callback objects are known to nest within the lifetime of the
45
+ `inplace_stop_source` object. — *end note*]
46
 
47
  ### Header `<stop_token>` synopsis <a id="thread.stoptoken.syn">[[thread.stoptoken.syn]]</a>
48
 
49
  ``` cpp
50
  namespace std {
51
+ // [stoptoken.concepts], stop token concepts
52
+ template<class CallbackFn, class Token, class Initializer = CallbackFn>
53
+ concept stoppable-callback-for = see below; // exposition only
54
+
55
+ template<class Token>
56
+ concept stoppable_token = see below;
57
+
58
+ template<class Token>
59
+ concept unstoppable_token = see below;
60
+
61
+ template<class Source>
62
+ concept stoppable-source = see below; // exposition only
63
+
64
  // [stoptoken], class stop_token
65
  class stop_token;
66
 
67
  // [stopsource], class stop_source
68
  class stop_source;
 
74
  inline constexpr nostopstate_t nostopstate{};
75
 
76
  // [stopcallback], class template stop_callback
77
  template<class Callback>
78
  class stop_callback;
79
+
80
+ // [stoptoken.never], class never_stop_token
81
+ class never_stop_token;
82
+
83
+ // [stoptoken.inplace], class inplace_stop_token
84
+ class inplace_stop_token;
85
+
86
+ // [stopsource.inplace], class inplace_stop_source
87
+ class inplace_stop_source;
88
+
89
+ // [stopcallback.inplace], class template inplace_stop_callback
90
+ template<class CallbackFn>
91
+ class inplace_stop_callback;
92
+
93
+ template<class T, class CallbackFn>
94
+ using stop_callback_for_t = T::template callback_type<CallbackFn>;
95
  }
96
  ```
97
 
98
+ ### Stop token concepts <a id="stoptoken.concepts">[[stoptoken.concepts]]</a>
99
+
100
+ The exposition-only `stoppable-callback-for` concept checks for a
101
+ callback compatible with a given `Token` type.
102
+
103
+ ``` cpp
104
+ template<class CallbackFn, class Token, class Initializer = CallbackFn>
105
+ concept stoppable-callback-for = // exposition only
106
+ invocable<CallbackFn> &&
107
+ constructible_from<CallbackFn, Initializer> &&
108
+ requires { typename stop_callback_for_t<Token, CallbackFn>; } &&
109
+ constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
110
+ ```
111
+
112
+ Let `t` and `u` be distinct, valid objects of type `Token` that
113
+ reference the same logical stop state; let `init` be an expression such
114
+ that `same_as<decltype(init), Initializer>` is `true`; and let `SCB`
115
+ denote the type `stop_callback_for_t<Token, CallbackFn>`.
116
+
117
+ The concept `stoppable-callback-for<CallbackFn, Token, Initializer>` is
118
+ modeled only if:
119
+
120
+ - The following concepts are modeled:
121
+ - `\texttt{constructible_from}<SCB, Token, Initializer>`
122
+ - `\texttt{constructible_from}<SCB, Token&, Initializer>`
123
+ - `\texttt{constructible_from}<SCB, const Token, Initializer>`
124
+ - An object of type `SCB` has an associated callback function of type
125
+ `CallbackFn`. Let `scb` be an object of type `SCB` and let
126
+ `callback_fn` denote `scb`’s associated callback function.
127
+ Direct-non-list-initializing `scb` from arguments `t` and `init` shall
128
+ execute a *stoppable callback registration* as follows:
129
+ - If `t.stop_possible()` is `true`:
130
+ - `callback_fn` shall be direct-initialized with `init`.
131
+ - Construction of `scb` shall only throw exceptions thrown by the
132
+ initialization of `callback_fn` from `init`.
133
+ - The callback invocation `std::forward<CallbackFn>(callback_fn)()`
134
+ shall be registered with `t`’s associated stop state as follows:
135
+ - If `t.stop_requested()` evaluates to `false` at the time of
136
+ registration, the callback invocation is added to the stop
137
+ state’s list of callbacks such that
138
+ `std::forward<CallbackFn>( callback_fn)()` is evaluated if a
139
+ stop request is made on the stop state.
140
+ - Otherwise, `std::forward<CallbackFn>(callback_fn)()` shall be
141
+ immediately evaluated on the thread executing `scb`’s
142
+ constructor, and the callback invocation shall not be added to
143
+ the list of callback invocations.
144
+
145
+ If the callback invocation was added to stop state’s list of
146
+ callbacks, `scb` shall be associated with the stop state.
147
+ - \[*Note 1*: If `t.stop_possible()` is `false`, there is no
148
+ requirement that the initialization of `scb` causes the
149
+ initialization of `callback_fn`. — *end note*]
150
+ - Destruction of `scb` shall execute a
151
+ *stoppable callback deregistration* as follows (in order):
152
+ - If the constructor of `scb` did not register a callback invocation
153
+ with `t`’s stop state, then the stoppable callback deregistration
154
+ shall have no effect other than destroying `callback_fn` if it was
155
+ constructed.
156
+ - Otherwise, the invocation of `callback_fn` shall be removed from the
157
+ associated stop state.
158
+ - If `callback_fn` is concurrently executing on another thread, then
159
+ the stoppable callback deregistration shall block [[defns.block]]
160
+ until the invocation of `callback_fn` returns such that the return
161
+ from the invocation of `callback_fn` strongly happens before
162
+ [[intro.races]] the destruction of `callback_fn`.
163
+ - If `callback_fn` is executing on the current thread, then the
164
+ destructor shall not block waiting for the return from the
165
+ invocation of `callback_fn`.
166
+ - A stoppable callback deregistration shall not block on the
167
+ completion of the invocation of some other callback registered with
168
+ the same logical stop state.
169
+ - The stoppable callback deregistration shall destroy `callback_fn`.
170
+
171
+ The `stoppable_token` concept checks for the basic interface of a stop
172
+ token that is copyable and allows polling to see if stop has been
173
+ requested and also whether a stop request is possible. The
174
+ `unstoppable_token` concept checks for a `stoppable_token` type that
175
+ does not allow stopping.
176
+
177
+ ``` cpp
178
+ template<template<class> class>
179
+ struct check-type-alias-exists; // exposition only
180
+
181
+ template<class Token>
182
+ concept stoppable_token =
183
+ requires (const Token tok) {
184
+ typename check-type-alias-exists<Token::template callback_type>;
185
+ { tok.stop_requested() } noexcept -> same_as<bool>;
186
+ { tok.stop_possible() } noexcept -> same_as<bool>;
187
+ { Token(tok) } noexcept; // see implicit expression variations[concepts.equality]
188
+ } &&
189
+ copyable<Token> &&
190
+ equality_comparable<Token>;
191
+
192
+ template<class Token>
193
+ concept unstoppable_token =
194
+ stoppable_token<Token> &&
195
+ requires (const Token tok) {
196
+ requires bool_constant<(!tok.stop_possible())>::value;
197
+ };
198
+ ```
199
+
200
+ An object whose type models `stoppable_token` has at most one associated
201
+ logical stop state. A `stoppable_token` object with no associated stop
202
+ state is said to be *disengaged*.
203
+
204
+ Let `SP` be an evaluation of `t.stop_possible()` that is `false`, and
205
+ let SR be an evaluation of `t.stop_requested()` that is `true`.
206
+
207
+ The type `Token` models `stoppable_token` only if:
208
+
209
+ - Any evaluation of `u.stop_possible()` or `u.stop_requested()` that
210
+ happens after [[intro.races]] `SP` is `false`.
211
+ - Any evaluation of `u.stop_possible()` or `u.stop_requested()` that
212
+ happens after `SR` is `true`.
213
+ - For any types `CallbackFn` and `Initializer` such that
214
+ `stoppable-callback-for<CallbackFn, Token, Initializer>` is satisfied,
215
+ `stoppable-callback-for<CallbackFn, Token, Initializer>` is modeled.
216
+ - If `t` is disengaged, evaluations of `t.stop_possible()` and
217
+ `t.stop_requested()` are `false`.
218
+ - If `t` and `u` reference the same stop state, or if both `t` and `u`
219
+ are disengaged, `t == u` is `true`; otherwise, it is `false`.
220
+
221
+ An object whose type models the exposition-only `stoppable-source`
222
+ concept can be queried whether stop has been requested
223
+ (`stop_requested`) and whether stop is possible (`stop_possible`). It is
224
+ a factory for associated stop tokens (`get_token`), and a stop request
225
+ can be made on it (`request_stop`). It maintains a list of registered
226
+ stop callback invocations that it executes when a stop request is first
227
+ made.
228
+
229
+ ``` cpp
230
+ template<class Source>
231
+ concept stoppable-source = // exposition only
232
+ requires (Source& src, const Source csrc) { // see implicit expression variations[concepts.equality]
233
+ { csrc.get_token() } -> stoppable_token;
234
+ { csrc.stop_possible() } noexcept -> same_as<bool>;
235
+ { csrc.stop_requested() } noexcept -> same_as<bool>;
236
+ { src.request_stop() } -> same_as<bool>;
237
+ };
238
+ ```
239
+
240
+ An object whose type models `stoppable-source` has at most one
241
+ associated logical stop state. If it has no associated stop state, it is
242
+ said to be disengaged. Let `s` be an object whose type models
243
+ `stoppable-source` and that is disengaged. `s.stop_possible()` and
244
+ `s.stop_requested()` shall be `false`.
245
+
246
+ Let `t` be an object whose type models `stoppable-source`. If `t` is
247
+ disengaged, `t.get_token()` shall return a disengaged stop token;
248
+ otherwise, it shall return a stop token that is associated with the stop
249
+ state of `t`.
250
+
251
+ Calls to the member functions `request_stop`, `stop_requested`, and
252
+ `stop_possible` and similarly named member functions on associated
253
+ `stoppable_token` objects do not introduce data races. A call to
254
+ `request_stop` that returns `true` synchronizes with a call to
255
+ `stop_requested` on an associated `stoppable_token` or
256
+ `stoppable-source` object that returns `true`. Registration of a
257
+ callback synchronizes with the invocation of that callback.
258
+
259
+ If the `stoppable-source` is disengaged, `request_stop` shall have no
260
+ effect and return `false`. Otherwise, it shall execute a
261
+ *stop request operation* on the associated stop state. A stop request
262
+ operation determines whether the stop state has received a stop request,
263
+ and if not, makes a stop request. The determination and making of the
264
+ stop request shall happen atomically, as-if by a read-modify-write
265
+ operation [[intro.races]]. If the request was made, the stop state’s
266
+ registered callback invocations shall be synchronously executed. If an
267
+ invocation of a callback exits via an exception then `terminate` shall
268
+ be invoked [[except.terminate]].
269
+
270
+ [*Note 2*: No constraint is placed on the order in which the callback
271
+ invocations are executed. — *end note*]
272
+
273
+ `request_stop` shall return `true` if a stop request was made, and
274
+ `false` otherwise. After a call to `request_stop` either a call to
275
+ `stop_possible` shall return `false` or a call to `stop_requested` shall
276
+ return `true`.
277
+
278
+ [*Note 3*: A stop request includes notifying all condition variables of
279
+ type `condition_variable_any` temporarily registered during an
280
+ interruptible wait [[thread.condvarany.intwait]]. — *end note*]
281
+
282
  ### Class `stop_token` <a id="stoptoken">[[stoptoken]]</a>
283
 
284
  #### General <a id="stoptoken.general">[[stoptoken.general]]</a>
285
 
286
+ The class `stop_token` models the concept `stoppable_token`. It shares
287
+ ownership of its stop state, if any, with its associated `stop_source`
288
+ object [[stopsource]] and any `stop_token` objects to which it compares
289
+ equal.
 
 
290
 
291
  ``` cpp
292
  namespace std {
293
  class stop_token {
294
  public:
295
+ template<class CallbackFn>
296
+ using callback_type = stop_callback<CallbackFn>;
297
 
298
+ stop_token() noexcept = default;
299
+
300
+ // [stoptoken.mem], member functions
 
 
301
  void swap(stop_token&) noexcept;
302
 
303
+ bool stop_requested() const noexcept;
304
+ bool stop_possible() const noexcept;
 
305
 
306
+ bool operator==(const stop_token& rhs) noexcept = default;
307
+
308
+ private:
309
+ shared_ptr<unspecified> stop-state; // exposition only
310
  };
311
  }
312
  ```
313
 
314
+ *`stop-state`* refers to the `stop_token`’s associated stop state. A
315
+ `stop_token` object is disengaged when *`stop-state`* is empty.
316
 
317
+ #### Member functions <a id="stoptoken.mem">[[stoptoken.mem]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
319
  ``` cpp
320
  void swap(stop_token& rhs) noexcept;
321
  ```
322
 
323
+ *Effects:* Equivalent to:
324
 
325
+ ``` cpp
326
+ stop-state.swap(rhs.stop-state);
327
+ ```
328
 
329
  ``` cpp
330
+ bool stop_requested() const noexcept;
331
  ```
332
 
333
+ *Returns:* `true` if *stop-state* refers to a stop state that has
334
  received a stop request; otherwise, `false`.
335
 
336
  ``` cpp
337
+ bool stop_possible() const noexcept;
338
  ```
339
 
340
+ *Returns:* `false` if
341
 
342
+ - `*this` is disengaged, or
343
  - a stop request was not made and there are no associated `stop_source`
344
  objects;
345
 
346
  otherwise, `true`.
347
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  ### Class `stop_source` <a id="stopsource">[[stopsource]]</a>
349
 
350
  #### General <a id="stopsource.general">[[stopsource.general]]</a>
351
 
 
 
 
 
 
 
352
  ``` cpp
353
  namespace std {
 
 
 
 
 
 
354
  class stop_source {
355
  public:
356
  // [stopsource.cons], constructors, copy, and assignment
357
  stop_source();
358
+ explicit stop_source(nostopstate_t) noexcept {}
359
 
360
+ // [stopsource.mem], member functions
 
 
 
 
361
  void swap(stop_source&) noexcept;
362
 
363
+ stop_token get_token() const noexcept;
364
+ bool stop_possible() const noexcept;
365
+ bool stop_requested() const noexcept;
 
366
  bool request_stop() noexcept;
367
 
368
+ bool operator==(const stop_source& rhs) noexcept = default;
369
+
370
+ private:
371
+ shared_ptr<unspecified> stop-state; // exposition only
372
  };
373
  }
374
  ```
375
 
376
+ *`stop-state`* refers to the `stop_source`’s associated stop state. A
377
+ `stop_source` object is disengaged when *`stop-state`* is empty.
378
+
379
+ `stop_source` models `stoppable-source`, `copyable`,
380
+ `equality_comparable`, and `swappable`.
381
+
382
  #### Constructors, copy, and assignment <a id="stopsource.cons">[[stopsource.cons]]</a>
383
 
384
  ``` cpp
385
  stop_source();
386
  ```
387
 
388
+ *Effects:* Initializes *stop-state* with a pointer to a new stop state.
389
 
390
  *Ensures:* `stop_possible()` is `true` and `stop_requested()` is
391
  `false`.
392
 
393
  *Throws:* `bad_alloc` if memory cannot be allocated for the stop state.
394
 
395
+ #### Member functions <a id="stopsource.mem">[[stopsource.mem]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
 
397
  ``` cpp
398
  void swap(stop_source& rhs) noexcept;
399
  ```
400
 
401
+ *Effects:* Equivalent to:
402
 
403
+ ``` cpp
404
+ stop-state.swap(rhs.stop-state);
405
+ ```
406
 
407
  ``` cpp
408
+ stop_token get_token() const noexcept;
409
  ```
410
 
411
  *Returns:* `stop_token()` if `stop_possible()` is `false`; otherwise a
412
+ new associated `stop_token` object; i.e., its *stop-state* member is
413
+ equal to the *stop-state* member of `*this`.
414
 
415
  ``` cpp
416
+ bool stop_possible() const noexcept;
417
  ```
418
 
419
+ *Returns:* *`stop-state`*` != nullptr`.
 
420
 
421
  ``` cpp
422
+ bool stop_requested() const noexcept;
423
  ```
424
 
425
+ *Returns:* `true` if *stop-state* refers to a stop state that has
426
  received a stop request; otherwise, `false`.
427
 
428
  ``` cpp
429
  bool request_stop() noexcept;
430
  ```
431
 
432
+ *Effects:* Executes a stop request operation [[stoptoken.concepts]] on
433
+ the associated stop state, if any.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
  ### Class template `stop_callback` <a id="stopcallback">[[stopcallback]]</a>
436
 
437
  #### General <a id="stopcallback.general">[[stopcallback.general]]</a>
438
 
439
  ``` cpp
440
  namespace std {
441
+ template<class CallbackFn>
442
  class stop_callback {
443
  public:
444
+ using callback_type = CallbackFn;
445
 
446
  // [stopcallback.cons], constructors and destructor
447
+ template<class Initializer>
448
+ explicit stop_callback(const stop_token& st, Initializer&& init)
449
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
450
+ template<class Initializer>
451
+ explicit stop_callback(stop_token&& st, Initializer&& init)
452
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
453
  ~stop_callback();
454
 
455
  stop_callback(const stop_callback&) = delete;
456
  stop_callback(stop_callback&&) = delete;
457
  stop_callback& operator=(const stop_callback&) = delete;
458
  stop_callback& operator=(stop_callback&&) = delete;
459
 
460
  private:
461
+ CallbackFn callback-fn; // exposition only
462
  };
463
 
464
+ template<class CallbackFn>
465
+ stop_callback(stop_token, CallbackFn) -> stop_callback<CallbackFn>;
466
  }
467
  ```
468
 
469
  *Mandates:* `stop_callback` is instantiated with an argument for the
470
+ template parameter `CallbackFn` that satisfies both `invocable` and
471
  `destructible`.
472
 
473
+ *Remarks:* For a type `Initializer`, if
474
+ `stoppable-callback-for<CallbackFn, stop_token, Initializer>` is
475
+ satisfied, then
476
+ `stoppable-callback-for<CallbackFn, stop_token, Initializer>` is
477
+ modeled. The exposition-only *`callback-fn`* member is the associated
478
+ callback function [[stoptoken.concepts]] of `stop_callback< CallbackFn>`
479
+ objects.
480
 
481
  #### Constructors and destructor <a id="stopcallback.cons">[[stopcallback.cons]]</a>
482
 
483
  ``` cpp
484
+ template<class Initializer>
485
+ explicit stop_callback(const stop_token& st, Initializer&& init)
486
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
487
+
488
+ template<class Initializer>
489
+ explicit stop_callback(stop_token&& st, Initializer&& init)
490
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
491
  ```
492
 
493
+ *Constraints:* `CallbackFn` and `Initializer` satisfy
494
+ `constructible_from<CallbackFn, Initializer>`.
495
+
496
+ *Effects:* Initializes *callback-fn* with
497
+ `std::forward<Initializer>(init)` and executes a stoppable callback
498
+ registration [[stoptoken.concepts]]. If a callback is registered with
499
+ `st`’s shared stop state, then `*this` acquires shared ownership of that
500
+ stop state.
 
 
 
 
 
 
 
 
 
 
 
501
 
502
  ``` cpp
503
  ~stop_callback();
504
  ```
505
 
506
+ *Effects:* Executes a stoppable callback
507
+ deregistration [[stoptoken.concepts]] and releases ownership of the stop
508
+ state, if any.
509
+
510
+ ### Class `never_stop_token` <a id="stoptoken.never">[[stoptoken.never]]</a>
511
+
512
+ The class `never_stop_token` models the `unstoppable_token` concept. It
513
+ provides a stop token interface, but also provides static information
514
+ that a stop is never possible nor requested.
515
+
516
+ ``` cpp
517
+ namespace std {
518
+ class never_stop_token {
519
+ struct callback-type { // exposition only
520
+ explicit callback-type(never_stop_token, auto&&) noexcept {}
521
+ };
522
+ public:
523
+ template<class>
524
+ using callback_type = callback-type;
525
+
526
+ static constexpr bool stop_requested() noexcept { return false; }
527
+ static constexpr bool stop_possible() noexcept { return false; }
528
+
529
+ bool operator==(const never_stop_token&) const = default;
530
+ };
531
+ }
532
+ ```
533
+
534
+ ### Class `inplace_stop_token` <a id="stoptoken.inplace">[[stoptoken.inplace]]</a>
535
+
536
+ #### General <a id="stoptoken.inplace.general">[[stoptoken.inplace.general]]</a>
537
+
538
+ The class `inplace_stop_token` models the concept `stoppable_token`. It
539
+ references the stop state of its associated `inplace_stop_source` object
540
+ [[stopsource.inplace]], if any.
541
+
542
+ ``` cpp
543
+ namespace std {
544
+ class inplace_stop_token {
545
+ public:
546
+ template<class CallbackFn>
547
+ using callback_type = inplace_stop_callback<CallbackFn>;
548
+
549
+ inplace_stop_token() = default;
550
+ bool operator==(const inplace_stop_token&) const = default;
551
+
552
+ // [stoptoken.inplace.mem], member functions
553
+ bool stop_requested() const noexcept;
554
+ bool stop_possible() const noexcept;
555
+ void swap(inplace_stop_token&) noexcept;
556
+
557
+ private:
558
+ const inplace_stop_source* stop-source = nullptr; // exposition only
559
+ };
560
+ }
561
+ ```
562
+
563
+ #### Member functions <a id="stoptoken.inplace.mem">[[stoptoken.inplace.mem]]</a>
564
+
565
+ ``` cpp
566
+ void swap(inplace_stop_token& rhs) noexcept;
567
+ ```
568
+
569
+ *Effects:* Exchanges the values of *stop-source* and
570
+ `rhs.`*`stop-source`*.
571
+
572
+ ``` cpp
573
+ bool stop_requested() const noexcept;
574
+ ```
575
+
576
+ *Effects:* Equivalent to:
577
+
578
+ ``` cpp
579
+ return stop-source != nullptr && stop-source->stop_requested();
580
+ ```
581
+
582
+ [*Note 1*: As specified in [[basic.life]], the behavior of
583
+ `stop_requested` is undefined unless the call strongly happens before
584
+ the start of the destructor of the associated `inplace_stop_source`
585
+ object, if any. — *end note*]
586
+
587
+ ``` cpp
588
+ stop_possible() const noexcept;
589
+ ```
590
+
591
+ *Returns:* *`stop-source`*` != nullptr`.
592
+
593
+ [*Note 2*: As specified in [[basic.stc.general]], the behavior of
594
+ `stop_possible` is implementation-defined unless the call strongly
595
+ happens before the end of the storage duration of the associated
596
+ `inplace_stop_source` object, if any. — *end note*]
597
+
598
+ ### Class `inplace_stop_source` <a id="stopsource.inplace">[[stopsource.inplace]]</a>
599
+
600
+ #### General <a id="stopsource.inplace.general">[[stopsource.inplace.general]]</a>
601
+
602
+ The class `inplace_stop_source` models `stoppable-source`.
603
+
604
+ ``` cpp
605
+ namespace std {
606
+ class inplace_stop_source {
607
+ public:
608
+ // [stopsource.inplace.cons], constructors
609
+ constexpr inplace_stop_source() noexcept;
610
+
611
+ inplace_stop_source(inplace_stop_source&&) = delete;
612
+ inplace_stop_source(const inplace_stop_source&) = delete;
613
+ inplace_stop_source& operator=(inplace_stop_source&&) = delete;
614
+ inplace_stop_source& operator=(const inplace_stop_source&) = delete;
615
+ ~inplace_stop_source();
616
+
617
+ // [stopsource.inplace.mem], stop handling
618
+ constexpr inplace_stop_token get_token() const noexcept;
619
+ static constexpr bool stop_possible() noexcept { return true; }
620
+ bool stop_requested() const noexcept;
621
+ bool request_stop() noexcept;
622
+ };
623
+ }
624
+ ```
625
+
626
+ #### Constructors <a id="stopsource.inplace.cons">[[stopsource.inplace.cons]]</a>
627
+
628
+ ``` cpp
629
+ constexpr inplace_stop_source() noexcept;
630
+ ```
631
+
632
+ *Effects:* Initializes a new stop state inside `*this`.
633
+
634
+ *Ensures:* `stop_requested()` is `false`.
635
+
636
+ #### Member functions <a id="stopsource.inplace.mem">[[stopsource.inplace.mem]]</a>
637
+
638
+ ``` cpp
639
+ constexpr inplace_stop_token get_token() const noexcept;
640
+ ```
641
+
642
+ *Returns:* A new associated `inplace_stop_token` object whose
643
+ *stop-source* member is equal to `this`.
644
+
645
+ ``` cpp
646
+ bool stop_requested() const noexcept;
647
+ ```
648
+
649
+ *Returns:* `true` if the stop state inside `*this` has received a stop
650
+ request; otherwise, `false`.
651
+
652
+ ``` cpp
653
+ bool request_stop() noexcept;
654
+ ```
655
+
656
+ *Effects:* Executes a stop request operation [[stoptoken.concepts]].
657
+
658
+ *Ensures:* `stop_requested()` is `true`.
659
+
660
+ ### Class template `inplace_stop_callback` <a id="stopcallback.inplace">[[stopcallback.inplace]]</a>
661
+
662
+ #### General <a id="stopcallback.inplace.general">[[stopcallback.inplace.general]]</a>
663
+
664
+ ``` cpp
665
+ namespace std {
666
+ template<class CallbackFn>
667
+ class inplace_stop_callback {
668
+ public:
669
+ using callback_type = CallbackFn;
670
+
671
+ // [stopcallback.inplace.cons], constructors and destructor
672
+ template<class Initializer>
673
+ explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init)
674
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
675
+ ~inplace_stop_callback();
676
+
677
+ inplace_stop_callback(inplace_stop_callback&&) = delete;
678
+ inplace_stop_callback(const inplace_stop_callback&) = delete;
679
+ inplace_stop_callback& operator=(inplace_stop_callback&&) = delete;
680
+ inplace_stop_callback& operator=(const inplace_stop_callback&) = delete;
681
+
682
+ private:
683
+ CallbackFn callback-fn; // exposition only
684
+ };
685
+
686
+ template<class CallbackFn>
687
+ inplace_stop_callback(inplace_stop_token, CallbackFn)
688
+ -> inplace_stop_callback<CallbackFn>;
689
+ }
690
+ ```
691
+
692
+ *Mandates:* `CallbackFn` satisfies both `invocable` and `destructible`.
693
+
694
+ *Remarks:* For a type `Initializer`, if
695
+
696
+ ``` cpp
697
+ stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer>
698
+ ```
699
+
700
+ is satisfied, then
701
+
702
+ ``` cpp
703
+ stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer>
704
+ ```
705
+
706
+ is modeled. For an `inplace_stop_callback<CallbackFn>` object, the
707
+ exposition-only *`callback-fn`* member is its associated callback
708
+ function [[stoptoken.concepts]].
709
+
710
+ #### Constructors and destructor <a id="stopcallback.inplace.cons">[[stopcallback.inplace.cons]]</a>
711
+
712
+ ``` cpp
713
+ template<class Initializer>
714
+ explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init)
715
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
716
+ ```
717
+
718
+ *Constraints:* `constructible_from<CallbackFn, Initializer>` is
719
+ satisfied.
720
+
721
+ *Effects:* Initializes *callback-fn* with
722
+ `std::forward<Initializer>(init)` and executes a stoppable callback
723
+ registration [[stoptoken.concepts]].
724
+
725
+ ``` cpp
726
+ ~inplace_stop_callback();
727
+ ```
728
+
729
+ *Effects:* Executes a stoppable callback
730
+ deregistration [[stoptoken.concepts]].
731