Boost logo

Boost :

From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2023-10-02 17:28:28


This was sent to me privately with an express wish it be posted here. I
don't know if the author is subscribed here, so I don't know if replies
will be seen.

This is the first REJECT review.

Niall

--- cut ---

What follows is my review of the proposed Boost.Async library.

>Please state your experience with C++ coroutines and ASIO in your
review, and how many hours you spent on the review.

I have considerable experience with C++ coroutines as I've been
implementing my own coroutine types in the past. I have used Asio before
in a professional setting, although I wouldn't call myself an Asio
expert. My experience involved using Beast/Asio to perform HTTP requests
and sending fan-out notifications to external subscribers. Notably, I
have a lot of experience with asynchronous programming in other
programming languages, mainly Java, Kotlin and JavaScript, but I'm also
very familiar with how it works in Go and Rust. I would say I've spent
around 10 hours evaluating the proposed library.

When I first saw this library being proposed, I was hoping it would
provide a more modern, capable and ergonomic version of asynchronous
programming, like other modern programming languagues and unlike Asio.
The goal of this library is seemingly not to provide such an
out-of-the-box seamless solution, but very specifically to provide
certain coroutine-related utilities and enable composition of different
coroutine types, including user-defined coroutine types (unlike
`asio::awaitable`).

However, I don't think either characterization is entirely correct, and
Boost.Async finds itself in an awkward middle. On one hand, it does not
build on top of Asio to provide a modern and seamless experience which
would completely replace the direct usage of Asio (which is exposed
front-and-center in the interface and code using this library has to
also use Asio a lot to get the job done). On the other hand, it's also
not a completely generic "coroutine library" that only provides
abstractions based on C++ coroutines that could be used by any library
(because it depends on Asio specifically).

In my view, the correct way to characterize this library would be to
regard it as a bundle of coroutine-related utilities on top of Asio.
However, the library is evidently not entirely compatible with any kind
of Asio usage as it's focused on "simple single threaded
asynchronicity." It can certainly be used in conjunction with Asio, but
it definitely brings some additional nuance and complexity (which I
don't think is good, considering that Asio has a lot of complexity of
its own).

When it comes to added functionality, there are definitely some welcome
additions in the form of `async::with` for asynchronous clean-up,
`async::select`, generators. What mainly stands out to me is channels,
which are a very important bread-and-butter feature for many languages.
However, we should keep in mind that Asio has some experimental support
for channels as well, and users of this library would probably be faced
with an unnecessary choice sometime in the future.

One of the most advertised features is the ability to "compose arbitrary
third party awaitables without any additional effort, which lets you tie
together third party libraries with ease and convenience". Firstly, I
don't think this is a goal worth pursuing. As a user, I would definitely
want as few coroutine types as possible in my codebase (ideally one).
`asio::awaitable` already nicely fits the bill. I very well understand
that we need at least a few more for sync/async generators, but that's
where I'd draw the line.

Secondly, this library does not exactly fulfill the promise of "tying
together third-party libraries with ease". Boost.Async does not work
with any coroutine library out of the box. For example, my coroutine
types are incompatible with it and the code doesn't compile. Same goes
for `asio::awaitable`. There is definitely some integration effort
necessary to wrangle these distinct types to work together.

Related to this, I also dislike exposing the whole C++ coroutine
machinery as some kind of a first-class "standard" API for integrating
different coroutine types together. There is evidently no "standard" API
for integrating different coroutine types as arbitrary coroutine types
won't simply work together out of the box. Additionally, having used the
standard coroutine customization points myself, I can't say I like this
API at all and I consider it a necessary evil. It is very subtle,
error-prone and hard to reason about. This is definitely not something
that should be exposed to the users of the library, even experts.
Implementing one coroutine type is hard enough, but making sure that two
coroutine types from different authors work together is even harder.
Considering the complexity of the standard coroutine API, even if my
coroutine types compiled with this library's types, I would not trust
the whole thing to actually work in all the edge cases. I believe
`asio::awaitable` made the right choice here.

I have built the library and played with the examples a bit. I've tried
integrating it with my own coroutine types as I've described above. The
documentation is filled with examples, which is good, but the reference
section is lacking a bit in a sense that it doesn't document the
signature, arguments, the return type, preconditions etc. as you would
expect. I don't see this is a major issue because the documentation can
always be improved, and perhaps we still have to discover how to
effectively document coroutines because of how unique and different they
are.

I vote to REJECT this library on the basis outlined above. This is
definitely an admirable effort and I want to see more progress for C++
in this direction, because the standardization efforts are not promising
and there are still no open-source libraries comparable to the likes of
Rust's Tokio and Kotlin's standard library. Unfortunately, I don't think
this library is a step in the right direction.

All the best,
Janko Dedic


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