From Jason Turner

[dcl.fct.def.coroutine]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpxxxnlvst/{from.md → to.md} +73 -66
tmp/tmpxxxnlvst/{from.md → to.md} RENAMED
@@ -31,19 +31,21 @@ task<void> g3(int a, ...) { // error: variable parameter list not allowed
31
 
32
  — *end example*]
33
 
34
  The *promise type* of a coroutine is
35
  `std::coroutine_traits<R, P₁, …, Pₙ>::promise_type`, where `R` is the
36
- return type of the function, and `P₁` … `Pₙ` are the sequence of types
37
- of the function parameters, preceded by the type of the implicit object
38
- parameter [[over.match.funcs]] if the coroutine is a non-static member
39
- function. The promise type shall be a class type.
40
 
41
- In the following, `pᵢ` is an lvalue of type `Pᵢ`, where `p₁` denotes
42
- `*this` and `p_i+1` denotes the $i^\textrm{th}$ function parameter for a
43
- non-static member function, and `pᵢ` denotes the $i^\textrm{th}$
44
- function parameter otherwise.
 
 
45
 
46
  A coroutine behaves as if its *function-body* were replaced by:
47
 
48
  ``` bnf
49
  '{'
@@ -64,75 +66,81 @@ final-suspend ':'
64
  ```
65
 
66
  where
67
 
68
  - the *await-expression* containing the call to `initial_suspend` is the
69
- *initial suspend point*, and
70
  - the *await-expression* containing the call to `final_suspend` is the
71
- *final suspend point*, and
72
  - *initial-await-resume-called* is initially `false` and is set to
73
  `true` immediately before the evaluation of the *await-resume*
74
- expression [[expr.await]] of the initial suspend point, and
75
  - *promise-type* denotes the promise type, and
76
  - the object denoted by the exposition-only name *`promise`* is the
77
  *promise object* of the coroutine, and
78
  - the label denoted by the name *`final-suspend`* is defined for
79
  exposition only [[stmt.return.coroutine]], and
80
  - *promise-constructor-arguments* is determined as follows: overload
81
  resolution is performed on a promise constructor call created by
82
- assembling an argument list with lvalues `p₁` … `pₙ`. If a viable
83
- constructor is found [[over.match.viable]], then
84
- *promise-constructor-arguments* is `(p₁, …, pₙ)`, otherwise
85
- *promise-constructor-arguments* is empty.
 
 
 
 
86
 
87
- The *unqualified-id*s `return_void` and `return_value` are looked up in
88
- the scope of the promise type. If both are found, the program is
89
  ill-formed.
90
 
91
- [*Note 1*: If the *unqualified-id* `return_void` is found, flowing off
92
- the end of a coroutine is equivalent to a `co_return` with no operand.
93
- Otherwise, flowing off the end of a coroutine results in undefined
94
- behavior [[stmt.return.coroutine]]. — *end note*]
95
 
96
  The expression `promise.get_return_object()` is used to initialize the
97
- glvalue result or prvalue result object of a call to a coroutine. The
98
- call to `get_return_object` is sequenced before the call to
99
  `initial_suspend` and is invoked at most once.
100
 
101
  A suspended coroutine can be resumed to continue execution by invoking a
102
  resumption member function [[coroutine.handle.resumption]] of a
103
  coroutine handle [[coroutine.handle]] that refers to the coroutine. The
104
- function that invoked a resumption member function is called the
105
  *resumer*. Invoking a resumption member function for a coroutine that is
106
  not suspended results in undefined behavior.
107
 
108
  An implementation may need to allocate additional storage for a
109
  coroutine. This storage is known as the *coroutine state* and is
110
  obtained by calling a non-array allocation function
111
  [[basic.stc.dynamic.allocation]]. The allocation function’s name is
