C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Coroutines: Add explicit initialization by "co_init" operator

From: Julien Villemure-Fréchette <julien.villemure_at_[hidden]>
Date: Wed, 09 Aug 2023 12:32:21 -0400
> There would be no more correlation required between the return type of the Coroutine and its promise type, so one could use standard types like std::any or similar as return types to implement interfaces that hide the implementation detail of a function being a coroutine or not (which was required in what I tried to do).

You can already customize the promise type based on the signature of the coroutine signature by specializing std::coroutine_traits.
See example at https://en.cppreference.com/w/cpp/coroutine/coroutine_traits

On August 9, 2023 11:05:53 a.m. EDT, Stefan Sichler via Std-Proposals <std-proposals_at_[hidden]> wrote:
>Hi,
>
>I recently tried to add C++20 coroutine support to the I/O framework code of
>the company I'm working at and ran into very specific problems with the
>current implementation.
>
>There are also several oddities that literally instantly caught my eye, so
>I'd like to share my thoughts here:
>
>
>
>
>
>* Motivation
>
>
>
>- There is currently no way to implement a well-defined initialization of
>the promise_type from within the Coroutine's implementation body (and pass
>some parameters to the promise_type constructor).
>
>- When looking through code, it is not directly obvious whether a function
>is a coroutine or not, because for deciding that, all of the function body
>has to be searched for a call to co_await, co_yield or co_return operators.
>This is very odd, because the compiler needs to add initialization code
>right at the very beginning of the function body anyway, if the function is
>a Coroutine.
>
>- The return type of a Coroutine is forced to expose "promise_type" as part
>of the Coroutine signature, because it needs to be defined in its return
>type, but this should actually be an implementation detail of the Coroutine
>and thus should not be directly visible in the signature.
>
>- The promise_type cannot have a member field of type of the return type,
>because the promise_type needs to be declared inside the return type, so the
>type definition of the return type is incomplete at that point.
>
>- The return object is created by promise_type::get_return_object() *before*
>the Coroutine implementation body had any chance of initializing the promise
>object by any means. (this was a major problem in my case that a had to work
>around in very ugly ways!)
>
>
>
>
>
>* My Proposal
>
>
>
>*All* of these points could be resolved by removing the requirement of
>defining a type "promise_type" in the return type of a Coroutine and instead
>adding a mandatory explicit coroutine initialization call within the
>Coroutine's implementation body, let's say a call to some new "co_init"
>operator.
>
>The return type of the expression passed to the co_init operator shall then
>define the promise type (and the promise object could be move-constructed
>from the return value of this expression).
>
>
>
>So, a coroutine body may then look like this:
>
>
>
>return_type my_coroutine(...)
>
>{
>
> co_init make_my_cool_promise(args...);
>
> ...
>
> co_await...
>
> ...
>
>}
>
>
>
>or (perhaps an even better syntax?):
>
>
>
>return_type my_coroutine(...)
>
> : co_init(make_my_cool_promise(args...))
>
>{
>
> ...
>
> co_await...
>
> ...
>
>}
>
>
>
>
>
>This approach has several benefits:
>
>
>
>- By forcing the co_init operator to be right at the beginning of the
>function body, one could clearly see that this function is actually a
>coroutine instead of a traditional function, so the compiler would instantly
>know that it has to inject specific initialization code right here.
>
>- There would be no more correlation required between the return type of the
>Coroutine and its promise type, so one could use standard types like
>std::any or similar as return types to implement interfaces that hide the
>implementation detail of a function being a coroutine or not (which was
>required in what I tried to do).
>
>- One could also be able to implement Coroutines with different promise
>types returning identical return types which is currently AFAIK not
>possible.
>
>- The coroutine implementation would now have a very simple way to influence
>the creation of the return object: it now explicitly initializes the promise
>object by move-construction from the return expression of the co_init
>operator *before* the return object is created by a call to the promise
>object's get_return_object() method. This is straight forward!
>
>- The type name "promise_type" would no longer need to be a reserved type
>name, because the name of the promise type would no longer matter - this
>feels like a much cleaner approach than the current implementation.
>
>- Coroutine Templates would be easy to achieve, because this approach allows
>templated promise types, depending on the template parameters of the
>Coroutine.
>
>
>
>
>
>* Outlook
>
>
>
>Coroutines, defined the way they are currently, are restricted to the body
>of a *single* function, meaning that there is currently no way to co_await
>in a sub-function called from the Coroutine and cause suspension of the
>calling Coroutine by this.
>
>But even this limitation can be overcome by an explicit co_init operator,
>because it also clearly defines the point to return to when the Coroutine is
>suspended. So now, when a sub-function is called from a Coroutine which is
>itself _not_ a Coroutine (because it misses co_init), but somewhere a
>co_await operator is encountered, then the *calling* Coroutine - if any -
>could be suspended, otherwise the call would be illegal. Of course, this
>would require a try/catch/throw-like compiler support.
>
>
>
>
>
>So, what do you think?
>
>
>
>I'm sorry that my proposal isn't clearly technically worked out now, and I'm
>sure that it requires major refinements from this point on, but wouldn't
>this actually be a very useful and reasonable modification of the current
>Coroutines specification?
>
>
>
>Best Regards
>
>Stefan
>
>
>

Received on 2023-08-09 16:32:32