Re: Capy Review

Vinnie Falco via Boost <[email protected]> Thu, 25 Jun 2026 01:53:42 -0700
Newsgroups gmane.comp.lib.boost.devel
Message-ID <CA+EzHGdxUx+jQ1_YwWQJUqVhnoU8MJis+iaJ=PC_dL-jcoJnww@mail.gmail.com>
On Wed, Jun 24, 2026 at 7:08 AM Rainer Deyke via Boost <
[email protected]> wrote:

> Capy coroutines cannot co_await awaitables from other coroutine libraries.


What you are asking for is:

    capy::task f()
    {
        co_await foreign_task();
    }

Here's my question. A Capy coroutine runs in a particular execution
context. TooManyCooks coroutines run in a TMC execution context. You want
the Capy coroutine to co_await the TMC coroutine, but this doesn't make
sense. The TMC coroutine has to be launched in a TMC execution context.

The only way this could make sense is if both the Capy and the TMC tasks
were running in the same context. Either the Capy execution context, or the
TMC context. TMC tasks want to run in TMC contexts so this means the Capy
task has to run in the TMC context.

So now I have to ask, why use Capy at all? You aren't using Corosio, you
aren't using byte-oriented streams, then why not just use TMC solely?


> Capy coroutines cannot co_await awaitables at all unless these awaitables
> also model the IoAwaitable concept.


This is technically correct as described above and it misses the point
entirely. If you are going to co_await a task launched on a foreign
execution context then you need a launch function which returns an
IoAwaitable. That would look like this:

    capy::task f()
    {
        co_await tmc_run( tmc_ex, foreign_task() );
    }

tmc_run is a custom launch function, tmc_ex is the foreign executor, and
foreign_task() returns the foreign task.

...Capy wants to be the only coroutine library in your program
>

I want to highlight that not only is this incorrect, it is the opposite.
Capy recognizes that programs may want multiple execution contexts each
with their own task types optimized for their domain, and is specifically
designed to be a good citizen in this environment. It scopes itself clearly
(IoAwaitable), it generates a compile error when the scope would be
exceeded (code trying to run tasks in a way that would break invariants),
and it offers the tools to create the bridges (IoAwaitable, IoRunnable) to
go from Capy's bounded scope elsewhere, and back, in a safe way that
preserves invariants.

The canonical example is the transition from reactor-based socket
operations to GPU operations, and back. As described in the papers:

*Consuming Senders from Coroutine-Native Code*
https://isocpp.org/files/papers/P4092R1.pdf

*Producing Senders from Coroutine-Native Code*
https://isocpp.org/files/papers/P4093R1.pdf

That is the entire point of the sender bridges.

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/QPVBBNHGMJXQFDPJ2GEHKFL22YG7ULAQ/