Re: Capy Review

Vinnie Falco via Boost <[email protected]> Thu, 25 Jun 2026 03:42:52 -0700
Newsgroups gmane.comp.lib.boost.devel
Message-ID <CA+EzHGek6PUzzrg5nW7BkjKPMTUzdTf9L8gpv29xMy+SOjAwGg@mail.gmail.com>
On Thu, Jun 25, 2026 at 3:12 AM Rainer Deyke via Boost <
[email protected]> wrote:

> The thing about i/o code is that it's never *just* i/o.

...

My choice...was very much deliberate...

Yes, we agree, and this observation supports every Capy decision. That is
why the bridges exist. The question is whether crossing the bridge should
require explicit action or happen silently. Capy chooses explicit. That's
the same choice the type system makes when it won't let you implicitly
convert a float to an int.

You didn't discover a limitation. You encountered a type-safety check,
found the documentation for the escape hatch lacking, and concluded the
escape hatch didn't exist. The frustration is understandable. The
conclusion is not.

The documentation failed you, and that's on us.


>    class awaitable_wrapper {
>      auto await_suspend(auto handle, auto env) {
>        this->env = env;
>        this->handle = handle;
>        return this->base_awaitable.await_suspend(this->my_coro());
>      }
>      auto my_coro() {
>        boost::capy::run(this->env)(this->handle);
>      }
>    };
>

This sketch is instructive, as every problem it has is a problem that the
explicit leaf IoAwaitable solves by requiring the author to make the
decisions the generic wrapper can't make, or else experience a compilation
error.

That said there is not enough information here to perform a thorough
analysis so I will bring back the code from my previous post and ask a
question:

      capy::task<> f()
      {
          co_await my_tmc_task();
    }

How do you propose to make this work? Which tmc executor does my_tmc_task
run on?


> Constantly having to referencing out-of-band documents to explain a library
> does not speak highly of the library's documentation.
>

The documentation failed you, and that's on us.


> >>>> ..innocent-looking functions like the following do not work correctly:
> >
> > This is not quite right. Your `task` coroutine frame is allocated using
> the
> > default allocator. Suboptimal, but it is what you asked for. The launch
> > function works fine. The coroutine executes. The coroutine frame is
> > deallocated properly. The invariants are preserved.
>
> OK.  This is not clear from the documentation.
>

You said "do not work correctly." This is not a documentation problem. You
observed that the program malfunctioned ("does not work"). What was the
actual observed runtime problem?


> TMC's advice to just use a better global allocator makes sense


It doesn't make sense for a library whose intent is standardization. Custom
allocators serve many purposes. Not just benchmarks. Per-tenant budgets,
tracking, specialized heaps, these require control of the allocator that
merely linking with a different heap manager doesn't provide. A
multi-tenant server that caps each tenant's coroutine memory at 64MB cannot
solve that with jemalloc alone.

...capy::run's return value...definitely isn't useless in general.
>

Agreed.

If I might go out on a limb here, based on your code examples and your
description I would hypothesize that you are coming from a place where you
are using TooManyCooks to submit work to its executor, and you saw the
Capy/Corosio review and thought to evaluate Capy in the same context of how
you are using TMC. The documentation failed you (and that's on us), this
left a bad taste in your mouth, everything else is the downstream
consequence of the scope mismatch and early friction. Did I understand this
wrong?

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