From Jason Turner

[exec.task]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpnqqwociq/{from.md → to.md} +418 -0
tmp/tmpnqqwociq/{from.md → to.md} RENAMED
@@ -0,0 +1,418 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### `execution::task` <a id="exec.task">[[exec.task]]</a>
2
+
3
+ #### `task` overview <a id="task.overview">[[task.overview]]</a>
4
+
5
+ The `task` class template represents a sender that can be used as the
6
+ return type of coroutines. The first template parameter `T` defines the
7
+ type of the value completion datum [[exec.async.ops]] if `T` is not
8
+ `void`. Otherwise, there are no value completion datums. Inside
9
+ coroutines returning `task<T, E>` the operand of `co_return` (if any)
10
+ becomes the argument of `set_value`. The second template parameter
11
+ `Environment` is used to customize the behavior of `task`.
12
+
13
+ #### Class template `task` <a id="task.class">[[task.class]]</a>
14
+
15
+ ``` cpp
16
+ namespace std::execution {
17
+ template<class T, class Environment>
18
+ class task {
19
+ // [task.state]
20
+ template<receiver Rcvr>
21
+ class state; // exposition only
22
+
23
+ public:
24
+ using sender_concept = sender_t;
25
+ using completion_signatures = see below;
26
+ using allocator_type = see below;
27
+ using scheduler_type = see below;
28
+ using stop_source_type = see below;
29
+ using stop_token_type = decltype(declval<stop_source_type>().get_token());
30
+ using error_types = see below;
31
+
32
+ // [task.promise]
33
+ class promise_type;
34
+
35
+ task(task&&) noexcept;
36
+ ~task();
37
+
38
+ template<receiver Rcvr>
39
+ state<Rcvr> connect(Rcvr&& rcvr);
40
+
41
+ private:
42
+ coroutine_handle<promise_type> handle; // exposition only
43
+ };
44
+ }
45
+ ```
46
+
47
+ `task<T, E>` models `sender` [[exec.snd]] if `T` is `void`, a reference
48
+ type, or a cv-unqualified non-array object type and `E` is a class type.
49
+ Otherwise a program that instantiates the definition of `task<T, E>` is
50
+ ill-formed.
51
+
52
+ The nested types of `task` template specializations are determined based
53
+ on the `Environment` parameter:
54
+
55
+ - `allocator_type` is `Environment::allocator_type` if that
56
+ *qualified-id* is valid and denotes a type, `allocator<byte>`
57
+ otherwise.
58
+ - `scheduler_type` is `Environment::scheduler_type` if that
59
+ *qualified-id* is valid and denotes a type, `task_scheduler`
60
+ otherwise.
61
+ - `stop_source_type` is `Environment::stop_source_type` if that
62
+ *qualified-id* is valid and denotes a type, `inplace_stop_source`
63
+ otherwise.
64
+ - `error_types` is `Environment::error_types` if that *qualified-id* is
65
+ valid and denotes a type,
66
+ `completion_signatures<set_error_t(exception_ptr)>` otherwise.
67
+
68
+ A program is ill-formed if `error_types` is not a specialization of
69
+ `execution::completion_signatures` or if the template arguments of that
70
+ specialization contain an element which is not of the form
71
+ `set_error_t(E)` for some type `E`.
72
+
73
+ The type alias `completion_signatures` is a specialization of
74
+ `execution::completion_signatures` with the template arguments (in
75
+ unspecified order):
76
+
77
+ - `set_value_t()` if `T` is `void`, and `set_value_t(T)` otherwise;
78
+ - template arguments of the specialization of
79
+ `execution::completion_signatures` denoted by `error_types`; and
80
+ - `set_stopped_t()`.
81
+
82
+ `allocator_type` shall meet the *Cpp17Allocator* requirements.
83
+
84
+ #### `task` members <a id="task.members">[[task.members]]</a>
85
+
86
+ ``` cpp
87
+ task(task&& other) noexcept;
88
+ ```
89
+
90
+ *Effects:* Initializes *handle* with `exchange(other.`*`handle`*`, {})`.
91
+
92
+ ``` cpp
93
+ ~task();
94
+ ```
95
+
96
+ *Effects:* Equivalent to:
97
+
98
+ ``` cpp
99
+ if (handle)
100
+ handle.destroy();
101
+ ```
102
+
103
+ ``` cpp
104
+ template<receiver Rcvr>
105
+ state<Rcvr> connect(Rcvr&& recv);
106
+ ```
107
+
108
+ *Preconditions:* `bool(`*`handle`*`)` is `true`.
109
+
110
+ *Effects:* Equivalent to:
111
+
112
+ ``` cpp
113
+ return state<Rcvr>(exchange(handle, {}), std::forward<Rcvr>(recv));
114
+ ```
115
+
116
+ #### Class template `task::state` <a id="task.state">[[task.state]]</a>
117
+
118
+ ``` cpp
119
+ namespace std::execution {
120
+ template<class T, class Environment>
121
+ template<receiver Rcvr>
122
+ class task<T, Environment>::state { // exposition only
123
+ public:
124
+ using operation_state_concept = operation_state_t;
125
+
126
+ template<class R>
127
+ state(coroutine_handle<promise_type> h, R&& rr);
128
+
129
+ ~state();
130
+
131
+ void start() & noexcept;
132
+
133
+ private:
134
+ using own-env-t = see belownc; // exposition only
135
+ coroutine_handle<promise_type> handle; // exposition only
136
+ remove_cvref_t<Rcvr> rcvr; // exposition only
137
+ own-env-t own-env; // exposition only
138
+ Environment environment; // exposition only
139
+ };
140
+ }
141
+ ```
142
+
143
+ The type *`own-env-t`* is `Environment::template
144
+ env_type<decltype(get_env({}declval{}<Rcvr>({}))){}>` if that
145
+ *qualified-id* is valid and denotes a type, `env<>` otherwise.
146
+
147
+ ``` cpp
148
+ template<class R>
149
+ state(coroutine_handle<promise_type> h, R&& rr);
150
+ ```
151
+
152
+ *Effects:* Initializes
153
+
154
+ - *handle* with `std::move(h)`;
155
+ - *rcvr* with `std::forward<R>(rr)`;
156
+ - *own-env* with *`own-env-t`*`(get_env(`*`rcvr`*`))` if that expression
157
+ is valid and *`own-env-t`*`()` otherwise. If neither of these
158
+ expressions is valid, the program is ill-formed.
159
+ - *environment* with `Environment(`*`own-env`*`)` if that expression is
160
+ valid, otherwise `Environment(get_env(`*`rcvr`*`))` if this expression
161
+ is valid, otherwise `Environment()`. If neither of these expressions
162
+ is valid, the program is ill-formed.
163
+
164
+ ``` cpp
165
+ ~state();
166
+ ```
167
+
168
+ *Effects:* Equivalent to:
169
+
170
+ ``` cpp
171
+ if (handle)
172
+ handle.destroy();
173
+ ```
174
+
175
+ ``` cpp
176
+ void start() & noexcept;
177
+ ```
178
+
179
+ *Effects:* Let *`prom`* be the object *`handle`*`.promise()`. Associates
180
+ *`STATE`*`(`*`prom`*`)`, *`RCVR`*`(`*`prom`*`)`, and
181
+ *`SCHED`*`(`*`prom`*`)` with `*this` as follows:
182
+
183
+ - *`STATE`*`(`*`prom`*`)` is `*this`.
184
+ - *`RCVR`*`(`*`prom`*`)` is *rcvr*.
185
+ - *`SCHED`*`(`*`prom`*`)` is the object initialized with
186
+ `scheduler_type(get_scheduler(get_env(`*`rcvr`*`)))` if that
187
+ expression is valid and `scheduler_type()` otherwise. If neither of
188
+ these expressions is valid, the program is ill-formed.
189
+
190
+ Let *`st`* be `get_stop_token(get_env(`*`rcvr`*`))`. Initializes
191
+ *`prom`*`.`*`token`* and *`prom`*`.`*`source`* such that
192
+
193
+ - *`prom`*`.`*`token`*`.stop_requested()` returns
194
+ *`st`*`.stop_requested()`;
195
+ - *`prom`*`.`*`token`*`.stop_possible()` returns
196
+ *`st`*`.stop_possible()`; and
197
+ - for types `Fn` and `Init` such that both `invocable<Fn>` and
198
+ `constructible_from<Fn, Init>` are modeled,
199
+ `stop_token_type::callback_type<Fn>` models
200
+ `stoppable-callback-for<Fn, stop_token_type, Init>`.
201
+
202
+ After that invokes *`handle`*`.resume()`.
203
+
204
+ #### Class `task::promise_type` <a id="task.promise">[[task.promise]]</a>
205
+
206
+ ``` cpp
207
+ namespace std::execution {
208
+ template<class T, class Environment>
209
+ class task<T, Environment>::promise_type {
210
+ public:
211
+ template<class... Args>
212
+ promise_type(const Args&... args);
213
+
214
+ task get_return_object() noexcept;
215
+
216
+ auto initial_suspend() noexcept;
217
+ auto final_suspend() noexcept;
218
+
219
+ void uncaught_exception();
220
+ coroutine_handle<> unhandled_stopped();
221
+
222
+ void return_void(); // present only if is_void_v<T> is true
223
+ template<class V>
224
+ void return_value(V&& value); // present only if is_void_v<T> is false
225
+
226
+ template<class E>
227
+ unspecified yield_value(with_error<E> error);
228
+
229
+ template<class A>
230
+ auto await_transform(A&& a);
231
+ template<class Sch>
232
+ auto await_transform(change_coroutine_scheduler<Sch> sch);
233
+
234
+ unspecified get_env() const noexcept;
235
+
236
+ template<class... Args>
237
+ void* operator new(size_t size, Args&&... args);
238
+
239
+ void operator delete(void* pointer, size_t size) noexcept;
240
+
241
+ private:
242
+ using error-variant = see belownc; // exposition only
243
+
244
+ allocator_type alloc; // exposition only
245
+ stop_source_type source; // exposition only
246
+ stop_token_type token; // exposition only
247
+ optional<T> result; // exposition only; present only if is_void_v<T> is false
248
+ error-variant errors; // exposition only
249
+ };
250
+ }
251
+ ```
252
+
253
+ Let `prom` be an object of `promise_type` and let `tsk` be the `task`
254
+ object created by `prom.get_return_object()`. The description below
255
+ refers to objects `STATE(prom)`, `RCVR(prom)`, and `SCHED(prom)`
256
+ associated with `tsk` during evaluation of `task::state<Rcvr>::start`
257
+ for some receiver `Rcvr`.
258
+
259
+ *`error-variant`* is a `variant<monostate,
260
+ remove_cvref_t<E>...>`, with duplicate types removed, where `E...` are
261
+ the parameter types of the template arguments of the specialization of
262
+ `execution::completion_signatures` denoted by `error_types`.
263
+
264
+ ``` cpp
265
+ template<class... Args>
266
+ promise_type(const Args&... args);
267
+ ```
268
+
269
+ *Mandates:* The first parameter of type `allocator_arg_t` (if any) is
270
+ not the last parameter.
271
+
272
+ *Effects:* If `Args` contains an element of type `allocator_arg_t` then
273
+ *alloc* is initialized with the corresponding next element of `args`.
274
+ Otherwise, *alloc* is initialized with `allocator_type()`.
275
+
276
+ ``` cpp
277
+ task get_return_object() noexcept;
278
+ ```
279
+
280
+ *Returns:* A `task` object whose member *handle* is
281
+ `coroutine_handle<promise_type>::from_promise(*this)`.
282
+
283
+ ``` cpp
284
+ auto initial_suspend() noexcept;
285
+ ```
286
+
287
+ *Returns:* An awaitable object of unspecified type [[expr.await]] whose
288
+ member functions arrange for
289
+
290
+ - the calling coroutine to be suspended,
291
+ - the coroutine to be resumed on an execution agent of the execution
292
+ resource associated with *`SCHED`*`(*this)`.
293
+
294
+ ``` cpp
295
+ auto final_suspend() noexcept;
296
+ ```
297
+
298
+ *Returns:* An awaitable object of unspecified type [[expr.await]] whose
299
+ member functions arrange for the completion of the asynchronous
300
+ operation associated with *`STATE`*`(*this)` by invoking:
301
+
302
+ - `set_error(std::move(`*`RCVR`*`(*this)), std::move(e))` if
303
+ *`errors`*`.index()` is greater than zero and `e` is the value held by
304
+ *errors*, otherwise
305
+ - `set_value(std::move(`*`RCVR`*`(*this)))` if `is_void<T>` is `true`,
306
+ and otherwise
307
+ - `set_value(std::move(`*`RCVR`*`(*this)), *`*`result`*`)`.
308
+
309
+ ``` cpp
310
+ template<class Err>
311
+ auto yield_value(with_error<Err> err);
312
+ ```
313
+
314
+ *Mandates:* `std::move(err.error)` is convertible to exactly one of the
315
+ `set_error_t` argument types of `error_types`. Let *`Cerr`* be that
316
+ type.
317
+
318
+ *Returns:* An awaitable object of unspecified type [[expr.await]] whose
319
+ member functions arrange for the calling coroutine to be suspended and
320
+ then completes the asynchronous operation associated with
321
+ *`STATE`*`(*this)` by invoking
322
+ `set_error(std::move(`*`RCVR`*`(*this)), `*`Cerr`*`(std::move(err.error)))`.
323
+
324
+ ``` cpp
325
+ template<sender Sender>
326
+ auto await_transform(Sender&& sndr) noexcept;
327
+ ```
328
+
329
+ *Returns:* If `same_as<inline_scheduler, scheduler_type>` is `true`
330
+ returns `as_awaitable(std::forward<Sender>(sndr), *this)`; otherwise
331
+ returns
332
+ `as_awaitable(affine_on(std::forward<Sender>(sndr), `*`SCHED`*`(*this)), *this)`.
333
+
334
+ ``` cpp
335
+ template<class Sch>
336
+ auto await_transform(change_coroutine_scheduler<Sch> sch) noexcept;
337
+ ```
338
+
339
+ *Effects:* Equivalent to:
340
+
341
+ ``` cpp
342
+ return await_transform(just(exchange(SCHED(*this), scheduler_type(sch.scheduler))), *this);
343
+ ```
344
+
345
+ ``` cpp
346
+ void uncaught_exception();
347
+ ```
348
+
349
+ *Effects:* If the signature `set_error_t(exception_ptr)` is not an
350
+ element of `error_types`, calls `terminate()` [[except.terminate]].
351
+ Otherwise, stores `current_exception()` into *errors*.
352
+
353
+ ``` cpp
354
+ coroutine_handle<> unhandled_stopped();
355
+ ```
356
+
357
+ *Effects:* Completes the asynchronous operation associated with
358
+ *`STATE`*`(*this)` by invoking
359
+ `set_stopped(std::move(`*`RCVR`*`(*this)))`.
360
+
361
+ *Returns:* `noop_coroutine()`.
362
+
363
+ ``` cpp
364
+ unspecified get_env() const noexcept;
365
+ ```
366
+
367
+ *Returns:* An object `env` such that queries are forwarded as follows:
368
+
369
+ - `env.query(get_scheduler)` returns
370
+ `scheduler_type(`*`SCHED`*`(*this))`.
371
+ - `env.query(get_allocator)` returns *alloc*.
372
+ - `env.query(get_stop_token)` returns *token*.
373
+ - For any other query `q` and arguments `a...` a call to
374
+ `env.query(q, a...)` returns *`STATE`*`(*this)`.
375
+ `environment.query(q, a...)` if this expression is well-formed and
376
+ `forwarding_query(q)` is well-formed and is `true`. Otherwise
377
+ `env.query(q, a...)` is ill-formed.
378
+
379
+ ``` cpp
380
+ template<class... Args>
381
+ void* operator new(size_t size, const Args&... args);
382
+ ```
383
+
384
+ If there is no parameter with type `allocator_arg_t` then let `alloc` be
385
+ `allocator_type()`. Otherwise, let `arg_next` be the parameter following
386
+ the first `allocator_arg_t` parameter, and let `alloc` be
387
+ `allocator_type(arg_next)`. Let `PAlloc` be
388
+ `allocator_traits<allocator_type>::template rebind_alloc<U>`, where `U`
389
+ is an unspecified type whose size and alignment are both
390
+ \_\_STDCPP_DEFAULT_NEW_ALIGNMENT\_\_.
391
+
392
+ *Mandates:*
393
+
394
+ - The first parameter of type `allocator_arg_t` (if any) is not the last
395
+ parameter.
396
+ - `allocator_type(arg_next)` is a valid expression if there is a
397
+ parameter of type `allocator_arg_t`.
398
+ - `allocator_traits<PAlloc>::pointer` is a pointer type.
399
+
400
+ *Effects:* Initializes an allocator `palloc` of type `PAlloc` with
401
+ `alloc`. Uses `palloc` to allocate storage for the smallest array of `U`
402
+ sufficient to provide storage for a coroutine state of size `size`, and
403
+ unspecified additional state necessary to ensure that `operator delete`
404
+ can later deallocate this memory block with an allocator equal to
405
+ `palloc`.
406
+
407
+ *Returns:* A pointer to the allocated storage.
408
+
409
+ ``` cpp
410
+ void operator delete(void* pointer, size_t size) noexcept;
411
+ ```
412
+
413
+ *Preconditions:* `pointer` was returned from an invocation of the above
414
+ overload of `operator new` with a size argument equal to `size`.
415
+
416
+ *Effects:* Deallocates the storage pointed to by `pointer` using an
417
+ allocator equal to that used to allocate it.
418
+