Skip to main content

NodeDispatchRuntime

Trait NodeDispatchRuntime 

Source
pub trait NodeDispatchRuntime {
    // Required method
    fn spin_once(&mut self, timeout_ms: u32) -> Result<(), ()>;

    // Provided methods
    fn apply_lifecycle(&mut self, autostart: u8) -> Result<(), &'static str> { ... }
    fn apply_param_services(&mut self) -> Result<(), &'static str> { ... }
    fn apply_param_store(&mut self) -> Result<(), &'static str> { ... }
    fn executor_handle(&mut self) -> *mut c_void { ... }
    fn apply_declared_params(
        &mut self,
        nodes: &'static [(&'static str, &'static str)],
        params: &'static [(&'static str, &'static str, u8)],
    ) -> Result<(), &'static str> { ... }
    fn observed_callback_counts(&self) -> (usize, usize) { ... }
    fn signal_callback(&mut self, _cb: SignaledCallback<'_>) { ... }
    fn dispatch_strategy(&self) -> DispatchStrategy { ... }
}
Expand description

Node runtime sink the codegen-emitted run_plan(runtime) body talks to (Phase 212.N.7 step-3.1).

Object-safe + no_std. The concrete impl (ExecutorNodeRuntime in nros) owns the live executor; BoardEntry::run installs it on the per-boot RuntimeCtx::runtime slot before invoking the user setup closure.

Phase 214.K.1 — renamed from NodeRuntime to disambiguate from the user-facing nros::NodeRuntime metadata-sink trait in packages/api/nros/src/node.rs:112. The two traits live at different layers (board-side dispatch sink vs user-side metadata declaration sink) and the previous shared name forced explicit nros_platform:: / nros:: qualification at every use site + produced confusing impl NodeRuntime for X ambiguity. The phase-214.K.1 NodeRuntime deprecation alias was removed in phase-313 W1 (issue #0243); use NodeDispatchRuntime directly.

Required Methods§

Source

fn spin_once(&mut self, timeout_ms: u32) -> Result<(), ()>

Drive the underlying executor for at most timeout_ms milliseconds. Ok(()) on a clean spin (including timeout); Err(()) if the executor surfaces a spin error.

Result<_, ()> is deliberate: the board entry-point callers (nros-board-{freertos,nuttx,threadx} spin loops) only {:?}-print the error and B::exit_failure() — a typed enum would carry no extra info across the trait boundary, since the underlying ExecutorError from nros::node_runtime is mapped to () at the impl site (impl NodeDispatchRuntime for ExecutorNodeRuntime). #[allow] keeps the surface narrow.

Provided Methods§

Source

fn apply_lifecycle(&mut self, autostart: u8) -> Result<(), &'static str>

Phase 264 W2 — register the REP-2002 lifecycle services on the underlying executor + drive boot autostart. autostart: 0 = none, 1 = configure, 2 = configure+activate. Default no-op (non-executor runtimes, or nros built without lifecycle-services); the ExecutorNodeRuntime impl in nros does the real work behind that feature. nros::main! calls this (via RuntimeCtx::apply_lifecycle) when system.toml declares [lifecycle], mirroring the bake’s generate.rs::render_lifecycle_fn. issue 0460 — the Err carries a STATIC REASON, not ().

A capability that fails to register is reported by the caller as RuntimeError::NodeRegister("lifecycle"), which names WHICH capability and nothing about WHY. On Zephyr that opaque string was the entire diagnostic for three dead entries: the image printed nothing after “Network ready” and the cause could only be guessed at. &'static str rather than a typed error because this trait lives below nros-node and cannot name NodeError.

Source

fn apply_param_services(&mut self) -> Result<(), &'static str>

Phase 264 W4b – register the 6 ROS 2 parameter services on the underlying executor and create its volatile RAM param store. Launch <param> initials are NOT passed here (issue 1272): each node’s are seeded on that node as it is built, from the params slice nros::main! sets before the node’s register call. After this, ros2 param list/get/set works against the running node; reconfigured values live in RAM until the next boot (RFC-0004 §10; persistence is out of scope, issue 0080). Default no-op (non-executor runtimes, or nros built without param-services); the ExecutorNodeRuntime impl in nros does the real work behind that feature. nros::main! calls this (via RuntimeCtx::apply_param_services) when system.toml declares [param_services], mirroring the bake’s generate.rs::render_param_persistence_fn. issue 0460 — the Err carries a STATIC REASON, not ().

A capability that fails to register is reported by the caller as RuntimeError::NodeRegister("lifecycle"), which names WHICH capability and nothing about WHY. On Zephyr that opaque string was the entire diagnostic for three dead entries: the image printed nothing after “Network ready” and the cause could only be guessed at. &'static str rather than a typed error because this trait lives below nros-node and cannot name NodeError.

Source

fn apply_param_store(&mut self) -> Result<(), &'static str>

phase-461 W6 – build the parameter STORE and register no service: the params capability axis. nros::main! calls this (via RuntimeCtx::apply_param_store) before the per-node register calls when the system declares params and not param_services. Default no-op (non-executor runtimes, or nros built without param-store, which the entry const-asserts against).

Source

fn executor_handle(&mut self) -> *mut c_void

Phase 258 (Track 2, 2a) — raw *mut Executor (as void*) for the owned-spin entry, so a Node pkg’s register(runtime) wrapper can call the uniform __nros_component_<pkg>_install(.., executor, ..) seam (nros::install_node_typed) instead of the retired opaque-fn-ptr register_dispatch_slot_dyn bridge. A pointer crosses the nros-platform → nros layering wall cleanly (the concrete ExecutorNodeRuntime lives in nros; this trait can’t name it).

Default null — sinks without a live executor (e.g. NullNodeRuntime, framework-dispatch-only runtimes) report no handle; the install path treats null as a registration error.

Source

fn apply_declared_params( &mut self, nodes: &'static [(&'static str, &'static str)], params: &'static [(&'static str, &'static str, u8)], ) -> Result<(), &'static str>

phase-446 W6 – hand the executor the parameters each node’s contract DECLARES, so a node whose code declares a parameter its contract does not (or with another type) refuses the boot naming the node, the parameter and the contract.

nodes is (node FQN, contract); params is (node FQN, name, rcl_interfaces type code). Plain tuples because this trait lives below nros-params and cannot name its types. nros::main! calls this before any node registers. Default no-op: a runtime with no parameter store has nothing to check.

Source

fn observed_callback_counts(&self) -> (usize, usize)

Observability counters from hosted/runtime tests.

Returns (all_callbacks, message_callbacks). Implementations that cannot observe callback dispatch keep the default zeros.

Source

fn signal_callback(&mut self, _cb: SignaledCallback<'_>)

Hand a signaled callback to the framework-side dispatcher (Phase 216.A.2). Only meaningful for DispatchStrategy::Deferred (RTIC / Embassy) runtimes — Inline runtimes drive callbacks directly from spin_once and never call this. The default panic surfaces the mis-wire loudly rather than silently dropping the callback signal.

Source

fn dispatch_strategy(&self) -> DispatchStrategy

Declare how this runtime delivers callbacks (Phase 216.A.2). nros check (Phase 216.D.1) cross-validates each Node pkg’s Node::DISPATCH against this value. Defaults to Inline so every existing impl reports the historical behavior unchanged.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§