Good day. I'm learning coroutines and I don't see any clarification in the standard about a few things.
First, can a coroutine be resumed inside an await_suspend call? I mean the following patterns
void await_suspend(auto self) {
self.resume();
}
bool await_suspend(auto self) {
self.resume();
return false; // UB here?
}
auto await_suspend(auto self) {
auto h2 = some_handle_;
self.resume();
return h2;
}
These calls behave differently. If false is returned, the coroutine is resumed twice from the same point, which (maybe) looks like an optimization in the implementations. This happens in both gcc and clang (
https://godbolt.org/z/KM63dooae)
The second thing I'd like to find out is, is it possible to return the handle of the coroutine itself to resume it directly? And can it be combined with the above?
auto await_suspend(auto self) {
// self.resume();
return self;
}
I think the first case where you call `resume()` directly, and then return `void`, is fine because there's no second resumption. The same goes for the last case.
The only precondition for `std::coroutine_handle<P>::resume()` is
that the coroutine it refers to is suspended and not at its final
suspend point (
[coroutine.handle.resumption]/2). When `await_suspend` is entered, the coroutine has already been suspended (
[expr.await]/5.1), so resuming the enclosing coroutine is permitted.
About the second and third cases where there's an implicit resumption upon return from `await_suspend`, it does seem odd to me that the result is not the same as that of explicitly calling `resume()` twice. Like you say, maybe this is an optimization. And maybe the compilers do this optimization because they believe that it should be UB when you do this. I suggest filing bugs against clang and gcc and then you can see how they respond.
Thank you for your attention.
Artyom Kolpakov
Translated with DeepL.com (free version)
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion