commonware-runtime 2026.10.0

Execute asynchronous tasks with a configurable scheduler.
Documentation
//! Task execution and I/O on Linux io_uring.
//!
//! [`Runner`] polls ordinary tasks and drives their I/O on a pool of
//! [`Config::with_worker_threads`] workers, two by default, each with its own
//! io_uring ring. The first worker runs on the calling thread and also polls
//! the root.
//!
//! A task woken while idle is first queued on the pool worker that woke it,
//! and one woken during its poll is first requeued on its poller. Tasks
//! spawned or woken from outside the pool, and tasks spawned on a worker with
//! other work queued when the pool has more than one worker, go to the global
//! queue that any worker takes from.
//!
//! Each worker has a bounded run queue. A push into a full run queue sends its
//! newest half and the new task to the global queue, or only the new task
//! while another worker is stealing from it. Before parking, a worker with
//! nothing to run can steal half of another worker's queued tasks, rounded
//! down, so a task queued alone behind a long poll waits for it.
//!
//! Dedicated and blocking tasks each receive a supervised thread and io_uring
//! ring. Their ordinary descendants execute on the pool. Task factories run
//! synchronously on the thread that calls [`crate::Spawner::spawn`].
//!
//! Sockets, blobs, and pending I/O and sleep futures can move between workers.
//! Registrations stay on their original worker without keeping it alive. If it
//! closes, pending I/O futures return errors and pending sleeps panic when polled.
//! [`crate::Blob::start_sync`] handles can be awaited on another thread, even after
//! the original runner shuts down.
//!
//! # Ownership
//!
//! Workers own request, timer, and result progress. Each ordinary task has at
//! most one runnable, which a queue or poller owns, and at most one poll of
//! that task runs at a time. A queued task can move through overflow or
//! stealing, and each run queue synchronizes its owner with the workers that
//! steal from it. Each open serializes its syncs and durable writes across
//! workers until their results are recorded. Forwarded results, mailboxes, the
//! global queue, the task set, task handles, supervision, and metrics are also
//! synchronized across threads.
//!
//! # Storage
//!
//! Failures while synchronizing blob contents, including during
//! [SYNC](crate::WriteOptions::SYNC) writes, are retained across opens of the
//! blob, even after every handle is dropped. Creation failures are retained
//! when the header is complete. Removing or recreating the blob clears its
//! retained error. A new runtime instance starts without the error record and
//! still requires normal storage recovery.
//!
//! # Requirements and Progress
//!
//! Linux 6.1 or newer is required for single-issuer rings with deferred task
//! work. Task polls must return so their worker can service I/O and deadlines.
//! I/O and sleeps stay registered on the worker that first polled them, so a
//! poll that blocks one worker also delays their results for tasks that have
//! moved elsewhere.
//!
//! Each worker limits in-flight I/O according to [`RingConfig::size`]. A receive
//! can occupy the last slot while a send needed to satisfy it waits to be
//! submitted. Use deadlines or cancellation to break such dependencies.
//!
//! # Shutdown
//!
//! On shutdown, the runner rejects new tasks and I/O, aborts supervised tasks,
//! and drains registered I/O before returning. The first poll registers an I/O
//! request with its worker. Registered storage writes and syncs run to completion
//! even if their futures are dropped while still queued. For pending reads and
//! network operations, dropping the future or closing the worker requests cancellation.
//!
//! Shutdown waits for all workers to finish runtime cleanup and failure publication,
//! with no timeout. No pool worker closes its mailbox or io_uring ring until
//! every pool task's future has been dropped, though dedicated and blocking
//! tasks may still run and find a pool worker closed. Native thread-local
//! destructors may run after the runner returns.
//!
//! # Examples
//!
//! ```no_run
//! use commonware_runtime::{Runner as _, Spawner, Supervisor, iouring};
//!
//! iouring::Runner::default().start(|context| async move {
//!     let child = context.child("worker").spawn(|_| async { 42 });
//!     assert_eq!(child.await.unwrap(), 42);
//! });
//! ```

mod driver;
mod idle;
mod mailbox;
pub(crate) mod operation;
mod pool;
mod queue;
mod registration;
pub(crate) mod request;
mod runtime;
mod slab;
mod sleep;
pub(crate) mod sockaddr;
mod spinner;
mod task;
mod tasks;
mod timeout;
mod waiter;
mod waker;

pub use runtime::{Config, Context, RingConfig, Runner};
pub use spinner::Config as SpinnerConfig;