Library

Async

Async I/O (files, sockets, timers, processes, fs events, threads wake-up)

MVP
Dependencies

File, FileSystem, Socket, Threading

SaneCppAsync.h is a multi-platform / event-driven asynchronous I/O library.

Note: Check library_async_streams for an higher level construct when streaming data

Note: Check library_await for the C++20 coroutine layer that wraps AsyncEventLoop with co_await syntax while preserving the same request lifetime expectations. It currently covers a small but useful subset of timers, sockets, loop wake-ups, files, file readiness, selected filesystem operations, process exit, signals, background work, child tasks, task groups, cancellation, and timeouts.

Note: Await keeps the same platform caveats as Async: POSIX file readiness is exposed directly, while Windows file readiness for normal file or pipe handles currently fails fast at the Await layer instead of pretending to be portable. File and filesystem operations that need blocking work use caller-provided ThreadPool storage.

Note: Long-lived callback streams such as FileSystemWatcher should stay callback-style or use an explicit caller-owned adapter with bounded event storage. Await intentionally does not model watcher streams as direct AwaitEventLoop methods.

Dependencies

Dependency Graph

Features

This is the list of supported async operations:

Async Operation Description
AsyncSocketConnect SC::AsyncSocketConnect
AsyncSocketAccept SC::AsyncSocketAccept
AsyncSocketSend SC::AsyncSocketSend
AsyncSocketReceive SC::AsyncSocketReceive
AsyncSocketSendTo SC::AsyncSocketSendTo
AsyncSocketReceiveFrom SC::AsyncSocketReceiveFrom
AsyncFileRead SC::AsyncFileRead
AsyncFileWrite SC::AsyncFileWrite
AsyncLoopTimeout SC::AsyncLoopTimeout
AsyncLoopWakeUp SC::AsyncLoopWakeUp
AsyncLoopWork SC::AsyncLoopWork
AsyncProcessExit SC::AsyncProcessExit
AsyncFileReadiness SC::AsyncFileReadiness
AsyncExternalCompletion SC::AsyncExternalCompletion
AsyncSequence SC::AsyncSequence
AsyncFileSystemOperation SC::AsyncFileSystemOperation
AsyncSignal SC::AsyncSignal

Details

Status

MVP This is usable but needs some more testing and a few more features.

Videos

This is the list of videos that have been recorded showing some of the internal thoughts that have been going into this library:

Blog

Some relevant blog posts are:

Description

AsyncEventLoop

Run modes

Event loop can be run in different ways to allow integrated it in multiple ways in applications.

Run mode Description
SC::AsyncEventLoop::run SC::AsyncEventLoop::run
SC::AsyncEventLoop::runOnce SC::AsyncEventLoop::runOnce
SC::AsyncEventLoop::runNoWait SC::AsyncEventLoop::runNoWait

Alternatively user can explicitly use three methods to submit, poll and dispatch events. This is very useful to integrate the event loop into applications with other event loops (for example GUI applications).

Run mode Description
SC::AsyncEventLoop::submitRequests SC::AsyncEventLoop::submitRequests
SC::AsyncEventLoop::blockingPoll SC::AsyncEventLoop::blockingPoll
SC::AsyncEventLoop::dispatchCompletions SC::AsyncEventLoop::dispatchCompletions

AsyncEventLoopMonitor

Functions Description
SC::AsyncEventLoopMonitor::startMonitoring SC::AsyncEventLoopMonitor::startMonitoring
SC::AsyncEventLoopMonitor::stopMonitoringAndDispatchCompletions SC::AsyncEventLoopMonitor::stopMonitoringAndDispatchCompletions

AsyncLoopTimeout

AsyncLoopWakeUp

AsyncLoopWork

AsyncProcessExit

AsyncSignal

AsyncSocketAccept

AsyncSocketConnect

AsyncSocketSend

AsyncSocketReceive

AsyncSocketSendTo

AsyncSocketReceiveFrom

AsyncFileRead

AsyncFileWrite

When using offsets, prefer a single contiguous buffer for portable examples and higher-level helpers. Combining scatter/gather buffers with an explicit offset needs backend-specific validation before being treated as a portable idiom.

AsyncFileReadiness

AsyncExternalCompletion

AsyncSequence

AsyncTaskSequence

AsyncFileSystemOperation

Implementation

Library abstracts async operations by exposing a completion based mechanism. This mechanism currently maps on kqueue on macOS and OVERLAPPED on Windows.

On Linux it tries to create a direct io_uring backend first and falls back to epoll when the kernel or runtime policy does not allow it. No liburing shared library is required.

The api works on file and socket descriptors, that can be obtained from the File and Socket libraries. It also works with serial descriptors from SerialPort, by using AsyncFileRead and AsyncFileWrite on an opened SC::SerialDescriptor. Pipe endpoints accepted/connected through SC::NamedPipeServer and SC::NamedPipeClient, exposed as SC::PipeDescriptor are also supported.

On Windows, AsyncTest includes an optional real COM section named serial com0com read/write. Set SC_TEST_COM0COM_PORT_A and SC_TEST_COM0COM_PORT_B (values can be COMx or \\.\COMx) to enable it. When variables are unset, this section prints a skip message and succeeds.

Memory allocation

The entire library is free of allocations, as it uses a double linked list inside SC::AsyncRequest.
Caller is responsible for keeping AsyncRequest-derived objects memory stable until async callback is called.
SC::ArenaMap from the Containers can be used to preallocate a bounded pool of Async objects.

Roadmap

Usable Features:

  • More AsyncFileSystemOperations
  • Async DNS Resolution

Complete Features:

  • TTY with ANSI Escape Codes
  • Signal handling (multi-watcher, cross-platform)

Statistics

Type Lines Of Code Comments Sum
Headers 885 830 1715
Sources 6443 1454 7897
Sum 7328 2284 9612