Re: Capy Review
Andrzej Krzemienski via Boost <[email protected]> Fri, 26 Jun 2026 00:58:29 +0200
| Newsgroups | gmane.comp.lib.boost.devel |
|---|---|
| Message-ID | <CAOenAXih_4TXqfuoMDpJdi5MqyA2VakV_yKWiV0xi98Y-SM1Xg@mail.gmail.com> |
czw., 25 cze 2026 o 15:12 Vinnie Falco via Boost <[email protected]> napisał(a): > On Thu, Jun 25, 2026 at 4:56 AM Rainer Deyke via Boost < > [email protected]> wrote: > > > Pretty sure that's not actually true. > > > Capy provides an execution model for coroutines which offers one simple > invariant: > > A coroutine will always be resumed by the same Executor object which > was used to launch it. > > This should probably be stated in the Capy docs up front. > Along with *why* this guarantee is important and worth trading other things for. Regards, &rzej; > > > > This isn't about Capy vs TooManyCooks. This is Capy vs an entire world > of > > C++ coroutine code that can interact with each other more or less > > seamlessly. > > > 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/asynchronous_operations.html > : > > The completion handler shall be submitted for execution as if by > performing dispatch(ex2, std::move(f)). > > Asio got many things right. Capy takes those things and expresses them with > a coroutine-native API. Or as I like to call it: coroutine-ONLY. > > Corosio similarly borrows the good parts of Asio unabashedly. And it uses > Capy for its execution model. Both libraries, built from Boost.Asio's 24 > years of experience getting things right. There's a reason we asked Jeff > Garland to be the review manager, as he was also the review manager for > Boost.Asio. > > "Capy vs the entire world of C++ coroutine code" is actually "Capy > continues 24 years of proven Boost design, while the rest of the coroutine > world chose the path of least resistance." > > > > And, to be clear, I'm reviewing Capy as a replacement for TMC, not as an > > extension. > > > Every misconception, misgiving, and misapprehension can be derived from a > failure to understand the Capy execution model. > > One could infer that "you don't understand Capy" and I think that's both > the charitable reading and also the correct reading. The documentation > should make the invariant clear. That's on us. The documentation problem is > surfacing in the Boost review, and this is a good thing. That's what Boost > reviews are for. We've been steeping in it so long that we can't see it > from the outside, for someone encountering it cold. > > Now let's review each of your objections through the lens of Capy's > execution guarantees (some quotes are paraphrased): > > 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. > > 2. "Capy is too restrictive to be useful." This conflates "I can't bypass > the executor" with "I can't do anything." The restriction is the feature. > > 3. "Plain awaitables should just work." A plain awaitable can resume on any > thread via raw coroutine_handle::resume(). That breaks the invariant. The > compile error prevents it. You went around it. > > 4. "The two-call syntax is brittle." The two-phase syntax exists to deliver > the frame allocator to operator new before the coroutine body executes. > This is what supporting custom allocators looks like, which TMC doesn't > offer. > > 5. "Not enough synchronization primitives." Your shared_mutex sketch calls > coroutine_handle::resume() directly on the unlock thread. That breaks the > invariant. An async_shared_mutex for Capy would need to dispatch through > the executor. it is a reasonable feature request, but your proposed design > is unsafe in Capy's model for the same reason it's unsafe in Asio's model. > > 6. "Not enough executors." You reviewed only Capy, not Corosio, which > provides the concrete executors. This is the equivalent to reviewing Asio's > executor model without looking at io_context. > > 7. "resume_on is better than run()." resume_on switches the current > coroutine to a different executor without creating a new environment. run() > creates a new io_env with the correct executor, stop token, and allocator. > resume_on is simpler because it doesn't preserve the invariant across the > transition. It trades away environment propagation for simpler syntax. > That's a valid choice for TMC's model. It's not compatible with Capy's > guarantees. > > 8. "The awaitable_wrapper can solve this generically." The wrapper calls > resume() directly, doesn't dispatch through the executor, doesn't know > which thread the foreign operation completes on. It breaks the invariant in > exactly the way IoAwaitable prevents. > > 9. "TMC task runs without an executor." Manually calling > resume()/done()/destroy() on a coroutine_handle. Works in a toy example, > breaks invariants in production code. > > 10. "Capy is a trap." A trap implies hidden costs. The cost is explicit: a > compile error when you try to bypass the executor. That's the opposite of a > trap. > > Thanks > _______________________________________________ > Boost mailing list -- [email protected] > To unsubscribe send an email to [email protected] > https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ > Archived at: > https://lists.boost.org/archives/list/[email protected]/message/QVN4UVUC4CK52RGNW5ORMWXXK7CKEGWY/ > _______________________________________________ Boost mailing list -- [email protected] To unsubscribe send an email to [email protected] https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/[email protected]/message/3OISEA7WWZ6WGITQP4OPAZFNZEZ6UCCP/