On Thu, Jun 25, 2026 at 3:12 AM Rainer Deyke via Boost < boost@lists.boost.org> 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