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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Async runtime: the async and runner surface of [`lgwks_bot`].
//!
//! This is the crate's async tier. It wraps tokio **core** behind a deliberate
//! surface and sources the engine from the [`lgwks_deps`] storefront
//! (`feature = "tokio"`), so `lgwks_deps` is the only crate that authors a
//! `tokio` edge (`INV-DEP-EDGE-OWNED`) and `lgwks_bot` is the crate a consumer
//! reaches async through.
//!
//! [`lgwks_bot`]: crate
//! [`lgwks_deps`]: lgwks_deps
//! [`runtime`]: crate::rt::runtime
//! [`task`]: crate::rt::task
//! [`time`]: crate::rt::time
//! [`clock`]: crate::rt::clock
//! [`sync`]: crate::rt::sync
//! [`Runtime`]: crate::rt::runtime::Runtime
//! [`Handle`]: crate::rt::runtime::Handle
//! [`block_on`]: crate::rt::runtime::block_on
//!
//! # What this is
//!
//! - [`runtime`] — an explicitly owned runtime ([`Runtime`]),
//! its builder, a cloneable [`Handle`], and a free [`block_on`].
//! - [`task`] — [`JoinSet`](crate::rt::task::JoinSet) and
//! [`join_all_bounded`](crate::rt::task::join_all_bounded): bounded-concurrency fan-out
//! that preserves input order and never exceeds the limit.
//! - [`supervise`](crate::rt::supervise) — `Supervisor`: the way concurrent
//! work, and a subprocess, is started. `Supervisor::default` is the ceiling
//! when the caller has no opinion; `Supervisor::spawn`,
//! `Supervisor::spawn_process` and `Supervisor::run_process` are the
//! starters — the first two report later, the last hands back what the child
//! wrote — and nothing here returns a handle to a running task or process, so
//! nothing can be started and then forgotten.
//! - [`tenancy`](crate::rt::tenancy) — per-tenant capacity: the
//! [`TenancyPolicy`](crate::rt::tenancy::TenancyPolicy) a supervisor admits
//! under, the [`SpawnRefused`](crate::rt::tenancy::SpawnRefused) a
//! tenant-scoped spawn answers with, and the pure
//! [`DeficitRoundRobin`](crate::rt::tenancy::DeficitRoundRobin) core that
//! shares freed permits fairly between tenants with queued work.
//! - [`time`] — `sleep`, `timeout`, `interval`, `Instant` (feature `time`).
//! - [`clock`] — one declared logical clock that governs every deadline this
//! crate evaluates, plus the independent wall-clock watchdog that pausing it
//! cannot disable (feature `time`).
//! - [`sync`] — `mpsc`, `oneshot`, `broadcast`, `watch`, `Mutex`, `RwLock`,
//! `Semaphore`, `Notify`, `Barrier` (feature `sync`).
//! - `net` — async TCP/UDP and `lookup_host` (feature `net`).
//! - `process`, `fs`, `signal` — opt-in drivers.
//! - `select!`, `join!`, `try_join!` — tokio's `macro_rules!` combinators,
//! re-exported at the crate root so a consumer never names `tokio`.
//!
//! # Entering async
//!
//! There is no attribute macro: a re-exported proc-macro expands to `::tokio`
//! paths a consumer without a `tokio` edge cannot resolve. Entry is explicit:
//!
//! ```
//! use lgwks_bot::Runtime;
//!
//! let runtime = Runtime::new().expect("runtime");
//! let answer = runtime.block_on(async { 2 + 2 });
//! assert_eq!(answer, 4);
//! ```
//!
//! # Starting work
//!
//! A future can be awaited, and the runtime can drive one to completion, but no
//! verb here hands a caller a droppable handle to a *running* task or process.
//! Work that outlives the call is placed on a
//! [`Supervisor`](crate::rt::supervise::Supervisor), which owns it, applies the
//! in-flight ceiling, and reports how each task or process ended:
//!
//! ```
//! use lgwks_bot::Runtime;
//! use lgwks_bot::rt::supervise::Supervisor;
//!
//! let runtime = Runtime::new().expect("runtime");
//! runtime.block_on(async {
//! let mut supervisor = Supervisor::default();
//! supervisor.spawn(|_token| async { /* one unit of work */ }).await;
//! // Dropping it stops what it started; `shutdown().await` waits instead.
//! });
//! ```
//!
//! # Limits
//!
//! This is not a scheduler with realtime guarantees. Future completion order
//! across worker threads is not deterministic; only the *result* order of
//! [`join_all_bounded`](crate::rt::task::join_all_bounded) is.
// The clock lives at the crate root (`crate::clock`) because it is `std`-only
// and the observation phase's per-poll deadline needs it in builds that have no
// engine here at all: a `--no-default-features` tick still runs and still has to
// bound a source that stops answering. This is the same module re-exported, not a
// second one — the re-export exists so a caller that already writes `rt::` for
// its deadlines does not have to learn a second path for the clock that governs
// them.
pub use crateclock;
/// Declare task-local storage, re-exported from the engine so a caller of
/// [`crate::task`] never names `tokio` to reach it.
///
/// It is a `macro_rules!` macro, so it cannot be listed inside `sync`: the
/// engine's `task_local!` needs only the `rt` feature this module already
/// requires, and a `pub use` of a macro is what keeps that true.
pub use task_local;
/// This crate's own cancellation primitive. Private, because its only public
/// name is `rt::sync::CancellationToken` (one type, one path), matching how
/// the ECS substrate is reached through `spec` rather than named directly.