112
- looked up in the scope of the promise type. If this lookup fails, the
113
- allocation function’s name is looked up in the global scope. If the
114
- lookup finds an allocation function in the scope of the promise type,
115
- overload resolution is performed on a function call created by
116
- assembling an argument list. The first argument is the amount of space
117
- requested, and has type `std::size_t`. The lvalues `p₁` … `pₙ` are the
118
- succeeding arguments. If no viable function is found
119
- [[over.match.viable]], overload resolution is performed again on a
120
- function call created by passing just the amount of space required as an
121
- argument of type `std::size_t`.
122
 
123
- The *unqualified-id* `get_return_object_on_allocation_failure` is looked
124
- up in the scope of the promise type by class member access lookup
125
- [[basic.lookup.classref]]. If any declarations are found, then the
126
- result of a call to an allocation function used to obtain storage for
127
- the coroutine state is assumed to return `nullptr` if it fails to obtain
128
- storage, and if a global allocation function is selected, the
129
- `::operator new(size_t, nothrow_t)` form is used. The allocation
130
- function used in this case shall have a non-throwing
131
- *noexcept-specification*. If the allocation function returns `nullptr`,
132
- the coroutine returns control to the caller of the coroutine and the
133
- return value is obtained by a call to
 
 
 
 
 
 
 
 
 
 
 
134
  `T::get_return_object_on_allocation_failure()`, where `T` is the promise
135
  type.
136
 
