From Jason Turner

[exec.run.loop]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp7htfzw8x/{from.md → to.md} +217 -0
tmp/tmp7htfzw8x/{from.md → to.md} RENAMED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### `execution::run_loop` <a id="exec.run.loop">[[exec.run.loop]]</a>
2
+
3
+ #### General <a id="exec.run.loop.general">[[exec.run.loop.general]]</a>
4
+
5
+ A `run_loop` is an execution resource on which work can be scheduled. It
6
+ maintains a thread-safe first-in-first-out queue of work. Its `run`
7
+ member function removes elements from the queue and executes them in a
8
+ loop on the thread of execution that calls `run`.
9
+
10
+ A `run_loop` instance has an associated *count* that corresponds to the
11
+ number of work items that are in its queue. Additionally, a `run_loop`
12
+ instance has an associated state that can be one of *starting*,
13
+ *running*, *finishing*, or *finished*.
14
+
15
+ Concurrent invocations of the member functions of `run_loop` other than
16
+ `run` and its destructor do not introduce data races. The member
17
+ functions *`pop-front`*, *`push-back`*, and `finish` execute atomically.
18
+
19
+ *Recommended practice:* Implementations should use an intrusive queue of
20
+ operation states to hold the work units to make scheduling
21
+ allocation-free.
22
+
23
+ ``` cpp
24
+ namespace std::execution {
25
+ class run_loop {
26
+ // [exec.run.loop.types], associated types
27
+ class run-loop-scheduler; // exposition only
28
+ class run-loop-sender; // exposition only
29
+ struct run-loop-opstate-base { // exposition only
30
+ virtual void execute() = 0; // exposition only
31
+ run_loop* loop; // exposition only
32
+ run-loop-opstate-base* next; // exposition only
33
+ };
34
+ template<class Rcvr>
35
+ using run-loop-opstate = unspecified; // exposition only
36
+
37
+ // [exec.run.loop.members], member functions
38
+ run-loop-opstate-base* pop-front(); // exposition only
39
+ void push-back(run-loop-opstate-base*); // exposition only
40
+
41
+ public:
42
+ // [exec.run.loop.ctor], constructor and destructor
43
+ run_loop() noexcept;
44
+ run_loop(run_loop&&) = delete;
45
+ ~run_loop();
46
+
47
+ // [exec.run.loop.members], member functions
48
+ run-loop-scheduler get_scheduler();
49
+ void run();
50
+ void finish();
51
+ };
52
+ }
53
+ ```
54
+
55
+ #### Associated types <a id="exec.run.loop.types">[[exec.run.loop.types]]</a>
56
+
57
+ ``` cpp
58
+ class run-loop-scheduler;
59
+ ```
60
+
61
+ *`run-loop-scheduler`* is an unspecified type that models `scheduler`.
62
+
63
+ Instances of *`run-loop-scheduler`* remain valid until the end of the
64
+ lifetime of the `run_loop` instance from which they were obtained.
65
+
66
+ Two instances of *`run-loop-scheduler`* compare equal if and only if
67
+ they were obtained from the same `run_loop` instance.
68
+
69
+ Let *`sch`* be an expression of type *`run-loop-scheduler`*. The
70
+ expression `schedule(sch)` has type *`run-loop- sender`* and is not
71
+ potentially-throwing if *`sch`* is not potentially-throwing.
72
+
73
+ ``` cpp
74
+ class run-loop-sender;
75
+ ```
76
+
77
+ *`run-loop-sender`* is an exposition-only type that satisfies `sender`.
78
+ `completion_signatures_of_t<run-{loop-sender}>` is
79
+
80
+ ``` cpp
81
+ completion_signatures<set_value_t(), set_error_t(exception_ptr), set_stopped_t()>
82
+ ```
83
+
84
+ An instance of *`run-loop-sender`* remains valid until the end of the
85
+ lifetime of its associated `run_loop` instance.
86
+
87
+ Let *`sndr`* be an expression of type *`run-loop-sender`*, let *`rcvr`*
88
+ be an expression such that `receiver_of<decltype((rcvr)), CS>` is `true`
89
+ where `CS` is the `completion_signatures` specialization above. Let `C`
90
+ be either `set_value_t` or `set_stopped_t`. Then:
91
+
92
+ - The expression `connect(sndr, rcvr)` has type
93
+ `run-loop-opstate<decay_t<decltype((rcvr))>>` and is
94
+ potentially-throwing if and only if `(void(sndr), auto(rcvr))` is
95
+ potentially-throwing.
96
+ - The expression `get_completion_scheduler<C>(get_env(sndr))` is
97
+ potentially-throwing if and only if *`sndr`* is potentially-throwing,
98
+ has type *`run-loop-scheduler`*, and compares equal to the
99
+ *`run-loop- scheduler`* instance from which *`sndr`* was obtained.
100
+
101
+ ``` cpp
102
+ template<class Rcvr>
103
+ struct run-loop-opstate;
104
+ ```
105
+
106
+ `\exposid{run-loop-opstate}<Rcvr>`
107
+
108
+ inherits privately and unambiguously from *`run-loop-opstate-base`*.
109
+
110
+ Let o be a non-const lvalue of type `run-loop-opstate<Rcvr>`, and let
111
+ `REC(o)` be a non-const lvalue reference to an instance of type `Rcvr`
112
+ that was initialized with the expression *`rcvr`* passed to the
113
+ invocation of connect that returned o. Then:
114
+
115
+ - The object to which `REC(o)` refers remains valid for the lifetime of
116
+ the object to which o refers.
117
+ - The type `run-loop-opstate<Rcvr>` overrides
118
+ `run-loop-opstate-base::execute()` such that `o.execute()` is
119
+ equivalent to:
120
+ ``` cpp
121
+ if (get_stop_token(REC(o)).stop_requested()) {
122
+ set_stopped(std::move(REC(o)));
123
+ } else {
124
+ set_value(std::move(REC(o)));
125
+ }
126
+ ```
127
+ - The expression `start(o)` is equivalent to:
128
+ ``` cpp
129
+ try {
130
+ o.loop->push-back(addressof(o));
131
+ } catch(...) {
132
+ set_error(std::move(REC(o)), current_exception());
133
+ }
134
+ ```
135
+
136
+ #### Constructor and destructor <a id="exec.run.loop.ctor">[[exec.run.loop.ctor]]</a>
137
+
138
+ ``` cpp
139
+ run_loop() noexcept;
140
+ ```
141
+
142
+ *Ensures:* The `run_loop` instance’s count is 0 and its state is
143
+ starting.
144
+
145
+ ``` cpp
146
+ ~run_loop();
147
+ ```
148
+
149
+ *Effects:* If the `run_loop` instance’s count is not 0 or if its state
150
+ is running, invokes `terminate` [[except.terminate]]. Otherwise, has no
151
+ effects.
152
+
153
+ #### Member functions <a id="exec.run.loop.members">[[exec.run.loop.members]]</a>
154
+
155
+ ``` cpp
156
+ run-loop-opstate-base* pop-front();
157
+ ```
158
+
159
+ *Effects:* Blocks [[defns.block]] until one of the following conditions
160
+ is `true`:
161
+
162
+ - The `run_loop` instance’s count is 0 and its state is finishing, in
163
+ which case *pop-front* sets the state to finished and returns
164
+ `nullptr`; or
165
+ - the `run_loop` instance’s count is greater than 0, in which case an
166
+ item is removed from the front of the queue, the count is decremented
167
+ by `1`, and the removed item is returned.
168
+
169
+ ``` cpp
170
+ void push-back(run-loop-opstate-base* item);
171
+ ```
172
+
173
+ *Effects:* Adds `item` to the back of the queue and increments the
174
+ `run_loop` instance’s count by 1.
175
+
176
+ *Synchronization:* This operation synchronizes with the *pop-front*
177
+ operation that obtains `item`.
178
+
179
+ ``` cpp
180
+ run-loop-scheduler get_scheduler();
181
+ ```
182
+
183
+ *Returns:* An instance of *run-loop-scheduler* that can be used to
184
+ schedule work onto this `run_loop` instance.
185
+
186
+ ``` cpp
187
+ void run();
188
+ ```
189
+
190
+ *Preconditions:* The `run_loop` instance’s state is either starting or
191
+ finishing.
192
+
193
+ *Effects:* If the `run_loop` instance’s state is starting, sets the
194
+ state to running, otherwise leaves the state unchanged. Then, equivalent
195
+ to:
196
+
197
+ ``` cpp
198
+ while (auto* op = pop-front()) {
199
+ op->execute();
200
+ }
201
+ ```
202
+
203
+ *Remarks:* When the `run_loop` instance’s state changes, it does so
204
+ without introducing data races.
205
+
206
+ ``` cpp
207
+ void finish();
208
+ ```
209
+
210
+ *Preconditions:* The `run_loop` instance’s state is either starting or
211
+ running.
212
+
213
+ *Effects:* Changes the `run_loop` instance’s state to finishing.
214
+
215
+ *Synchronization:* `finish` synchronizes with the *pop-front* operation
216
+ that returns `nullptr`.
217
+