@@ -1506,6 +1506,9 @@ The changes since R9 are as follows:
1506
1506
1507
1507
<b> Enhancements:</b>
1508
1508
1509
+ * The `operation_state` concept no longer requires that operation states
1510
+ model `queryable`.
1511
+
1509
1512
* The `get_delegatee_scheduler` query has been renamed to
1510
1513
`get_delegation_scheduler`.
1511
1514
@@ -6148,14 +6151,12 @@ namespace std::execution {
6148
6151
is well-formed and denotes a scheduler `sch`. If an asynchronous operation
6149
6152
created by connecting `sndr` with a receiver `rcvr` causes the evaluation of
6150
6153
<code><i> completion-fn</i> (rcvr, args...)</code> , the behavior is undefined
6151
- unless it happens on an execution agent that belongs to `sch`'s associated
6152
- execution resource.
6154
+ unless the evaluation happens on an execution agent that belongs to `sch`'s
6155
+ associated execution resource.
6153
6156
6154
6157
4. The expression <code> forwarding_query(get_completion_scheduler<<i> completion-tag</i> >)</code>
6155
6158
is a core constant expression and has value `true`.
6156
6159
6157
- <!-- LWG stopped here -->
6158
-
6159
6160
## Schedulers <b> [exec.sched] </b> ## {#spec-execution.schedulers}
6160
6161
6161
6162
1. The `scheduler` concept defines the requirements of a scheduler type
@@ -6164,15 +6165,9 @@ namespace std::execution {
6164
6165
6165
6166
<pre highlight="c++">
6166
6167
namespace std::execution {
6167
- template<class Sch>
6168
- concept <i> enable-scheduler</i> = <i> // exposition only</i>
6169
- requires {
6170
- requires derived_from<typename Sch::scheduler_concept, scheduler_t>;
6171
- };
6172
-
6173
6168
template<class Sch>
6174
6169
concept scheduler =
6175
- <i> enable-scheduler </i> <remove_cvref_t< Sch> > &&
6170
+ derived_from <typename Sch::scheduler_concept, scheduler_t > &&
6176
6171
<i> queryable</i> <Sch> &&
6177
6172
requires(Sch&& sch) {
6178
6173
{ schedule(std::forward<Sch>(sch)) } -> sender;
@@ -6185,30 +6180,30 @@ namespace std::execution {
6185
6180
}
6186
6181
</pre>
6187
6182
6188
- 2. Let `Sch` be the type of a scheduler and let `Env` be the type of an execution
6189
- environment for which `sender_in<schedule_result_t<Sch> , Env>` is `true`. Then
6190
- <code><i> sender-of-in</i> <schedule_result_t<Sch>, Env></code> shall be `true`.
6183
+ 2. Let `Sch` be the type of a scheduler and let `Env` be the type of an
6184
+ execution environment for which `sender_in<schedule_result_t<Sch> , Env>` is
6185
+ satisfied. Then <code><i> sender-of-in</i> <schedule_result_t<Sch>,
6186
+ Env></code> shall be modeled.
6191
6187
6192
6188
3. None of a scheduler's copy constructor, destructor, equality comparison, or
6193
- `swap` member functions shall exit via an exception.
6194
-
6195
- 4. None of these member functions, nor a scheduler type's `schedule` function,
6196
- shall introduce data races as a result of concurrent invocations of those
6197
- functions from different threads.
6189
+ `swap` member functions shall exit via an exception. None of these member
6190
+ functions, nor a scheduler type's `schedule` function, shall introduce data
6191
+ races as a result of potentially concurrent ([intro.races] ) invocations of
6192
+ those functions from different threads.
6198
6193
6199
- 5 . For any two (possibly `const`) values `sch1` and `sch2` of some scheduler type
6200
- `Sch`, `sch1 == sch2` shall return `true` only if both `sch1` and `sch2` share the
6201
- same associated execution resource.
6194
+ 4 . For any two values `sch1` and `sch2` of some scheduler type `Sch`, `sch1 ==
6195
+ sch2` shall return `true` only if both `sch1` and `sch2` share the same
6196
+ associated execution resource.
6202
6197
6203
- 6 . For a given scheduler expression `sch`, the expression
6198
+ 5 . For a given scheduler expression `sch`, the expression
6204
6199
`get_completion_scheduler<set_value_t> (get_env(schedule(sch)))` shall
6205
6200
compare equal to `sch`.
6206
6201
6207
- 7 . For a given scheduler expression `sch`, if the expression `get_domain(sch)`
6202
+ 6 . For a given scheduler expression `sch`, if the expression `get_domain(sch)`
6208
6203
is well-formed, then the expression `get_domain(get_env(schedule(sch)))`
6209
6204
is also well-formed and has the same type.
6210
6205
6211
- 8 . A scheduler type's destructor shall not block pending completion of any
6206
+ 7 . A scheduler type's destructor shall not block pending completion of any
6212
6207
receivers connected to the sender objects returned from `schedule`. <span
6213
6208
class="wg21note"> The ability to wait for completion of submitted function
6214
6209
objects can be provided by the associated execution resource of the
@@ -6223,19 +6218,14 @@ namespace std::execution {
6223
6218
([async.ops] ). The `receiver_of` concept defines the requirements for a
6224
6219
receiver type that is usable as the first argument of a set of completion
6225
6220
operations corresponding to a set of completion signatures. The `get_env`
6226
- customization point is used to access a receiver's associated environment.
6221
+ customization point object is used to access a receiver's associated
6222
+ environment.
6227
6223
6228
6224
<pre highlight="c++">
6229
6225
namespace std::execution {
6230
- template<class Rcvr>
6231
- concept <i> enable-receiver</i> = // exposition only
6232
- requires {
6233
- requires derived_from<typename Rcvr::receiver_concept, receiver_t>;
6234
- };
6235
-
6236
6226
template<class Rcvr>
6237
6227
concept receiver =
6238
- <i> enable-receiver </i> <remove_cvref_t< Rcvr> > &&
6228
+ derived_from <typename Rcvr::receiver_concept, receiver_t > &&
6239
6229
requires(const remove_cvref_t<Rcvr>& rcvr) {
6240
6230
{ get_env(rcvr) } -> <i> queryable</i> ;
6241
6231
} &&
@@ -6263,39 +6253,42 @@ namespace std::execution {
6263
6253
}
6264
6254
</pre>
6265
6255
6266
- 2. Class types that are `final` do not model the `receiver` concept.
6256
+ 2. Class types that are marked `final` do not model the `receiver` concept.
6267
6257
6268
6258
3. Let `rcvr` be a receiver and let `op_state` be an operation state associated
6269
- with an asynchronous operation created by connecting `rcvr` with a sender. Let
6270
- `token` be a stop token equal to `get_stop_token(get_env(rcvr))`. `token` shall
6271
- remain valid for the duration of the asynchronous operation's lifetime
6272
- ([async.ops] ). <span class="wg21note"> This means that, unless it knows about
6273
- further guarantees provided by the type of receiver `rcvr`, the implementation
6274
- of `op_state` can not use `token` after it executes a completion operation.
6275
- This also implies that any stop callbacks registered on `token` must be
6276
- destroyed before the invocation of the completion operation.</span>
6259
+ with an asynchronous operation created by connecting `rcvr` with a sender.
6260
+ Let `token` be a stop token equal to `get_stop_token(get_env(rcvr))`.
6261
+ `token` shall remain valid for the duration of the asynchronous operation's
6262
+ lifetime ([async.ops] ). <span class="wg21note"> This means that, unless it
6263
+ knows about further guarantees provided by the type of `rcvr`, the
6264
+ implementation of `op_state` can not use `token` after it executes a
6265
+ completion operation. This also implies that any stop callbacks registered
6266
+ on `token` must be destroyed before the invocation of the completion
6267
+ operation.</span>
6277
6268
6278
6269
### `execution::set_value` <b> [exec.set.value] </b> ### {#spec-execution.receivers.set_value}
6279
6270
6280
6271
1. `set_value` is a value completion function ([async.ops] ). Its associated
6281
6272
completion tag is `set_value_t`. The expression `set_value(rcvr, vs...)` for
6282
6273
a subexpression `rcvr` and pack of subexpressions `vs` is ill-formed if `rcvr`
6283
- is an lvalue or a ` const` rvalue . Otherwise, it is expression-equivalent to
6274
+ is an lvalue or an rvalue of const type . Otherwise, it is expression-equivalent to
6284
6275
<code><i> MANDATE-NOTHROW</i> (rcvr.set_value(vs...))</code> .
6285
6276
6286
6277
### `execution::set_error` <b> [exec.set.error] </b> ### {#spec-execution.receivers.set_error}
6287
6278
6288
- 1. `set_error` is an error completion function. Its associated completion tag is
6289
- `set_error_t`. The expression `set_error(rcvr, err)` for some subexpressions `rcvr`
6290
- and `err` is ill-formed if `rcvr` is an lvalue or a `const` rvalue. Otherwise, it is
6291
- expression-equivalent to <code><i> MANDATE-NOTHROW</i> (rcvr.set_error(err))</code> .
6279
+ 1. `set_error` is an error completion function ([async.ops] ). Its associated completion tag is
6280
+ `set_error_t`. The expression `set_error(rcvr, err)` for some subexpressions
6281
+ `rcvr` and `err` is ill-formed if `rcvr` is an lvalue or an rvalue of const
6282
+ type. Otherwise, it is expression-equivalent to
6283
+ <code><i> MANDATE-NOTHROW</i> (rcvr.set_error(err))</code> .
6292
6284
6293
6285
### `execution::set_stopped` <b> [exec.set.stopped] </b> ### {#spec-execution.receivers.set_stopped}
6294
6286
6295
- 1. `set_stopped` is a stopped completion function. Its associated completion tag
6296
- is `set_stopped_t`. The expression `set_stopped(rcvr)` for a subexpression
6297
- `rcvr` is ill-formed if `rcvr` is an lvalue or a `const` rvalue. Otherwise, it is
6298
- expression-equivalent to <code><i> MANDATE-NOTHROW</i> (rcvr.set_stopped())</code> .
6287
+ 1. `set_stopped` is a stopped completion function ([async.ops] ). Its associated
6288
+ completion tag is `set_stopped_t`. The expression `set_stopped(rcvr)` for a
6289
+ subexpression `rcvr` is ill-formed if `rcvr` is an lvalue or an rvalue of
6290
+ `const` type. Otherwise, it is expression-equivalent to
6291
+ <code><i> MANDATE-NOTHROW</i> (rcvr.set_stopped())</code> .
6299
6292
6300
6293
## Operation states <b> [exec.opstate] </b> ## {#spec-execution.opstate}
6301
6294
@@ -6304,41 +6297,40 @@ namespace std::execution {
6304
6297
6305
6298
<pre highlight="c++">
6306
6299
namespace std::execution {
6307
- template<class Rcvr>
6308
- concept <i> enable-opstate</i> = // exposition only
6309
- requires {
6310
- requires derived_from<typename Rcvr::operation_state_concept, operation_state_t>;
6311
- };
6312
-
6313
6300
template<class O>
6314
6301
concept operation_state =
6315
- <i> enable-opstate</i> <remove_cvref_t<O>> &&
6316
- <i> queryable</i> <O> &&
6302
+ derived_from<typename Rcvr::operation_state_concept, operation_state_t> &&
6317
6303
is_object_v<O> &&
6318
6304
requires (O& o) {
6319
6305
{ start(o) } noexcept;
6320
6306
};
6321
6307
}
6322
6308
</pre>
6323
6309
6324
- 2. If an `operation_state` object is moved during the lifetime of its
6325
- asynchronous operation ([async.ops] ), the behavior is undefined.
6310
+ 2. If an `operation_state` object is destroyed during the lifetime of its
6311
+ asynchronous operation ([async.ops] ), the behavior is undefined. <span
6312
+ class="wg21note"> The `operation_state` concept does not impose requirements
6313
+ on any operations other than destruction and `start`, including copy and
6314
+ move operations. Invoking any such operation on an object whose type models
6315
+ `operation_state` can lead to undefined behavior.</span>
6326
6316
6327
- 3. Library-provided operation state types are non-movable.
6317
+ 3. The program is ill-formed if it performs a copy or move construction or
6318
+ assigment operation on an operation state object created by connecting a
6319
+ library-provided sender.
6328
6320
6329
6321
### `execution::start` <b> [exec.opstate.start] </b> ### {#spec-execution.opstate.start}
6330
6322
6331
6323
1. The name `start` denotes a customization point object that starts
6332
6324
([async.ops] ) the asynchronous operation associated with the operation state
6333
6325
object. For a subexpression `op`, the expression `start(op)` is ill-formed
6334
- if `op` is an rvalue. Otherwise, it is expression-equivalent to:
6326
+ if `op` is an rvalue. Otherwise, it is expression-equivalent to
6327
+ <code><i> MANDATE-NOTHROW</i> (op.start())</code> .
6335
6328
6336
- <pre highlight="c++">
6337
- <i> MANDATE-NOTHROW </i> (op.start())
6338
- </pre>
6329
+ 2. If `op.start()` does not start ( [async.ops] ) the asynchronous operation
6330
+ associated with the operation state `op`, the behavior of calling
6331
+ `start(op)` is undefined.
6339
6332
6340
- 2. If `op.start()` does not start the asynchronous operation associated with the
6341
- operation state `op`, the behavior of calling `start(op)` is undefined.
6333
+ <!-- LWG stopped here -->
6342
6334
6343
6335
## Senders <b> [exec.snd] </b> ## {#spec-execution.senders}
6344
6336
0 commit comments