Skip to content

archiyun/CoroPact

Repository files navigation

CoroPact⚡

C++ Platform License Stars

A C++23 asynchronous networking runtime and L7 gateway for Linux, powered by coroutines, epoll, and io_uring.

CoroPact provides a unified and explicit coroutine programming model over independent Reactor and io_uring networking backends:

  • 🔀 A unified asynchronous I/O contract The epoll and io_uring modules own independent event loops while exposing consistent coroutine Stream semantics. Application code depends on Task<T>, AsyncStream, and AsyncListener rather than backend details such as epoll_event, SQE, or CQE.

  • 🧩 Explicit ownership and completion semantics Each Worker owns its thread, event loop, connections, and I/O operations. Operations complete in their owning execution context and coroutine continuations resume in that same context, with explicit rules for buffer lifetimes, cancellation, and asynchronous close.

  • 🚀 Networking runtime and L7 gateway CoroPact provides asynchronous accept, connect, read, write, and close, together with an incremental HTTP/1.1 parser, reverse proxy, upstream connection pool, load balancing, health checking, circuit breaking, and rate limiting.

Although Linux is the current primary platform, the coroutine and I/O contracts can be used to add other backends such as macOS kqueue and Windows IOCP.

Quick Start

#include <array>
#include <cstddef>

#include "coropact/coro/task.h"
#include "coropact/io/stream_algorithms.h"

coropact::coro::Task<void> Echo(coropact::io::AsyncStream auto& stream) {
    std::array<std::byte, 4096> buffer{};

    for (;;) {
        auto read = co_await stream.ReadSome(buffer);
        if (!read.has_value() || *read == 0) {
            break;
        }

        auto written =
            co_await coropact::io::WriteAll(stream, buffer.first(*read));

        if (!written.has_value()) {
            break;
        }
    }

    co_await stream.Close();
}

Build the Reactor backend:

cmake -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DBUILD_TESTS=ON \
  -DBUILD_EXAMPLES=ON

cmake --build build -j"$(nproc)"
ctest --test-dir build --output-on-failure

Build with the io_uring backend enabled:

# Make sure liburing is installed first.

cmake -B build-uring \
  -DCMAKE_BUILD_TYPE=Release \
  -DBUILD_TESTS=ON \
  -DBUILD_EXAMPLES=ON \
  -DCOROPACT_ENABLE_URING=ON

cmake --build build-uring -j"$(nproc)"
ctest --test-dir build-uring --output-on-failure

Architecture

HTTP / Gateway / Custom Session
               |
               v
 Task<T> + Scheduler + AsyncStream
               |
       Submit -> Suspend
       Complete -> Resume
               |
        +------+------+
        |             |
        v             v
Reactor / epoll   luring / io_uring
  coropact::reactor     coropact::luring

The two backends do not share an event loop, and their internal state machines do not need to be identical. They only need to satisfy the same business-observable asynchronous I/O contract.

The io_uring server uses a thread-per-ring topology:

LUringServer
  |
  +-- Worker 0 -> Thread 0 -> LUringLoop 0 -> Ring 0
  +-- Worker 1 -> Thread 1 -> LUringLoop 1 -> Ring 1
  `-- Worker N -> Thread N -> LUringLoop N -> Ring N

Connections, I/O operations, and coroutine continuations remain owned by the Worker and Ring that created them; they do not migrate between Rings during execution.

Performance Benchmarks

CoroPact includes reproducible wrk benchmarks covering:

  • Reactor and io_uring backends
  • raw liburing
  • standalone Asio
  • Monoio
  • Compio
  • the libaio poll compatibility path
  • an Nginx reference configuration

Results depend strongly on the workload and must not be interpreted as a universal ranking of networking frameworks. The complete seven-target fixed-HTTP comparison, including charts, summary data, per-round data, latency anomalies, CPU usage, memory usage, and error counts, is available in the unified network-library benchmark report. Other benchmark scripts, raw results, and optimization records are under docs/benchmark.

Documentation

Most documentation is still being written and may lag behind the current implementation. Treat it as design and development reference material.

  • Networking architecture: runtime layering, backend boundaries, and ownership models.
  • Coroutine state-machine formalization: planned documentation under the design tree.
  • AsyncStream semantics: read, write, close, cancellation, and buffer-lifetime semantics.
  • Gateway architecture: HTTP handling, reverse proxying, and upstream management.
  • Data structures: modern C++ intrusive data structures, intrusive red-black trees, intrusive lists, MPSC queues, and their use in the project.
  • Performance benchmarks: the unified network-library report; additional methods, raw results, and optimization records are in docs/benchmark.
  • Examples: Reactor, io_uring, and Gateway examples.
  • Tests: coroutine, networking, lifecycle, and gateway validation.

Current Status

CoroPact is still an experimental networking runtime and is not yet a production-ready replacement for mature networking frameworks.

Current work includes:

  • Formal state-machine proofs, invariant tests, and concurrency validation for additional backends.
  • Modern liburing networking options and io_uring optimizations.
  • More realistic workload benchmarks and bottleneck analysis.

Contributing

  • Please open an Issue for bugs, questions, or feature requests.
  • Pull Requests are welcome: open a PR.
  • This project is released under the MIT License.

About

A C++23 asynchronous networking runtime and L7 gateway built around explicit coroutine I/O semantics across epoll and io_uring backends.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages