Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-09-24 15:23:59


niedz., 24 wrz 2023 o 16:17 Klemens Morgenstern <
klemensdavidmorgenstern_at_[hidden]> napisał(a):

> >>
> >> Why? How would you want to communicate to the awaiter that the coro is
> done?
> >
> >
> > First, there are a bunch of use cases where the consumer of the
> generator doesn't need to know, like the one with the listener: keep
> generating until you are canceled.
>
> Ok, so it's technically UB, but you can skip the co_return. That will
> however generate a warning on msvc, so it's not officially recommended
> or mentioned in the docs.
> But I tested it on all compilers and it seemed to work.
>

It is only UB if the control reaches the end of the body.
But if I know the loop is infinite and I will be always canceling the
coroutine (calling .destroy()), reaching the end of function body does not
happen, and therefore no UB.

>
> This is an issue with the C++ API. A coroutine promise can either have
> a return_value OR a return_void. I cannot have both at the same time.
> If that was possible, I'd do it.
>

OK, I now understand why std::generator does not trigger an analogous
warning in MSVC.
std::generator<T>::promise_type defines the pair yield_value() and
return_void(). So you can yield a value from a std::generator but you
cannot return one.

Question: Is it important to the design of async::generator to allow
`co_return value`? All the examples of coroutines I have ever seen yield
values in a loop.

> > Second, std::generator somehow does it. (I do not know how.)
>
> It does it by using iterators. I.e. you advance the iterator, which
> will resume the coroutine. Then you check against end() if it
> co_returned (void) and then you get the cached value.
>
> The async::generator does it in one call.
>

Yeah, so the interface of std::generator is similar to returning
optional<T> form async::generator.
In the sense that it returns two pieces of information: (1) whether we are
at the end, (2) and if not, what value we have.

>
> > Back to your question, when I see a code structure like this:
> >
> > async::generator<T> fun()
> > {
> > while(cond)
> > {
> > co_yield something;
> > }
> > }
> >
> > I know that there is nothing to do after the last co_yield in the loop.
> So maybe the compiler/library should also.
> > Modulo that this may not be doable in the library, or the hacks are too
> expensive.
>
> It's doable, but the price is more API complication. I think a dummy
> return while annoying is the best solution.
> Because otherwise the user needs to use a different generator type if
> he wants to use a significant value return as indication he's done
> (e.g. a generator<system::result<size_t>>.).
>

Given the present interface, I have two ways of checking the "I am done"
state:
1. One is to call generator::operator bool()
2. The other is to inspect the state of the yielded value.

I see no use for the first one. There is an `operator bool` that doesn't do
the job. Or did I misunderstand again?

Would it be correct to say that I cannot use `async::generator<T>`
effectively when my type `T` doesn't have a special dummy state?

> The asio::experimental::coro defaults to using an optional btw., which
> I find much more cumbersome as a default, especially with the example
> above.
>

I am aware of two use cases. One where the resumer decides when the
generation ends, the other when it is the generator that decides. For the
former case, you are right. For the latter case, using optional is no worse
than testing the dummy value on one side, and putting an additional code to
generate the dummy value on the other.

Regards,
&rzej;

>
>
> >
> > Regards,
> > &rzej;
> >
> >>
> >>
> >>
> >>> that the end of generation should be signaled in this way.
> >>>
> >>> Regards,
> >>> &rzej;
> >>>
> >>> _______________________________________________
> >>> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk