Boost.Corosio

Boost.Corosio is a coroutine-first I/O library for C++20 that provides asynchronous networking primitives with automatic executor affinity propagation.

What This Library Does

Corosio provides asynchronous I/O operations designed from the ground up for C++20 coroutines. Every operation returns an awaitable that integrates with the affine awaitable protocol, ensuring your coroutines resume on the correct executor without manual dispatch.

  • io_context — Event loop for processing asynchronous operations

  • socket — Asynchronous TCP socket with connect, read, and write

  • acceptor — TCP listener for accepting incoming connections

  • tcp_server — Server framework with worker pools

  • resolver — Asynchronous DNS resolution

  • timer — Asynchronous timer for delays and timeouts

  • signal_set — Asynchronous signal handling

  • wolfssl_stream — TLS encryption using WolfSSL

What This Library Does Not Do

Corosio focuses on coroutine-first I/O primitives. It does not include:

  • General-purpose executor abstractions (use Boost.Capy)

  • The sender/receiver execution model (P2300)

  • HTTP, WebSocket, or other application protocols (use Boost.Http or Boost.Beast2)

  • UDP or other transport protocols (TCP only for now)

Corosio works with Boost.Capy for task management and execution contexts.

Design Philosophy

Coroutines first. Every I/O operation returns an awaitable. There are no callback-based interfaces.

Affinity through protocol. The dispatcher propagates through await_suspend parameters, not through thread-local storage. When an I/O operation completes, it resumes your coroutine through the dispatcher you provided.

Structured bindings. Results use io_result<T> which supports structured bindings: auto [ec, n] = co_await s.read_some(buf). Call .value() to throw on error instead.

Type erasure at I/O boundaries. Socket implementations use type-erased dispatchers internally. The indirection cost is negligible compared to I/O latency.

Target Audience

Corosio is designed for C++ developers who want to build network applications using modern asynchronous programming patterns. This documentation assumes:

  • Familiarity with Boost.Capy — task types, executors, buffer sequences

  • Understanding of C++20 coroutinesco_await, co_return, awaitables

  • Basic TCP/IP networking concepts — clients, servers, ports, connections

If you’re new to these topics, see TCP/IP Networking and Concurrent Programming for background.

Requirements

  • C++20 compiler with coroutine support

  • Boost libraries: Capy, URL, System

Tested Compilers

  • GCC 11+

  • Clang 14+

  • MSVC 19.29+ (Visual Studio 2019 16.10+)

Platform Support

  • Windows (IOCP)

  • Linux (planned: io_uring)

  • macOS (planned: kqueue)

Code Convention

Code examples in this documentation assume these declarations are in effect:
#include <boost/corosio.hpp>
#include <boost/capy/task.hpp>
#include <boost/capy/ex/run_async.hpp>

namespace corosio = boost::corosio;
namespace capy = boost::capy;

Quick Example

#include <boost/corosio.hpp>
#include <boost/capy/task.hpp>
#include <boost/capy/ex/run_async.hpp>
#include <iostream>

namespace corosio = boost::corosio;
namespace capy = boost::capy;

capy::task<void> connect_example(corosio::io_context& ioc)
{
    corosio::socket s(ioc);
    s.open();

    // Connect using structured bindings
    auto [ec] = co_await s.connect(
        corosio::endpoint(boost::urls::ipv4_address::loopback(), 8080));

    if (ec)
    {
        std::cerr << "Connect failed: " << ec.message() << "\n";
        co_return;
    }

    // Read some data
    char buf[1024];
    auto [read_ec, n] = co_await s.read_some(
        capy::mutable_buffer(buf, sizeof(buf)));

    if (!read_ec)
        std::cout << "Received " << n << " bytes\n";
}

int main()
{
    corosio::io_context ioc;
    capy::run_async(ioc.get_executor())(connect_example(ioc));
    ioc.run();
}

Next Steps