
A modern C++20 I/O scheduling library providing cross-platform asynchronous socket operations, event polling, and streaming interfaces. Built with advanced C++ patterns including tag-dispatched customization points, RAII resource management, and thread-safe design patterns.
Features
- Tag-Dispatched Operations: Type-safe, extensible socket operations using the
tag_invoke
customization point pattern
- Cross-Platform Socket Abstraction: Unified API for Windows (WinSock2) and POSIX socket operations with platform-specific implementations
- Thread-Safe Socket Handles: RAII socket wrappers with atomic storage and mutex-protected operations
- Advanced Message Handling: Thread-safe
socket_message
class for scatter-gather I/O and ancillary data with push()
and emplace()
methods for efficient data appending
- Move-Only Semantics: Clear resource ownership preventing double-free errors and resource leaks
- Comprehensive Socket Operations: Full set of socket operations (bind, listen, connect, accept, sendmsg, recvmsg, etc.) through customization points
- Exception Safety: Robust error handling with automatic resource cleanup and strong exception guarantees
- Modern C++20 Design: Extensive use of concepts, three-way comparison, and contemporary C++ patterns
Quick Start
Prerequisites
- CMake 3.26+
- C++20 compatible compiler
- Boost libraries (header-only Boost.Predef required)
Build and Test
# Clone the repository
git clone https://github.com/kcexn/iosched.git
cd iosched
# Quick build with tests
cmake --preset debug
cmake --build --preset debug
ctest --preset debug
# Alternative presets:
cmake --preset release # Optimized build
cmake --preset benchmark # High-performance build with -O3 -march=native
Detailed Build Instructions
For comprehensive build instructions, dependency installation guides, code coverage setup, and troubleshooting, see DEVELOPER.md.
Documentation
API documentation is available at: https://kcexn.github.io/iosched/
To build documentation locally:
cmake --preset debug -DIOSCHED_ENABLE_DOCS=ON
cmake --build --preset debug --target docs # Generate docs
cmake --build --preset debug --target docs-deploy # Deploy to docs/html/ for GitHub Pages
# View at build/debug/docs/html/index.html or docs/html/index.html
Usage
Basic Socket Operations
#include <netinet/in.h>
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
io::bind(server_socket,
reinterpret_cast<const sockaddr*
>(&addr),
sizeof(addr));
sockaddr_in client_addr{};
socklen_t client_len = sizeof(client_addr);
reinterpret_cast<sockaddr*>(&client_addr),
&client_len);
if (client_fd != -1) {
}
auto [client_socket, client_address] =
io::accept(server_socket);
A thread-safe, move-only RAII wrapper for a native socket handle.
This file contains the main header for the I/O library. It includes all the necessary headers for the...
constexpr detail::cpo< socket::bind_t > bind
A customization point object for binding a socket to an address.
constexpr detail::cpo< socket::accept_t > accept
A customization point object that accepts an incoming connection on a listening socket.
constexpr detail::cpo< socket::listen_t > listen
A customization point object for setting a socket to listen for.
This file defines the socket_handle class, a cross-platform, thread-safe RAII wrapper for native sock...
Client Socket Connection
#include <netinet/in.h>
sockaddr_in server_addr{};
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(8080);
reinterpret_cast<const sockaddr*>(&server_addr),
sizeof(server_addr));
if (result == 0) {
const char *message = "Hello, server!";
struct iovec iov {};
iov.iov_base = const_cast<char *>(message);
iov.iov_len = strlen(message);
struct msghdr msg {};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
}
constexpr detail::cpo< socket::connect_t > connect
A customization point object that connects a socket to an address.
constexpr detail::cpo< socket::sendmsg_t > sendmsg
A customization point object that sends a message on a socket.
Advanced Message I/O
#include <netinet/in.h>
std::string header = "HTTP/1.1 200 OK\r\n";
std::string content = "Hello, World!";
msg.push(header.data(), header.size());
msg.push(content.data(), content.size());
msg.emplace("Connection: close\r\n\r\n");
auto bytes_sent =
io::sendmsg(client_socket, msg.native(), MSG_NOSIGNAL);
if (bytes_sent > 0) {
std::cout << "Sent " << bytes_sent << " bytes\n";
}
recv_msg.reserve_buffer(1024);
auto bytes_received =
io::recvmsg(client_socket, recv_msg.native(), 0);
A thread-safe container for socket messages used in advanced I/O operations.
constexpr detail::cpo< socket::recvmsg_t > recvmsg
A customization point object that receives a message from a socket.
This file defines the socket_message class, a thread-safe container for advanced socket I/O operation...
Socket Address Management
#include <netinet/in.h>
struct sockaddr_in native_addr{};
native_addr.sin_family = AF_INET;
native_addr.sin_addr.s_addr = INADDR_ANY;
native_addr.sin_port = htons(8080);
auto addr = io::socket::make_address(&native_addr);
io::bind(socket, addr.data(), *addr.size());
auto addr_copy = addr;
auto addr_moved = std::move(addr);
This file defines the socket_address class, a platform-independent abstraction for socket addresses.
High-Level Socket Operations
The library provides high-level operations that return managed objects for easier resource management:
auto server_addr = io::socket::make_address<struct sockaddr_in>();
auto *bind_addr = reinterpret_cast<struct sockaddr_in*>(server_addr.data());
bind_addr->sin_family = AF_INET;
bind_addr->sin_addr.s_addr = INADDR_ANY;
bind_addr->sin_port = 80;
try {
auto [client_socket, client_addr] =
io::accept(server_socket);
const auto* addr_info = reinterpret_cast<const sockaddr_in*>(client_addr.data());
std::cout << "Client connected from port: " << ntohs(addr_info->sin_port) << std::endl;
} catch (const std::system_error& e) {
std::cerr << "Accept failed: " << e.what() << std::endl;
}
Architecture
Core Components
- **
io::socket::socket_handle
**: Thread-safe RAII socket wrapper with atomic storage and mutex-protected operations
- **
io::socket::socket_address
**: Platform-independent socket address abstraction with safe data access via data()
and size()
methods
- **
io::socket::socket_message
**: Thread-safe message container supporting scatter-gather I/O, ancillary data, and advanced messaging patterns with efficient push()
and emplace()
methods for data management
- Tag-Dispatched Operations: Extensible socket operations (
io::bind
, io::connect
, io::accept
, io::sendmsg
, io::recvmsg
, etc.) with multiple overloads using the tag_invoke
pattern
- Cross-Platform Abstraction: Platform-specific implementations in
src/socket/platforms/
with unified interfaces
- Error Handling: Structured exception handling with
std::system_error
for high-level operations and return codes for low-level operations
Design Principles
- Tag-Dispatched Customization: Type-safe, extensible operations using
tag_invoke
pattern for compile-time dispatch
- Cross-Platform Compatibility: Unified API with platform-specific implementations using conditional compilation
- RAII Resource Management: Automatic socket cleanup with exception-safe constructors and destructors
- Thread Safety: Atomic socket storage with mutex protection for modification operations
- Move-Only Semantics: Clear resource ownership preventing accidental copies and resource leaks
- Exception Safety: Robust error handling with proper cleanup guaranteed in all failure scenarios
- Modern C++20: Extensive use of three-way comparison, concepts, and contemporary language features
Performance Characteristics
- Zero-Copy Operations: Scatter-gather I/O support minimizes memory copying for high-performance applications
- Lock-Free Reads: Socket handle state queries use atomic operations for minimal overhead
- Efficient Threading: Mixed threading model with mutex protection only where necessary
- Platform Optimization: Native platform APIs used directly with minimal abstraction overhead
- Memory Management: Move-only semantics and RAII prevent unnecessary allocations and copies
Dependencies
- GoogleTest: Auto-fetched via CMake FetchContent for unit testing
- Boost.Predef: Used for cross-platform compiler and OS detection (header-only)
Code Quality
The project uses comprehensive static analysis with clang-tidy:
# Run clang-tidy on the entire codebase
clang-tidy src/**/*.cpp src/**/*.hpp -- -std=c++20 -I src/
Configured rules include bugprone-*
, cert-*
, cppcoreguidelines-*
, modernize-*
, performance-*
, and readability-*
checks (excludes readability-braces-around-statements
, readability-magic-numbers
, and readability-implicit-bool-conversion
for flexibility).
Thread Safety
- Socket Handles: Full thread safety with atomic reads and mutex-protected modifications
- Socket Messages: Thread-safe access to message data and buffers
- Socket Addresses: Thread-safe copy/move operations with proper synchronization
- Tag-Invoke Operations: Concurrent operation dispatch with no shared mutable state
License
This project is licensed under the Apache License, Version 2.0. You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.