tmp/tmp2zeg3cpk/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#### `execution::on` <a id="exec.on">[[exec.on]]</a>
|
| 2 |
+
|
| 3 |
+
The `on` sender adaptor has two forms:
|
| 4 |
+
|
| 5 |
+
- `on(sch, sndr)`, which starts a sender `sndr` on an execution agent
|
| 6 |
+
belonging to a scheduler `sch`’s associated execution resource and
|
| 7 |
+
that, upon `sndr`’s completion, transfers execution back to the
|
| 8 |
+
execution resource on which the `on` sender was started.
|
| 9 |
+
- `on(sndr, sch, closure)`, which upon completion of a sender `sndr`,
|
| 10 |
+
transfers execution to an execution agent belonging to a scheduler
|
| 11 |
+
`sch`’s associated execution resource, then executes a sender adaptor
|
| 12 |
+
closure `closure` with the async results of the sender, and that then
|
| 13 |
+
transfers execution back to the execution resource on which `sndr`
|
| 14 |
+
completed.
|
| 15 |
+
|
| 16 |
+
The name `on` denotes a pipeable sender adaptor object. For
|
| 17 |
+
subexpressions `sch` and `sndr`, `on(sch, sndr)` is ill-formed if any of
|
| 18 |
+
the following is `true`:
|
| 19 |
+
|
| 20 |
+
- `decltype((sch))` does not satisfy `scheduler`, or
|
| 21 |
+
- `decltype((sndr))` does not satisfy `sender` and `sndr` is not a
|
| 22 |
+
pipeable sender adaptor closure object [[exec.adapt.obj]], or
|
| 23 |
+
- `decltype((sndr))` satisfies `sender` and `sndr `is also a pipeable
|
| 24 |
+
sender adaptor closure object.
|
| 25 |
+
|
| 26 |
+
Otherwise, if `decltype((sndr))` satisfies `sender`, the expression
|
| 27 |
+
`on(sch, sndr)` is expression-equivalent to:
|
| 28 |
+
|
| 29 |
+
``` cpp
|
| 30 |
+
transform_sender(
|
| 31 |
+
query-with-default(get_domain, sch, default_domain()),
|
| 32 |
+
make-sender(on, sch, sndr))
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
except that `sch` is evaluated only once.
|
| 36 |
+
|
| 37 |
+
For subexpressions `sndr`, `sch`, and `closure`, if
|
| 38 |
+
|
| 39 |
+
- `decltype((sch))` does not satisfy `scheduler`, or
|
| 40 |
+
- `decltype((sndr))` does not satisfy `sender`, or
|
| 41 |
+
- `closure` is not a pipeable sender adaptor closure object
|
| 42 |
+
[[exec.adapt.obj]],
|
| 43 |
+
|
| 44 |
+
the expression `on(sndr, sch, closure)` is ill-formed; otherwise, it is
|
| 45 |
+
expression-equivalent to:
|
| 46 |
+
|
| 47 |
+
``` cpp
|
| 48 |
+
transform_sender(
|
| 49 |
+
get-domain-early(sndr),
|
| 50 |
+
make-sender(on, product-type{sch, closure}, sndr))
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
except that `sndr` is evaluated only once.
|
| 54 |
+
|
| 55 |
+
Let `out_sndr` and `env` be subexpressions, let `OutSndr` be
|
| 56 |
+
`decltype((out_sndr))`, and let `Env` be `decltype((env))`. If
|
| 57 |
+
`sender-for<OutSndr, on_t>` is `false`, then the expressions
|
| 58 |
+
`on.transform_env(out_sndr, env)` and
|
| 59 |
+
`on.transform_sender(out_sndr, env)` are ill-formed.
|
| 60 |
+
|
| 61 |
+
Otherwise: Let *`not-a-scheduler`* be an unspecified empty class type.
|
| 62 |
+
|
| 63 |
+
The expression `on.transform_env(out_sndr, env)` has effects equivalent
|
| 64 |
+
to:
|
| 65 |
+
|
| 66 |
+
``` cpp
|
| 67 |
+
auto&& [_, data, _] = out_sndr;
|
| 68 |
+
if constexpr (scheduler<decltype(data)>) {
|
| 69 |
+
return JOIN-ENV(SCHED-ENV(std::forward_like<OutSndr>(data)), FWD-ENV(std::forward<Env>(env)));
|
| 70 |
+
} else {
|
| 71 |
+
return std::forward<Env>(env);
|
| 72 |
+
}
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
The expression `on.transform_sender(out_sndr, env)` has effects
|
| 76 |
+
equivalent to:
|
| 77 |
+
|
| 78 |
+
``` cpp
|
| 79 |
+
auto&& [_, data, child] = out_sndr;
|
| 80 |
+
if constexpr (scheduler<decltype(data)>) {
|
| 81 |
+
auto orig_sch =
|
| 82 |
+
query-with-default(get_scheduler, env, not-a-scheduler());
|
| 83 |
+
|
| 84 |
+
if constexpr (same_as<decltype(orig_sch), not-a-scheduler>) {
|
| 85 |
+
return not-a-sender{};
|
| 86 |
+
} else {
|
| 87 |
+
return continues_on(
|
| 88 |
+
starts_on(std::forward_like<OutSndr>(data), std::forward_like<OutSndr>(child)),
|
| 89 |
+
std::move(orig_sch));
|
| 90 |
+
}
|
| 91 |
+
} else {
|
| 92 |
+
auto& [sch, closure] = data;
|
| 93 |
+
auto orig_sch = query-with-default(
|
| 94 |
+
get_completion_scheduler<set_value_t>,
|
| 95 |
+
get_env(child),
|
| 96 |
+
query-with-default(get_scheduler, env, not-a-scheduler()));
|
| 97 |
+
|
| 98 |
+
if constexpr (same_as<decltype(orig_sch), not-a-scheduler>) {
|
| 99 |
+
return not-a-sender{};
|
| 100 |
+
} else {
|
| 101 |
+
return write_env(
|
| 102 |
+
continues_on(
|
| 103 |
+
std::forward_like<OutSndr>(closure)(
|
| 104 |
+
continues_on(
|
| 105 |
+
write_env(std::forward_like<OutSndr>(child), SCHED-ENV(orig_sch)),
|
| 106 |
+
sch)),
|
| 107 |
+
orig_sch),
|
| 108 |
+
SCHED-ENV(sch));
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
Let `out_sndr` be a subexpression denoting a sender returned from
|
| 114 |
+
`on(sch, sndr)` or one equal to such, and let `OutSndr` be the type
|
| 115 |
+
`decltype((out_sndr))`. Let `out_rcvr` be a subexpression denoting a
|
| 116 |
+
receiver that has an environment of type `Env` such that
|
| 117 |
+
`sender_in<OutSndr, Env>` is `true`. Let `op` be an lvalue referring to
|
| 118 |
+
the operation state that results from connecting `out_sndr` with
|
| 119 |
+
`out_rcvr`. Calling `start(op)` shall
|
| 120 |
+
|
| 121 |
+
- remember the current scheduler, `get_scheduler(get_env(rcvr))`;
|
| 122 |
+
- start `sndr` on an execution agent belonging to `sch`’s associated
|
| 123 |
+
execution resource;
|
| 124 |
+
- upon `sndr`’s completion, transfer execution back to the execution
|
| 125 |
+
resource associated with the scheduler remembered in step 1; and
|
| 126 |
+
- forward `sndr`’s async result to `out_rcvr`.
|
| 127 |
+
|
| 128 |
+
If any scheduling operation fails, an error completion on `out_rcvr`
|
| 129 |
+
shall be executed on an unspecified execution agent.
|
| 130 |
+
|
| 131 |
+
Let `out_sndr` be a subexpression denoting a sender returned from
|
| 132 |
+
`on(sndr, sch, closure)` or one equal to such, and let `OutSndr` be the
|
| 133 |
+
type `decltype((out_sndr))`. Let `out_rcvr` be a subexpression denoting
|
| 134 |
+
a receiver that has an environment of type `Env` such that
|
| 135 |
+
`sender_in<OutSndr, Env>` is `true`. Let `op` be an lvalue referring to
|
| 136 |
+
the operation state that results from connecting `out_sndr` with
|
| 137 |
+
`out_rcvr`. Calling `start(op)` shall
|
| 138 |
+
|
| 139 |
+
- remember the current scheduler, which is the first of the following
|
| 140 |
+
expressions that is well-formed:
|
| 141 |
+
- `get_completion_scheduler<set_value_t>(get_env(sndr))`
|
| 142 |
+
- `get_scheduler(get_env(rcvr))`;
|
| 143 |
+
- start `sndr` on the current execution agent;
|
| 144 |
+
- upon `sndr`’s completion, transfer execution to an agent owned by
|
| 145 |
+
`sch`’s associated execution resource;
|
| 146 |
+
- forward `sndr`’s async result as if by connecting and starting a
|
| 147 |
+
sender `closure(S)`, where `S` is a sender that completes
|
| 148 |
+
synchronously with `sndr`’s async result; and
|
| 149 |
+
- upon completion of the operation started in the previous step,
|
| 150 |
+
transfer execution back to the execution resource associated with the
|
| 151 |
+
scheduler remembered in step 1 and forward the operation’s async
|
| 152 |
+
result to `out_rcvr`.
|
| 153 |
+
|
| 154 |
+
If any scheduling operation fails, an error completion on `out_rcvr`
|
| 155 |
+
shall be executed on an unspecified execution agent.
|
| 156 |
+
|