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