On Thursday, June 25th, 2026 at 12:58 PM, Ruben Perez via Boost <boost@lists.boost.org> wrote:
asio::awaitable<void> co_main() { auto exec = capy::wrap_asio_executor(co_await asio::this_coro::executor); co_await capy::asio_spawn(exec, my_capy_task()); }
Out of curiosity, how does the out-of-the-box Corosio integration work? I mean, the example uses asio::io_context::run(). How does this get to service Corosio's reactor?
You create a service through the asio executor that contains a capy::execution_context - and vice versa. When the corosio::socket then gets the scheduler from this context, the scheduler *should* create a thread for the reactor. Then, the completion would do a dispatch back onto the asio executor.
The above isn't clearly defined in capy yet, which is another reason it's not merged at this point.
I've tried the following and it fails:
capy::task<void> capy_work(int i) { std::cout << "Capy task started\n"; corosio::tcp_socket sock{co_await capy::this_coro::executor}; auto [ec] = co_await sock.connect(corosio::endpoint("127.0.0.1:8000")); std::cout << "Capy task: " << i << ": " << ec << std::endl; co_return; }
net::awaitable<void> co_main() { std::cout << "co_main\n"; auto exec = capy::wrap_asio_executor(co_await net::this_coro::executor); co_await capy::asio_spawn(exec, capy_work(42)); std::cout << "co_main finished\n"; }
int main() { net::io_context ctx;
net::co_spawn(ctx, co_main(), [](std::exception_ptr exc) { if (exc) std::rethrow_exception(exc); });
ctx.run(); }
With the following output:
co_main Capy task started terminate called after throwing an instance of 'std::logic_error' what(): io_object::create_handle: service not installed Aborted (core dumped)
Looking at the code, corosio I/O objects don't create any services by default, but require these to be already installed in the execution context that you passed. This happens in corosio::io_context constructor.
This means that this also fails:
capy::task<void> co_main() { std::cout << "Capy task started\n"; corosio::tcp_socket sock{co_await capy::this_coro::executor}; auto [ec] = co_await sock.connect(corosio::endpoint("127.0.0.1:8000")); std::cout << "Capy task finished: " << ec << std::endl; co_return; }
int main() { capy::thread_pool ctx{4};
capy::run_async( ctx.get_executor(), []() { std::cout << "Done\n"; }, [](std::exception_ptr exc) { try { std::rethrow_exception(exc); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; } exit(1); })(co_main());
ctx.join(); }
Which makes me think that Corosio can only be used with corosio::io_context, and no other execution contexts.
That is correct, for now. The Boost.Asio compatibility is not part of Capy *yet*. It is un-reviewed and not merged. To support this we simply lazily load services.