Skip to main content

nros_node/executor/
mod.rs

1//! Embedded executor with build-time configured arena.
2//!
3//! Provides `Executor` and `Node` that work with the compile-time
4//! selected RMW backend (zenoh, XRCE-DDS, or C FFI).
5//!
6//! # Example
7//!
8//! ```ignore
9//! use nros_node::executor::*;
10//! use std_msgs::msg::Int32;
11//!
12//! let config = ExecutorConfig::from_env().node_name("my_node");
13//! let mut executor = Executor::open(&config)?;
14//! let mut node = executor.create_node("my_node")?;
15//!
16//! let publisher = node.create_publisher::<Int32>("/chatter")?;
17//! publisher.publish(&Int32 { data: 42 })?;
18//!
19//! loop {
20//!     executor.spin_once(core::time::Duration::from_millis(10));
21//! }
22//! ```
23
24#[cfg(any(has_rmw, test))]
25pub mod action_core;
26#[cfg(any(has_rmw, test))]
27pub(crate) mod activator;
28#[cfg(any(has_rmw, test))]
29mod arena;
30// Phase 8 (autoware-safety-island `docs/design/callback_tracing.rst`) —
31// callback-level dispatch tracing. Same gating shape as `wake_probe`, for the
32// same reason: hot-path hooks that must vanish in production. The module ALSO
33// self-gates (`#![cfg(feature = "trace-callbacks")]`), so the call sites use
34// paired stubs rather than naming it directly.
35#[cfg(all(any(has_rmw, test), feature = "trace-callbacks"))]
36pub mod callback_trace;
37#[cfg(any(has_rmw, test))]
38pub(crate) mod dispatcher;
39#[cfg(any(has_rmw, test))]
40mod handles;
41// issue 0669 / phase-359 W10 — `pub mod handoff` stood here. `Handoff<M, N>`
42// was optional sugar over `Arc<Mutex<heapless::Vec<M, N>>>` for the
43// cross-priority bridge pattern (phase-104.E.3), it was `std`-gated on
44// `std::sync::Mutex` alone, and it had no consumer anywhere in the tree — not
45// one call site in `packages/` or `examples/` since it landed. Deleted rather
46// than ported: the only portable mutex reachable from here costs a `spin`
47// dependency edge on every build of this crate (measured: `spin` is in NO
48// board's graph today), and an API with no consumer has no evidence its shape
49// is the right one. The pattern it wrapped is six lines and is written out in
50// issue 0669.
51#[cfg(any(has_rmw, test))]
52pub mod monitor;
53#[cfg(any(has_rmw, test))]
54mod node;
55#[cfg(any(has_rmw, test))]
56pub mod node_record;
57#[cfg(any(has_rmw, test))]
58mod node_wake;
59// phase-359 W10 — the per-OS-priority worker pool, ported off `std::thread`
60// onto the platform task ABI so it is reachable on every platform.
61//
62// Deliberately the SAME predicate as `node_wake` above, which it imports:
63// spelling a second, hand-matched predicate here is how the two drift, and they
64// did — an `all(feature = …, any(has_rmw, test))` copy resolved true in a build
65// where `node_wake` resolved false. The feature half lives inside the file as
66// an inner `#![cfg]`, so there is one condition per fact and no pair to keep in
67// step.
68#[cfg(any(has_rmw, test))]
69pub(crate) mod os_priority;
70// phase-359 W10 — the allocate/spawn/join helper moved to
71// `nros_platform_api::task`, beside the ABI it wraps, once `nros-cpp` became a
72// third caller. Reached through a `use` below rather than a module here.
73#[cfg(any(has_rmw, test))]
74pub(crate) mod ready_set;
75pub mod sched_context;
76#[cfg(any(has_rmw, test))]
77mod spin;
78#[cfg(any(has_rmw, test))]
79pub(crate) mod spsc_ring;
80#[cfg(any(has_rmw, test))]
81mod storage;
82#[cfg(any(has_rmw, test))]
83pub(crate) mod triple_buffer;
84mod types;
85#[cfg(all(any(has_rmw, test), feature = "wake-latency-probe"))]
86pub mod wake_probe;
87
88#[cfg(any(has_rmw, test))]
89pub mod action;
90
91// MockSession-based tests. Disabled when any rmw-* feature is active because
92// feature unification under `cargo test --workspace` flips `ConcreteSession`
93// to a real backend handle (e.g. UorbSession when rmw-uorb is on transitively
94// via the workspace), breaking the type signatures the tests expect.
95// `feature = "std"` is part of the gate, not decoration. The crate is
96// `#![no_std]`; `tests.rs` uses `std::` in 155 places and calls
97// `from_session`, which is itself `#[cfg(feature = "alloc")]`. Without the
98// feature in the gate, a plain `cargo test -p nros-node` compiles this module
99// into a no_std crate and produces 252 errors, 192 of them "cannot find module
100// or crate `std`" — an incomprehensible wall for anyone running the obvious
101// command, and unrelated to whatever they were changing.
102//
103// These tests genuinely need a host: they spawn threads, sleep, and read the
104// wall clock. Gating them is not hiding coverage, it is declaring what they
105// already required. `cargo test -p nros-node --features std` is unchanged and
106// remains the way to run them.
107#[cfg(all(test, feature = "std", not(feature = "rmw-cffi")))]
108mod tests;
109
110// Flat re-exports so users write `executor::Executor` etc.
111#[cfg(any(has_rmw, test))]
112pub use action::{
113    ActionClientRawHandle, ActionServerHandle, ActionServerRawHandle, RawActionClientSpec,
114    RawActionServerSpec,
115};
116#[cfg(any(has_rmw, test))]
117pub use action_core::{ActionClientCore, ActionServerCore, RawActiveGoal, action_channel_type};
118#[cfg(any(has_rmw, test))]
119pub use arena::TimerClockSource;
120#[cfg(any(has_rmw, test))]
121pub use arena::TimerOverrunPolicy;
122#[cfg(any(has_rmw, test))]
123pub use handles::*;
124#[cfg(any(has_rmw, test))]
125pub use node::{CallbackGroup, NodeHandle};
126#[cfg(any(has_rmw, test))]
127pub use node_record::{NodeBuilder, NodeId, NodeRecord};
128#[cfg(any(has_rmw, test))]
129pub use spin::Executor;
130#[cfg(any(has_rmw, test))]
131pub use spin::SessionHandle;
132#[cfg(all(any(has_rmw, test), feature = "rmw-cffi"))]
133pub use spin::SessionSpec;
134#[cfg(any(has_rmw, test))]
135pub use storage::{
136    ExecutorInlineStorage, ExecutorSizing, executor_storage_layout, executor_storage_u64_len,
137};
138pub use types::*;