Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-08-18 22:05:09


Hi Everyone,
I will not be able to write a decent review due to the lack of time (I am
now on vacation), but I wanted to share some partial feedback.

I am not well familiar with C++ coroutines. I wrote some toy examples of an
async TCP echo server in ASIO in the past, to try to learn how coroutines
work, but my knowledge is very superficial. I hoped to understand
coroutines better from studying Boost.Async's docs.

When I discovered Boost some 18 years ago, I found it useful not only
because of the high quality libraries but also because of extraordinary
documentation that often provided a very deep insight into the problem
domain, a lot of rationale, design goals, and the documentation of
engineering trade-offs of different sorts. I do not know how people feel
about the importance of documentation nowadays. For me, however, it is the
primary focus. I devoted like 10 hours in total for studying the docs and
running some toy examples. Because I am not very good at C++ coroutines,
you get a typical, I would think, feedback from a user that wants to learn
how coroutines are used, what problems they solve, and what problems they
do not solve.

Regarding the *really* asynchronous part, promises and tasks, I guess they
would work fine. By "really asynchronous" I mean the situations where a
coroutine is resumed by events unpredictable by the programmer (when data
arrives, when certain time passes, when an external connection is
requested). I also guess that when Marcelo and Ruben say they successfully
integrated Boost.Async into their projects, they meant types `task` and
`promise`, rather than `generator`.

My investigation was interrupted by `generator` which I cannot understand
or appreciate. It feels like a type quite separate from the rest of the
library. For instance, through all the simple examples in the docs, only
the examples for `generator` never use the trick with `co_await
async::this_coro::executor`.

I needed to ask a lot of questions, and even though Klemens is very
responsive and very helpful, I still do not understand how
`async::generator` solves real problems. This may indicate that either I am
a very slow learner, or that there is something wrong with the design of
`generator`. But even if it is the former, I think I represent the average
user of this library.

When I try to use a C+23 std::generator, the usage is intuitive and
straightforward to me. I know how to easily yield a sequence of values, and
on the caller side how to easily check if I can still obtain the next value
from the generator:

```
std::generator<int> seq(int from, int to)
{
    for (int i = from; i <= to; ++i)
        co_yield i;
}

int main()
{
    for(int i : seq(1, 4))
        std::cout << i << std::endl;
}
```
https://godbolt.org/z/PTvz3v4Y6

But when I try what I believe to be an analogous example in Boost.Async, I
get an exception:

```
async::generator<int> seq(int from, int to)
{
    for (int i = from; i <= to; ++i)
        co_yield i;
}

async::main co_main(int argc, char* argv[])
{
    auto s = seq(1, 4);
    while (s) {
        std::cout << co_await s << std::endl;
    }
}
```

And the docs or examples don't help me understand why this use case doesn't
work.
The case with the eager generator that can be injected values is even
weirder. I think it is wrong. Klemens thinks otherwise, but the docs do not
give any convincing example of where and how it could be used.

The lack of examples or description can be just that, but it could also
indicate that the design for generators is missing something.

In this feedback, I am only mentioning generators, because this is the
place where I stuck in my review. I guess that other parts of the library
do not have this problem.

I am pretty sure that this library will be accepted into Boost at some
point. It addresses a real need (although not necessarily the generators),
and the feedback from Ruben and Marcelo are strong testimony to the quality
of the library.

But at this point, I am not comfortable with adding a library whose design
for generators cannot be explained in the docs to the extent that I
consider satisfactory.

Would this library lose in usability if generators were removed?

I know it is not a fair review. I only covered one subject, and my feeling
is that it is not the most relevant one. So please consider it as "just
feedback" rather than a review.

Again, thanks Klemens for writing and sharing this library. I hope that
this message does not come across as negative. I want to think that I am
contributing to the quality of Boost.Async.

Regards,
&rzej;


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