Skip to main content

spawned_rt/tasks/
mod.rs

1//! Runtime wrapper to remove dependencies from code. Using this library will
2//! allow to set a tokio runtime or any other runtime, once implemented just by
3//! changing the enabled feature.
4//! May implement the `deterministic` version based on comonware.xyz's runtime:
5//! <https://github.com/commonwarexyz/monorepo/blob/main/runtime/src/deterministic.rs>
6//!
7//! Currently, only a very limited set of tokio functionality is reexported. We may want to
8//! extend this functionality as needed.
9
10#[cfg_attr(spawned_sim, allow(unused_imports, dead_code))]
11mod tokio;
12
13/// Deterministic single-thread executor with virtual time, selected with
14/// `RUSTFLAGS="--cfg spawned_sim --cfg tokio_unstable"`. See the module docs for its limits.
15#[cfg(spawned_sim)]
16pub mod sim;
17
18// The simulator seeds Tokio's thread-local RNG (`select!` branch order,
19// `watch` waiter shards) per run, which Tokio only allows under its own cfg.
20#[cfg(all(spawned_sim, not(tokio_unstable)))]
21compile_error!(
22    "--cfg spawned_sim needs --cfg tokio_unstable too: \
23     RUSTFLAGS=\"--cfg spawned_sim --cfg tokio_unstable\""
24);
25mod sim_test;
26pub use sim_test::{sim_test, SimTest};
27
28#[cfg(feature = "backend-experiments")]
29mod dispatch_gate;
30
31#[cfg(feature = "backend-experiments")]
32#[doc(hidden)]
33pub mod experimental;
34
35use crate::tracing::init_tracing;
36
37pub mod affinity;
38
39#[cfg(spawned_sim)]
40pub use crate::tasks::sim::{
41    block_in_place, sleep, spawn, spawn_blocking, task_id, timeout, unconstrained, yield_now,
42    Handle, JoinHandle, Runtime, RuntimeFlavor,
43};
44pub use crate::tasks::tokio::mpsc;
45pub use crate::tasks::tokio::oneshot;
46#[cfg(not(spawned_sim))]
47pub use crate::tasks::tokio::sleep;
48#[cfg(not(spawned_sim))]
49pub use crate::tasks::tokio::timeout;
50pub use crate::tasks::tokio::watch;
51pub use crate::tasks::tokio::CancellationToken;
52#[cfg(not(spawned_sim))]
53pub use crate::tasks::tokio::{
54    block_in_place, spawn, spawn_blocking, task_id, unconstrained, yield_now, Handle, JoinHandle,
55    Runtime, RuntimeFlavor,
56};
57pub use crate::tasks::tokio::{BroadcastStream, ReceiverStream};
58use std::future::Future;
59
60/// Build an explicitly sized async runtime. Runtime owners must destroy it
61/// outside an async executor thread.
62#[cfg(not(spawned_sim))]
63pub fn worker_runtime(name: &str, workers: usize) -> std::io::Result<Runtime> {
64    ::tokio::runtime::Builder::new_multi_thread()
65        .worker_threads(workers)
66        .thread_name(name)
67        .enable_all()
68        .build()
69}
70
71/// Build a single-thread control runtime, driven by its owning native thread.
72#[cfg(not(spawned_sim))]
73pub fn control_runtime() -> std::io::Result<Runtime> {
74    ::tokio::runtime::Builder::new_current_thread()
75        .enable_all()
76        .build()
77}
78
79/// Create a tokio runtime, initialize tracing, and block on the given future.
80pub fn run<F: Future>(future: F) -> F::Output {
81    init_tracing();
82
83    let rt = Runtime::new().unwrap();
84    rt.block_on(future)
85}
86
87/// Block on a future using the current tokio runtime handle.
88/// Panics if no tokio runtime is active.
89pub fn block_on<F: Future>(future: F) -> F::Output {
90    Handle::current().block_on(future)
91}
92
93#[cfg(spawned_sim)]
94pub use crate::tasks::sim::ctrl_c;
95#[cfg(not(spawned_sim))]
96pub use crate::tasks::tokio::ctrl_c;
97
98/// Under simulation every runtime is this thread's simulated executor.
99#[cfg(spawned_sim)]
100pub fn worker_runtime(_name: &str, _workers: usize) -> std::io::Result<Runtime> {
101    Runtime::new()
102}
103
104/// Under simulation every runtime is this thread's simulated executor.
105#[cfg(spawned_sim)]
106pub fn control_runtime() -> std::io::Result<Runtime> {
107    Runtime::new()
108}