137
  [*Example 2*:
138
 
@@ -147,11 +155,11 @@ struct generator {
147
  struct promise_type {
148
  int current_value;
149
  static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }
150
  auto get_return_object() { return generator{handle::from_promise(*this)}; }
151
  auto initial_suspend() { return std::suspend_always{}; }
152
- auto final_suspend() { return std::suspend_always{}; }
153
  void unhandled_exception() { std::terminate(); }
154
  void return_void() {}
155
  auto yield_value(int value) {
156
  current_value = value;
157
  return std::suspend_always{};
@@ -177,30 +185,28 @@ int main() {
177
 
178
  The coroutine state is destroyed when control flows off the end of the
179
  coroutine or the `destroy` member function
180
  [[coroutine.handle.resumption]] of a coroutine handle
181
  [[coroutine.handle]] that refers to the coroutine is invoked. In the
182
- latter case objects with automatic storage duration that are in scope at
183
- the suspend point are destroyed in the reverse order of the
184
- construction. The storage for the coroutine state is released by calling
185
- a non-array deallocation function [[basic.stc.dynamic.deallocation]]. If
186
- `destroy` is called for a coroutine that is not suspended, the program
187
- has undefined behavior.
188
 
189
- The deallocation function’s name is looked up in the scope of the
190
- promise type. If this lookup fails, the deallocation function’s name is
191
- looked up in the global scope. If deallocation function lookup finds
192
- both a usual deallocation function with only a pointer parameter and a
193
- usual deallocation function with both a pointer parameter and a size
194
- parameter, then the selected deallocation function shall be the one with
195
- two parameters. Otherwise, the selected deallocation function shall be
196
- the function with one parameter. If no usual deallocation function is
197
- found, the program is ill-formed. The selected deallocation function
198
- shall be called with the address of the block of storage to be reclaimed
199
- as its first argument. If a deallocation function with a parameter of
200
- type `std::size_t` is used, the size of the block is passed as the
201
- corresponding argument.
202
 
203
  When a coroutine is invoked, after initializing its parameters
204
  [[expr.call]], a copy is created for each coroutine parameter. For a
205
  parameter of type cv `T`, the copy is a variable of type cv `T` with
206
  automatic storage duration that is direct-initialized from an xvalue of
@@ -221,10 +227,11 @@ the coroutine after the lifetime of the entity referred to by that
221
  parameter has ended is likely to result in undefined
222
  behavior. — *end note*]
223
 
224
  If the evaluation of the expression `promise.unhandled_exception()`
225
  exits via an exception, the coroutine is considered suspended at the
226
- final suspend point.
 
227
 
228
  The expression `co_await` `promise.final_suspend()` shall not be
229
  potentially-throwing [[except.spec]].
230
 
 
31
 
32
  — *end example*]
33
 
34
  The *promise type* of a coroutine is
35
  `std::coroutine_traits<R, P₁, …, Pₙ>::promise_type`, where `R` is the
36
+ return type of the function, and `P₁` … `Pₙ` is the sequence of types of
37
+ the non-object function parameters, preceded by the type of the object
38
+ parameter [[dcl.fct]] if the coroutine is a non-static member function.
39
+ The promise type shall be a class type.
40
 
41
+ In the following, `pᵢ` is an lvalue of type `Pᵢ`, where `p₁` denotes the
42
+ object parameter and `p_i+1` denotes the iᵗʰ non-object function
43
+ parameter for a non-static member function, and `pᵢ` denotes the iᵗʰ
44
+ function parameter otherwise. For a non-static member function, `q₁` is
45
+ an lvalue that denotes `*this`; any other `qᵢ` is an lvalue that denotes
46
+ the parameter copy corresponding to `pᵢ`, as described below.
47
 
48
  A coroutine behaves as if its *function-body* were replaced by:
49
 
50
  ``` bnf
51
  '{'
 
66
  ```
67
 
68
  where
69
 
70
  - the *await-expression* containing the call to `initial_suspend` is the
71
+ *initial await expression*, and
72
  - the *await-expression* containing the call to `final_suspend` is the
73
+ *final await expression*, and
74
  - *initial-await-resume-called* is initially `false` and is set to
75
  `true` immediately before the evaluation of the *await-resume*
76
+ expression [[expr.await]] of the initial await expression, and
77
  - *promise-type* denotes the promise type, and
78
  - the object denoted by the exposition-only name *`promise`* is the
79
  *promise object* of the coroutine, and
80
  - the label denoted by the name *`final-suspend`* is defined for
81
  exposition only [[stmt.return.coroutine]], and
82
  - *promise-constructor-arguments* is determined as follows: overload
83
  resolution is performed on a promise constructor call created by
84
+ assembling an argument list `q₁` … `qₙ`. If a viable constructor is
85
+ found [[over.match.viable]], then *promise-constructor-arguments* is
86
+ `(q₁, …, qₙ)`, otherwise *promise-constructor-arguments* is empty, and
87
+ - a coroutine is suspended at the *initial suspend point* if it is
88
+ suspended at the initial await expression, and
89
+ - a coroutine is suspended at a *final suspend point* if it is suspended
90
+ - at a final await expression or
91
+ - due to an exception exiting from `unhandled_exception()`.
92
 
93
+ If searches for the names `return_void` and `return_value` in the scope
94
+ of the promise type each find any declarations, the program is
95
  ill-formed.
96
 
97
+ [*Note 1*: If `return_void` is found, flowing off the end of a
98
+ coroutine is equivalent to a `co_return` with no operand. Otherwise,
99
+ flowing off the end of a coroutine results in undefined behavior
100
+ [[stmt.return.coroutine]]. — *end note*]
101
 
102
  The expression `promise.get_return_object()` is used to initialize the
103
+ returned reference or prvalue result object of a call to a coroutine.
104
+ The call to `get_return_object` is sequenced before the call to
105
  `initial_suspend` and is invoked at most once.
106
 
107
  A suspended coroutine can be resumed to continue execution by invoking a
108
  resumption member function [[coroutine.handle.resumption]] of a
109
  coroutine handle [[coroutine.handle]] that refers to the coroutine. The
110
+ evaluation that invoked a resumption member function is called the
111
  *resumer*. Invoking a resumption member function for a coroutine that is
112
  not suspended results in undefined behavior.
113
 
114
  An implementation may need to allocate additional storage for a
115
  coroutine. This storage is known as the *coroutine state* and is
116
  obtained by calling a non-array allocation function
117
  [[basic.stc.dynamic.allocation]]. The allocation function’s name is
118
+ looked up by searching for it in the scope of the promise type.
 
 
 
 
 
 
 
 
 
119
 
120
+ - If the search finds any declarations, overload resolution is performed
121
+ on a function call created by assembling an argument list. The first
122
+ argument is the amount of space requested, and is a prvalue of type
123
+ `std::size_t`. The lvalues `p₁` `pₙ` are the successive arguments.
124
+ If no viable function is found [[over.match.viable]], overload
125
+ resolution is performed again on a function call created by passing
126
+ just the amount of space required as a prvalue of type `std::size_t`.
127
+ - If the search finds no declarations, a search is performed in the
128
+ global scope. Overload resolution is performed on a function call
129
+ created by passing the amount of space required as a prvalue of type
130
+ `std::size_t`.
131
+
132
+ If a search for the name `get_return_object_on_allocation_failure` in
133
+ the scope of the promise type [[class.member.lookup]] finds any
134
+ declarations, then the result of a call to an allocation function used
135
+ to obtain storage for the coroutine state is assumed to return `nullptr`
136
+ if it fails to obtain storage, and if a global allocation function is
137
+ selected, the `::operator new(size_t, nothrow_t)` form is used. The
138
+ allocation function used in this case shall have a non-throwing
139
+ *noexcept-specifier*. If the allocation function returns `nullptr`, the
140
+ coroutine returns control to the caller of the coroutine and the return
141
+ value is obtained by a call to
142
  `T::get_return_object_on_allocation_failure()`, where `T` is the promise
143
  type.
144
 
145
  [*Example 2*:
146
 
 
155
  struct promise_type {
156
  int current_value;
157
  static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }
158
  auto get_return_object() { return generator{handle::from_promise(*this)}; }
159
  auto initial_suspend() { return std::suspend_always{}; }
160
+ auto final_suspend() noexcept { return std::suspend_always{}; }
161
  void unhandled_exception() { std::terminate(); }
162
  void return_void() {}
163
  auto yield_value(int value) {
164
  current_value = value;
165
  return std::suspend_always{};
 
185
 
186
  The coroutine state is destroyed when control flows off the end of the
187
  coroutine or the `destroy` member function
188
  [[coroutine.handle.resumption]] of a coroutine handle
189
  [[coroutine.handle]] that refers to the coroutine is invoked. In the
190
+ latter case, control in the coroutine is considered to be transferred
191
+ out of the function [[stmt.dcl]]. The storage for the coroutine state is
192
+ released by calling a non-array deallocation function
193
+ [[basic.stc.dynamic.deallocation]]. If `destroy` is called for a
194
+ coroutine that is not suspended, the program has undefined behavior.
 
195
 
196
+ The deallocation function’s name is looked up by searching for it in the
197
+ scope of the promise type. If nothing is found, a search is performed in
198
+ the global scope. If both a usual deallocation function with only a
199
+ pointer parameter and a usual deallocation function with both a pointer
200
+ parameter and a size parameter are found, then the selected deallocation
201
+ function shall be the one with two parameters. Otherwise, the selected
202
+ deallocation function shall be the function with one parameter. If no
203
+ usual deallocation function is found, the program is ill-formed. The
204
+ selected deallocation function shall be called with the address of the
205
+ block of storage to be reclaimed as its first argument. If a
206
+ deallocation function with a parameter of type `std::size_t` is used,
207
+ the size of the block is passed as the corresponding argument.
 
208
 
209
  When a coroutine is invoked, after initializing its parameters
210
  [[expr.call]], a copy is created for each coroutine parameter. For a
211
  parameter of type cv `T`, the copy is a variable of type cv `T` with
212
  automatic storage duration that is direct-initialized from an xvalue of
 
227
  parameter has ended is likely to result in undefined
228
  behavior. — *end note*]
229
 
230
  If the evaluation of the expression `promise.unhandled_exception()`
231
  exits via an exception, the coroutine is considered suspended at the
232
+ final suspend point and the exception propagates to the caller or
233
+ resumer.
234
 
235
  The expression `co_await` `promise.final_suspend()` shall not be
236
  potentially-throwing [[except.spec]].
237