| Docs | GitHub Actions | Drone | Code Coverage | |
|---|---|---|---|---|
master |
||||
develop |
This library provides facilities which use C++20 coroutines to perform I/O. It is not a networking library, yet it is the perfect foundation upon which networking libraries, or any libraries that perform I/O, may be built. It introduces concepts for representing buffers of data, and moving those buffers of data through processing pipelines driven entirely by C++20 coroutines. The design of the library is based on one simple observation from Peter Dimov:
An API designed from the ground up to use C++20 coroutines can achieve performance and ergonomics which cannot otherwise be obtained.
- CMake 3.20 or later
- C++20 compiler (GCC 12+, Clang 17+, MSVC 14.34+)
- Ninja (recommended) or other CMake generator
git clone https://github.com/cppalliance/capy.git
cd capy
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build buildUse FetchContent or add_subdirectory to add capy to your project,
then link against Boost::capy:
include(FetchContent)
FetchContent_Declare(capy
GIT_REPOSITORY https://github.com/cppalliance/capy.git
GIT_TAG develop
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(capy)
target_link_libraries(my_app Boost::capy)Capy is opinionated on the things that matter for I/O:
- An executor model for coroutine affinity and completion dispatch
- Stop token integration: uniform cancellation, always available
- Allocator control over frame allocation with zero-overhead recycling
- Forward propagation of the full context through every
co_await - A
tasktype that enforces the ContextAwaitable protocol at compile time - Composition primitives for launching and coordinating coroutines
- A strand for safe concurrency without mutexes
- Buffer sequences:
std::rangesfor untyped bytes - Type erasure by default: no combinatorial explosion of templates
When an I/O operation completes, the operating system wakes up some thread, such as a completion port thread, an epoll reactor, or an io_uring worker. Without affinity tracking, your coroutine resumes on that arbitrary thread, forcing you to add synchronization everywhere or risk data races. This is the fundamental problem that coroutine-based networking must solve.
Capy's answer is the ContextAwaitable protocol. When you launch a coroutine with a designated executor, every child coroutine inherits that executor affinity automatically. Execution context flows forward through co_await chains, not backward through P3826 queries, to ensure every coroutine in the chain runs in the same context. When I/O completes on some OS thread, the ContextAwaitable protocol ensures your coroutine resumes on its designated executor. The data flow is explicit and testable. There are no thread-local globals, no implicit context, no surprises. Capy's task type uses the compiler to enforce invariants.
Cancellation follows the same forward-propagation model. Stop tokens flow forward from the launch of a coroutine chain alongside the execution context, to arrive at the platform API boundary, providing a uniform cancellation interface across all operations.
Frame allocation is where coroutine overhead traditionally hurts performance. Capy addresses this with thread-local recycling pools that achieve zero steady-state allocations after warmup. The coroutine launch site controls allocation policy, enabling per-deployment customization: bounded pools for real-time systems, per-tenant budgets for multi-tenant servers, or tracking allocators for debugging.
Buffer handling is essential for networking, and Asio's twenty five years of experience showed us how. Capy provides buffer sequence algorithms: think std::ranges but for buffers. These are the vocabulary types and operations that networking code needs: slicing, copying, and iterating over discontiguous memory. One million scatter/gather buffers, if you will. The design is driven by real-world usage, not theoretical completeness.
Capy is the foundation for Corosio, a complete networking library built on the facilities that Capy offers. We intend to propose this library as the successor to the immensely popular Boost.Asio library.
- Documentation: https://master.corosio.cpp.al/corosio/index.html
Capy is also the foundation for Http. The Http library uses Capy, yet does not use Corosio. That is because Http is "Sans/IO." It provides the algorithms and data structures which implement the HTTP protocol at a high level, while remaining agnostic to the particular network implementation. This is possible thanks to the powerful stream abstractions which Capy offers.
- Documentation: https://master.http.cpp.al/http/index.html
Capy is also used by Beast2, which uses the Capy, Corosio, and Http libraries to implement high-level HTTP servers written in a C++ version of Express JS routers. This is the successor to Boost.Beast (note: Boost.Beast will continue to be maintained as its own separate library, Beast2 is new).
The Beast2 family of libraries includes:
- Capy — The foundation of I/O.
- Corosio — Coroutine-only portable networking. This is the successor to Boost.Asio.
- Http — Sans-I/O HTTP/1.1. This is a high-level library: servers, clients, Express JS middleware.
- Websocket — Sans-I/O Websocket. This is also a high-level library.
- Beast2 — High-level HTTP and WebSocket servers. Express.js-style routing, multithreaded, idiomatic C++.
- Burl — High-level HTTP client. The features of curl, the ergonomics of coroutines, and the design sensibility of Python Requests.
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)