Re: [Capy review] Some questions

Ruben Perez via Boost <[email protected]> Thu, 25 Jun 2026 12:56:39 +0200
Newsgroups gmane.comp.lib.boost.devel
Message-ID <CACR-mdLDPs8-C-7CbC29V97YcA9h3SE+4J9u1W=0z53EUkubWg@mail.gmail.com>
>>
>> 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.
_______________________________________________
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/PZ6SMMTUWK4ITB37VX6LT3ND3DRENTCA/