Asio Project Structure Explained: chriskohlhoff/asio Repository Layout
The Asio project structure organizes a cross-platform C++ networking library into include/ for header-only public APIs, src/ for optional compiled implementations, and Autotools/Visual Studio build scripts supporting both header-only and compiled library modes.
The chriskohlhoff/asio repository provides a comprehensive C++ library for asynchronous I/O operations. Understanding the Asio project structure helps developers choose between header-only integration or compiled library linking. The layout separates public interfaces from platform-specific implementation details while maintaining compatibility across Unix-like systems and Windows.
Directory Layout and Organization
Public Headers in include/
The include/ directory contains the complete public API as header-only files. The master header include/asio.hpp aggregates the entire interface, allowing single-include usage. All user-visible symbols, including io_context, socket types, and timer classes, are declared within this hierarchy. According to the chriskohlhoff/asio source code, this design enables zero-configuration integration for projects that prefer header-only dependencies.
Implementation Sources in src/
The src/ directory contains minimal compiled sources required when building Asio as a static or shared library. The file src/asio.cpp provides the entry point for the library implementation, containing the io_context runtime and platform-specific glue code. This directory also houses platform-specific makefiles such as src/Makefile.msc for Visual Studio and src/Makefile.mgw for MinGW.
Build Configuration Files
Root-level configuration files support multiple build workflows:
configure.ac– Autoconf script generating theconfigurescript for Unix-like buildsMakefile.am– Automake description defining library targets, headers, and testsasio.pc.in– Template for pkg-config file generation at install timeasio.manifest– Metadata for Boost build system integration
Core Architectural Components
io_context and Event Loop
The io_context class (defined in include/asio/io_context.hpp) serves as the central I/O dispatcher. It owns the event loop, schedules asynchronous work, and provides an executor type (io_context::executor_type) for submitting handlers. This component forms the backbone of Asio's asynchronous operation model.
Executors and Execution Context
Asio's modern execution model resides in the execution/ sub-namespace (e.g., execution::blocking, execution::relationship). Executors are lightweight wrappers that submit work to an io_context without exposing the underlying implementation details. The include/asio/executor.hpp header defines these interfaces.
Networking and Timer Types
All networking primitives—including ip::tcp::socket, ip::udp::socket, and acceptors—are implemented as header-only templates depending on io_context for event handling. Timer classes such as steady_timer, deadline_timer, and high_resolution_timer (defined in include/asio/steady_timer.hpp) implement asynchronous waiting operations.
Coroutine Support
Modern C++20 coroutine integration is provided through include/asio/awaitable.hpp and include/asio/co_spawn.hpp. These facilities enable structured concurrency with co_spawn, compose, and awaitable wrapper types, allowing asynchronous code to be written with linear control flow.
Build System Options
Header-Only Mode
When the macro ASIO_HEADER_ONLY is defined, implementation files from src/impl/*.ipp are included directly through the headers. This mode requires no compiled library and eliminates the need for linking against libasio.
Compiled Library Mode
Using the Autotools chain (configure.ac + Makefile.am) or Visual Studio makefiles (src/Makefile.msc), users can build static or shared libraries. This approach minimizes binary size in applications linking multiple translation units.
Continuous Integration
The .github/workflows/ directory contains CI pipelines testing Linux, BSD, and Windows configurations, ensuring cross-platform compatibility for both header-only and compiled modes.
Implementation Examples
Basic Timer with io_context
This example demonstrates the fundamental io_context and steady_timer usage:
#include <asio.hpp>
#include <iostream>
int main()
{
asio::io_context ctx;
// Create a timer that expires after 1 second.
asio::steady_timer timer(ctx, std::chrono::seconds(1));
timer.async_wait([&](const asio::error_code& ec)
{
if (!ec)
std::cout << "Timer expired after 1 second.\n";
});
// Run the event loop until there is no more work.
ctx.run();
}
Key symbols: asio::io_context, asio::steady_timer, async_wait.
Source links: include/asio/io_context.hpp, include/asio/steady_timer.hpp.
Asynchronous TCP Echo Server
Using C++20 coroutines with the modern executor API:
#include <asio.hpp>
#include <iostream>
using asio::ip::tcp;
asio::awaitable<void> session(tcp::socket sock)
{
try {
char data[1024];
for (;;) {
std::size_t n = co_await sock.async_read_some(
asio::buffer(data), asio::use_awaitable);
co_await asio::async_write(sock,
asio::buffer(data, n), asio::use_awaitable);
}
} catch (std::exception& e) {
std::cerr << "Session error: " << e.what() << '\n';
}
}
int main()
{
asio::io_context ctx;
tcp::acceptor acceptor(ctx, tcp::endpoint(tcp::v4(), 12345));
// Spawn a coroutine for each incoming connection.
for (;;) {
tcp::socket sock = co_await acceptor.async_accept(asio::use_awaitable);
asio::co_spawn(ctx, session(std::move(sock)), asio::detached);
}
ctx.run();
}
Key symbols: asio::awaitable, asio::co_spawn, asio::detached, asio::use_awaitable.
Source links: include/asio/awaitable.hpp, include/asio/co_spawn.hpp.
Explicit Executor Usage
Submitting work through an executor explicitly:
#include <asio.hpp>
#include <iostream>
int main()
{
asio::io_context ctx;
auto ex = ctx.get_executor(); // executor bound to ctx
// Submit a plain function.
asio::post(ex, []{
std::cout << "Running in the io_context thread.\n";
});
ctx.run();
}
Key symbols: io_context::get_executor, asio::post.
Source links: include/asio/executor.hpp, include/asio/post.hpp.
Summary
- The Asio project structure in chriskohlhoff/asio separates public headers (
include/) from optional compiled sources (src/), supporting both header-only and library builds. - Autotools (
configure.ac,Makefile.am) and Visual Studio makefiles (src/Makefile.msc) provide flexible build options across platforms. - The
io_contextclass serves as the central event loop, with executors providing lightweight work submission interfaces. - Header-only mode (activated by
ASIO_HEADER_ONLY) includes implementation files directly, while compiled mode links againstlibasiofor smaller binaries. - Modern coroutine support via
co_spawnandawaitableenables structured asynchronous programming with C++20.
Frequently Asked Questions
What is the difference between header-only and compiled library mode in Asio?
Header-only mode, enabled by defining ASIO_HEADER_ONLY, includes implementation files directly from src/impl/*.ipp into translation units at compile time. This eliminates the need to link against a library but may increase binary size. Compiled library mode builds src/asio.cpp into a static or shared library using the Autotools or Visual Studio makefiles, reducing binary size when multiple translation units use Asio.
Which file serves as the main entry point for including the entire Asio library?
The file include/asio.hpp acts as the master header that aggregates the complete public API. According to the chriskohlhoff/asio source code, this single-include header pulls in all networking, timer, and executor components, making it the canonical entry point for users.
How does the Asio project structure support cross-platform builds?
The repository provides configure.ac and Makefile.am for Unix-like systems using Autotools, while src/Makefile.msc and src/Makefile.mgw support Windows builds with Visual Studio and MinGW respectively. Additionally, the .github/workflows/ directory contains CI configurations that validate builds across Linux, BSD, and Windows platforms.
What is the role of the io_context in the Asio project structure?
The io_context class, defined in include/asio/io_context.hpp, serves as the central I/O execution context and event loop. It owns the queue of pending asynchronous operations, dispatches completion handlers, and provides an executor type for submitting work. All asynchronous I/O objects such as sockets and timers require an io_context reference to operate.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →