1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//! 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);
//! });
//! ```
pub
pub
pub
pub use ;
pub use Config as SpinnerConfig;