Skip to content

Commit 077ddcc

Browse files
committed
LWG feedback from the 2024-05-29 telecon
1 parent 05d84e5 commit 077ddcc

File tree

1 file changed

+60
-68
lines changed

1 file changed

+60
-68
lines changed

execution.bs

Lines changed: 60 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,9 @@ The changes since R9 are as follows:
15061506

15071507
<b>Enhancements:</b>
15081508

1509+
* The `operation_state` concept no longer requires that operation states
1510+
model `queryable`.
1511+
15091512
* The `get_delegatee_scheduler` query has been renamed to
15101513
`get_delegation_scheduler`.
15111514

@@ -6148,14 +6151,12 @@ namespace std::execution {
61486151
is well-formed and denotes a scheduler `sch`. If an asynchronous operation
61496152
created by connecting `sndr` with a receiver `rcvr` causes the evaluation of
61506153
<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.
61536156

61546157
4. The expression <code>forwarding_query(get_completion_scheduler&lt;<i>completion-tag</i>>)</code>
61556158
is a core constant expression and has value `true`.
61566159

6157-
<!-- LWG stopped here -->
6158-
61596160
## Schedulers <b>[exec.sched] </b> ## {#spec-execution.schedulers}
61606161

61616162
1. The `scheduler` concept defines the requirements of a scheduler type
@@ -6164,15 +6165,9 @@ namespace std::execution {
61646165

61656166
<pre highlight="c++">
61666167
namespace std::execution {
6167-
template&lt;class Sch>
6168-
concept <i>enable-scheduler</i> = <i>// exposition only</i>
6169-
requires {
6170-
requires derived_from&lt;typename Sch::scheduler_concept, scheduler_t>;
6171-
};
6172-
61736168
template&lt;class Sch>
61746169
concept scheduler =
6175-
<i>enable-scheduler</i>&lt;remove_cvref_t&lt;Sch>> &&
6170+
derived_from&lt;typename Sch::scheduler_concept, scheduler_t> &&
61766171
<i>queryable</i>&lt;Sch> &&
61776172
requires(Sch&& sch) {
61786173
{ schedule(std::forward&lt;Sch>(sch)) } -> sender;
@@ -6185,30 +6180,30 @@ namespace std::execution {
61856180
}
61866181
</pre>
61876182

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>&lt;schedule_result_t&lt;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>&lt;schedule_result_t&lt;Sch>,
6186+
Env></code> shall be modeled.
61916187

61926188
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.
61986193

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.
62026197

6203-
6. For a given scheduler expression `sch`, the expression
6198+
5. For a given scheduler expression `sch`, the expression
62046199
`get_completion_scheduler<set_value_t>(get_env(schedule(sch)))` shall
62056200
compare equal to `sch`.
62066201

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)`
62086203
is well-formed, then the expression `get_domain(get_env(schedule(sch)))`
62096204
is also well-formed and has the same type.
62106205

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
62126207
receivers connected to the sender objects returned from `schedule`. <span
62136208
class="wg21note">The ability to wait for completion of submitted function
62146209
objects can be provided by the associated execution resource of the
@@ -6223,19 +6218,14 @@ namespace std::execution {
62236218
([async.ops]). The `receiver_of` concept defines the requirements for a
62246219
receiver type that is usable as the first argument of a set of completion
62256220
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.
62276223

62286224
<pre highlight="c++">
62296225
namespace std::execution {
6230-
template&lt;class Rcvr>
6231-
concept <i>enable-receiver</i> = // exposition only
6232-
requires {
6233-
requires derived_from&lt;typename Rcvr::receiver_concept, receiver_t>;
6234-
};
6235-
62366226
template&lt;class Rcvr>
62376227
concept receiver =
6238-
<i>enable-receiver</i>&lt;remove_cvref_t&lt;Rcvr>> &&
6228+
derived_from&lt;typename Rcvr::receiver_concept, receiver_t> &&
62396229
requires(const remove_cvref_t&lt;Rcvr>& rcvr) {
62406230
{ get_env(rcvr) } -> <i>queryable</i>;
62416231
} &&
@@ -6263,39 +6253,42 @@ namespace std::execution {
62636253
}
62646254
</pre>
62656255

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.
62676257

62686258
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>
62776268

62786269
### `execution::set_value` <b>[exec.set.value]</b> ### {#spec-execution.receivers.set_value}
62796270

62806271
1. `set_value` is a value completion function ([async.ops]). Its associated
62816272
completion tag is `set_value_t`. The expression `set_value(rcvr, vs...)` for
62826273
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
62846275
<code><i>MANDATE-NOTHROW</i>(rcvr.set_value(vs...))</code>.
62856276

62866277
### `execution::set_error` <b>[exec.set.error]</b> ### {#spec-execution.receivers.set_error}
62876278

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>.
62926284

62936285
### `execution::set_stopped` <b>[exec.set.stopped]</b> ### {#spec-execution.receivers.set_stopped}
62946286

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>.
62996292

63006293
## Operation states <b>[exec.opstate]</b> ## {#spec-execution.opstate}
63016294

@@ -6304,41 +6297,40 @@ namespace std::execution {
63046297

63056298
<pre highlight="c++">
63066299
namespace std::execution {
6307-
template&lt;class Rcvr>
6308-
concept <i>enable-opstate</i> = // exposition only
6309-
requires {
6310-
requires derived_from&lt;typename Rcvr::operation_state_concept, operation_state_t>;
6311-
};
6312-
63136300
template&lt;class O>
63146301
concept operation_state =
6315-
<i>enable-opstate</i>&lt;remove_cvref_t&lt;O>> &&
6316-
<i>queryable</i>&lt;O> &&
6302+
derived_from&lt;typename Rcvr::operation_state_concept, operation_state_t> &&
63176303
is_object_v&lt;O> &&
63186304
requires (O& o) {
63196305
{ start(o) } noexcept;
63206306
};
63216307
}
63226308
</pre>
63236309

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>
63266316

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.
63286320

63296321
### `execution::start` <b>[exec.opstate.start]</b> ### {#spec-execution.opstate.start}
63306322

63316323
1. The name `start` denotes a customization point object that starts
63326324
([async.ops]) the asynchronous operation associated with the operation state
63336325
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>.
63356328

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.
63396332

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 -->
63426334

63436335
## Senders <b>[exec.snd]</b> ## {#spec-execution.senders}
63446336

0 commit comments

Comments
 (0)