Skip to main content

nuclei/
lib.rs

1//! # Nuclei
2//!
3//! A proactive async runtime: thread-per-core shards that run tasks and
4//! drive their own IO, timers and buffers. Every operation is completed for
5//! the task that asked for it; no task waits for readiness and then makes
6//! the call itself. IO runs on io_uring on Linux where the kernel allows it,
7//! else on epoll; on kqueue on macOS and the BSDs; and on I/O completion
8//! ports on Windows.
9//!
10//! [`spawn`], [`block_on`] and the rest place work on the process default
11//! [`Runtime`], which starts on first use with no configuration; a
12//! [`Builder`] sets every setting for a runtime of one's own.
13//!
14//! # What is where
15//!
16//! - [`runtime`]: runtimes, their builder and handles, `block_on`, tasks
17//!   placed on a worker one names
18//!   ([`RuntimeHandle::spawn_on_worker`], [`RuntimeHandle::on_each_worker`])
19//!   and values kept per worker ([`shard_local!`]).
20//! - [`task`]: spawning, [`JoinSet`](task::JoinSet), abort handles, ids and
21//!   names, task-local values and yielding.
22//! - [`net`]: TCP, UDP and Unix sockets, names, socket options and builders,
23//!   stream halves, `shut` and `abort`, and pipes.
24//! - [`io`]: [`Handle`], async operations on std's own IO objects, and the
25//!   helpers every stream gets: reads and writes as futures, copies,
26//!   buffers, in-memory pipes, the standard streams and readiness; and the
27//!   buffers the owned calls lend the driver ([`io::IoBuf`],
28//!   [`io::AlignedBuf`], [`io::IoVecBuf`]).
29//! - [`fs`]: files, whole-file calls, metadata and directories; IO at an
30//!   offset, direct IO, syncs, the space calls and advisory locks.
31//! - [`time`]: sleeps on a millisecond wheel or to the microsecond,
32//!   timeouts, intervals and a clock tests can pause.
33//! - [`sync`]: locks, semaphores, notifications, once-cells, channels and
34//!   cancellation tokens, for any executor; [`sync::local`], their cheaper
35//!   twins for the tasks of one shard; and [`sync::mesh`], channels between
36//!   every pair of a set of parties.
37//! - [`process`] and [`signal`]: child processes, signals and console events.
38//! - [`stats()`]: a snapshot of what every shard is doing, with poll times
39//!   when recorded and, with the `io-stats` feature, its IO counts and
40//!   latencies.
41//! - [`select!`], [`join!`] and [`try_join!`] wait on several futures in one
42//!   task; `#[nuclei::main]`, `#[nuclei::test]` and `#[nuclei::bench]` run
43//!   an async function in the runtime.
44//!
45//! A call that needs the default runtime or the calling thread's shard
46//! panics if that cannot start (the system refused its poller: no
47//! descriptors or memory left); [`Builder::build`] and [`task::Builder`]
48//! answer the error instead. [`Builder::build`] also checks every setting
49//! first, and answers one out of range as `InvalidInput` naming it.
50//!
51//! The guide, a path from the first program to production with an example
52//! that runs for every idea, is at <https://nuclei.rs/learn/>.
53//!
54//! ```no_run
55//! use nuclei::net::TcpListener;
56//!
57//! #[nuclei::main]
58//! async fn main() -> std::io::Result<()> {
59//!     let listener = TcpListener::bind("127.0.0.1:7000").await?;
60//!     loop {
61//!         let (stream, _) = listener.accept().await?;
62//!         nuclei::spawn(async move {
63//!             let mut buf = [0u8; 1024];
64//!             while let Ok(n @ 1..) = stream.recv(&mut buf).await {
65//!                 if stream.send(&buf[..n]).await.is_err() {
66//!                     break;
67//!                 }
68//!             }
69//!         })
70//!         .detach();
71//!     }
72//! }
73//! ```
74
75// A model-checking build (`--cfg loom`) compiles the loom models and leaves
76// the ordinary tests out, so the helpers only those tests use go unused.
77#![cfg_attr(all(loom, test), allow(dead_code, unused_imports))]
78// No unwrap, expect or panic outside a documented contract, each marked
79// where it is; every unsafe block names what it rests on. Tests and the
80// model-checking build may assert.
81#![cfg_attr(
82    not(test),
83    warn(
84        clippy::unwrap_used,
85        clippy::expect_used,
86        clippy::panic,
87        clippy::unreachable,
88        clippy::todo,
89        clippy::unimplemented,
90        clippy::undocumented_unsafe_blocks
91    )
92)]
93
94mod buf;
95mod compat;
96/// The proactor's configuration: the io_uring settings of every shard and the default backend.
97pub mod config;
98pub mod fs;
99pub mod io;
100mod mem;
101pub mod net;
102mod proactor;
103/// Child processes: spawn one, wait for its exit and talk to it through async pipes.
104pub mod process;
105mod rt;
106/// nuclei's own runtime: shards, tasks, `block_on`, `spawn` and the blocking pool.
107pub mod runtime;
108mod shard_local;
109/// Signals (unix) and console control events (Windows), as streams.
110pub mod signal;
111pub mod stats;
112/// Runtime-independent synchronization primitives: futures and wakers only, usable from any executor.
113pub mod sync;
114#[cfg(any(target_os = "linux", target_os = "android", windows))]
115mod syscore {
116    // The io_uring ring and its probe. Parts of the ring layer (provided
117    // buffer rings, multishot entries, flags) are for the driver's next
118    // steps; their own tests run them now.
119    #[cfg(any(target_os = "linux", target_os = "android"))]
120    #[allow(dead_code)]
121    pub(crate) mod linux;
122    // The kernel32, ws2_32 and ntdll interface of the IOCP driver.
123    #[cfg(windows)]
124    pub(crate) mod windows;
125}
126#[cfg(test)]
127mod alone;
128mod coop;
129mod join_set;
130#[doc(hidden)]
131pub mod macros;
132/// Tasks: spawning, their handles and ids, cancellation from anywhere, and yielding.
133pub mod task;
134mod task_local;
135/// Time: sleeping, timeouts and intervals on the shard's timer wheel.
136pub mod time;
137
138#[cfg(not(any(
139    target_os = "linux",     // epoll, iouring
140    target_os = "android",   // epoll
141    target_os = "illumos",   // epoll
142    target_os = "macos",     // kqueue
143    target_os = "ios",       // kqueue
144    target_os = "freebsd",   // kqueue
145    target_os = "netbsd",    // kqueue
146    target_os = "openbsd",   // kqueue
147    target_os = "dragonfly", // kqueue
148    windows,                 // I/O completion ports
149)))]
150compile_error!("Target OS is not supported");
151
152pub use compat::{
153    GlobalExecutorConfig, init, init_with_config, spawn_more_threads, stop_current_thread,
154    stop_thread,
155};
156pub use io::{Handle, IoObject};
157pub use net::TcpStreamGenerator;
158#[cfg(feature = "attributes")]
159pub use nuclei_macros::{bench, main, test};
160pub use proactor::{IoBackend, Proactor, drive};
161pub use runtime::{
162    Builder, FallibleTask, Runtime, RuntimeHandle, Task, block_on, spawn, spawn_blocking,
163    spawn_local,
164};
165pub use stats::stats;
166pub use time::{sleep, timeout};