From Jason Turner

[exec.schedule.from]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp0q8g2ahn/{from.md → to.md} +182 -0
tmp/tmp0q8g2ahn/{from.md → to.md} RENAMED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### `execution::schedule_from` <a id="exec.schedule.from">[[exec.schedule.from]]</a>
2
+
3
+ `schedule_from` schedules work dependent on the completion of a sender
4
+ onto a scheduler’s associated execution resource.
5
+
6
+ [*Note 1*: `schedule_from` is not meant to be used in user code; it is
7
+ used in the implementation of `continues_on`. — *end note*]
8
+
9
+ The name `schedule_from` denotes a customization point object. For some
10
+ subexpressions `sch` and `sndr`, let `Sch` be `decltype((sch))` and
11
+ `Sndr` be `decltype((sndr))`. If `Sch` does not satisfy `scheduler`, or
12
+ `Sndr` does not satisfy `sender`, `schedule_from(sch, sndr)` is
13
+ ill-formed.
14
+
15
+ Otherwise, the expression `schedule_from(sch, sndr)` is
16
+ expression-equivalent to:
17
+
18
+ ``` cpp
19
+ transform_sender(
20
+ query-with-default(get_domain, sch, default_domain()),
21
+ make-sender(schedule_from, sch, sndr))
22
+ ```
23
+
24
+ except that `sch` is evaluated only once.
25
+
26
+ The exposition-only class template *`impls-for`* [[exec.snd.expos]] is
27
+ specialized for `schedule_from_t` as follows:
28
+
29
+ ``` cpp
30
+ namespace std::execution {
31
+ template<>
32
+ struct impls-for<schedule_from_t> : default-impls {
33
+ static constexpr auto get-attrs = see below;
34
+ static constexpr auto get-state = see below;
35
+ static constexpr auto complete = see below;
36
+
37
+ template<class Sndr, class... Env>
38
+ static consteval void check-types();
39
+ };
40
+ }
41
+ ```
42
+
43
+ The member `impls-for<schedule_from_t>::get-attrs` is initialized with a
44
+ callable object equivalent to the following lambda:
45
+
46
+ ``` cpp
47
+ [](const auto& data, const auto& child) noexcept -> decltype(auto) {
48
+ return JOIN-ENV(SCHED-ATTRS(data), FWD-ENV(get_env(child)));
49
+ }
50
+ ```
51
+
52
+ The member `impls-for<schedule_from_t>::get-state` is initialized with a
53
+ callable object equivalent to the following lambda:
54
+
55
+ ``` cpp
56
+ []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below)
57
+ requires sender_in<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)> {
58
+
59
+ auto& [_, sch, child] = sndr;
60
+
61
+ using sched_t = decltype(auto(sch));
62
+ using variant_t = see below;
63
+ using receiver_t = see below;
64
+ using operation_t = connect_result_t<schedule_result_t<sched_t>, receiver_t>;
65
+ constexpr bool nothrow = noexcept(connect(schedule(sch), receiver_t{nullptr}));
66
+
67
+ struct state-type {
68
+ Rcvr& rcvr; // exposition only
69
+ variant_t async-result; // exposition only
70
+ operation_t op-state; // exposition only
71
+
72
+ explicit state-type(sched_t sch, Rcvr& rcvr) noexcept(nothrow)
73
+ : rcvr(rcvr), op-state(connect(schedule(sch), receiver_t{this})) {}
74
+ };
75
+
76
+ return state-type{sch, rcvr};
77
+ }
78
+ ```
79
+
80
+ ``` cpp
81
+ template<class Sndr, class... Env>
82
+ static consteval void check-types();
83
+ ```
84
+
85
+ *Effects:* Equivalent to:
86
+
87
+ ``` cpp
88
+ get_completion_signatures<schedule_result_t<data-type<Sndr>>, FWD-ENV-T(Env)...>();
89
+ auto cs = get_completion_signatures<child-type<Sndr>, FWD-ENV-T(Env)...>();
90
+ decay-copyable-result-datums(cs); // see [exec.snd.expos]
91
+ ```
92
+
93
+ Objects of the local class *`state-type`* can be used to initialize a
94
+ structured binding.
95
+
96
+ Let `Sigs` be a pack of the arguments to the `completion_signatures`
97
+ specialization named by
98
+ `completion_signatures_of_t<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)>`.
99
+ Let *`as-tuple`* be an alias template such that `as-tuple<Tag(Args...)>`
100
+ denotes the type `decayed-tuple<Tag, Args...>`, and let
101
+ *`is-nothrow-decay-copy-sig`* be a variable template such that
102
+ `auto(is-nothrow-decay-copy-sig<Tag(Args...{})>)` is a constant
103
+ expression of type `bool` and equal to
104
+ `(is_nothrow_constructible_v<decay_t<Args>, Args> && ...)`. Let
105
+ *`error-completion`* be a pack consisting of the type
106
+ `set_error_t(exception_ptr)` if
107
+ `(is-nothrow-decay-copy-sig<Sigs> &&...)` is `false`, and an empty pack
108
+ otherwise. Then `variant_t` denotes the type
109
+ `variant<monostate, as-tuple<Sigs>..., error-completion...>`, except
110
+ with duplicate types removed.
111
+
112
+ `receiver_t` is an alias for the following exposition-only class:
113
+
114
+ ``` cpp
115
+ namespace std::execution {
116
+ struct receiver-type {
117
+ using receiver_concept = receiver_t;
118
+ state-type* state; // exposition only
119
+
120
+ void set_value() && noexcept {
121
+ visit(
122
+ [this]<class Tuple>(Tuple& result) noexcept -> void {
123
+ if constexpr (!same_as<monostate, Tuple>) {
124
+ auto& [tag, ...args] = result;
125
+ tag(std::move(state->rcvr), std::move(args)...);
126
+ }
127
+ },
128
+ state->async-result);
129
+ }
130
+
131
+ template<class Error>
132
+ void set_error(Error&& err) && noexcept {
133
+ execution::set_error(std::move(state->rcvr), std::forward<Error>(err));
134
+ }
135
+
136
+ void set_stopped() && noexcept {
137
+ execution::set_stopped(std::move(state->rcvr));
138
+ }
139
+
140
+ decltype(auto) get_env() const noexcept {
141
+ return FWD-ENV(execution::get_env(state->rcvr));
142
+ }
143
+ };
144
+ }
145
+ ```
146
+
147
+ The expression in the `noexcept` clause of the lambda is `true` if the
148
+ construction of the returned *`state-type`* object is not potentially
149
+ throwing; otherwise, `false`.
150
+
151
+ The member `impls-for<schedule_from_t>::complete` is initialized with a
152
+ callable object equivalent to the following lambda:
153
+
154
+ ``` cpp
155
+ []<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
156
+ -> void {
157
+ using result_t = decayed-tuple<Tag, Args...>;
158
+ constexpr bool nothrow = (is_nothrow_constructible_v<decay_t<Args>, Args> && ...);
159
+
160
+ try {
161
+ state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
162
+ } catch (...) {
163
+ if constexpr (!nothrow)
164
+ state.async-result.template emplace<tuple<set_error_t,
165
+ exception_ptr>>(set_error, current_exception());
166
+ }
167
+ start(state.op-state);
168
+ };
169
+ ```
170
+
171
+ Let `out_sndr` be a subexpression denoting a sender returned from
172
+ `schedule_from(sch, sndr)` or one equal to such, and let `OutSndr` be
173
+ the type `decltype((out_sndr))`. Let `out_rcvr` be a subexpression
174
+ denoting a receiver that has an environment of type `Env` such that
175
+ `sender_in<OutSndr, Env>` is `true`. Let `op` be an lvalue referring to
176
+ the operation state that results from connecting `out_sndr` with
177
+ `out_rcvr`. Calling `start(op)` shall start `sndr` on the current
178
+ execution agent and execute completion operations on `out_rcvr` on an
179
+ execution agent of the execution resource associated with `sch`. If
180
+ scheduling onto `sch` fails, an error completion on `out_rcvr` shall be
181
+ executed on an unspecified execution agent.
182
+