On 6/25/26 15:11, Vinnie Falco via Boost wrote:
Capy's invariant, stated plainly above, is the coroutine-native expression of the same invariant which Boost.Asio's execution model maintains. Asio's normative requirement, from https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference/asynchro...
I never used Boost.Asio. I looked at it, very briefly, and it looked like an overcomplicated solution to a problem I don't have. To be perfectly clear: I am not writing a server, or even a network client. I am writing single player computer games. The only networking in my code is through the Steam API, which already handles the low-level socket code for me. I don't know what the actual network protocol looks like, I don't care what the actual network protocol looks like, and I expect that the actual network protocol is a trade secret that I am not even allowed to know about. I can't rewrite it in ASIO, or Corosio, or any other networking library. The best thing I can do is wrap an awaitable or IoAwaitable around it. For me, asynchronous i/o is asynchronous *file* i/o, first and foremost. And ASIO *looks* like it's mainly or exclusively about solving network i/o problems. I am not reviewing Capy/Corosio as replacements for ASIO, but as libraries in their own right. Saying that ASIO does it that way is not a rationale, and referencing ASIO is not an explanation.
1. "Capy wants to be the only coroutine library." This follows from not understanding why the boundary exists. The boundary enforces the invariant. It's the same reason Asio dispatches handlers through the associated executor instead of calling them directly. You called resume() manually. You called the handler directly. We don't do that.
You know, I actually liked Capy *better* when I thought that it wanted to be the only coroutine library. Capy wins the coroutine war, we all switch to Capy, we all get the benefits of Capy (such as custom allocators and stop token propagation), all new synchronization structures and other awaitables are written for Capy. Some casualties along the way, but we move on, and we're better for it. I was very careful to mark the severity level of the flaws I perceived. You will note that I never considered "Capy wants to be the only coroutine library" by itself to be a reject-level flaw, or even a conditionally-accept-level flaw, although it did cause me to be harsher on several other points later on. "One coroutine library to rule them all" is only a problem if that one library is behind the others in features. What you are suggesting here is much worse. It's not a three-body problem (between Capy, non-Capy coroutine and non-coroutine), it's an N-body problem where N is unbounded between different incompatible coroutine environments. It means that synchronization and communication between different parts of the same program becomes an essentially unsolvable problem, with tons of unnecessary work and code duplication porting features from one coroutine environment to another. It's the opposite of how C++ is supposed to work. At this point I'm thinking I wasn't harsh enough in my original review. This isn't a flawed library; it's an abomination. -- Rainer Deyke - rainerd@eldwood.com