Skip to main content

Component

Struct Component 

Source
pub struct Component { /* private fields */ }
Expand description

A node in the runtime component tree.

Components form a hierarchy: Session → Scenario → Phase → Dispenser. Each component carries its own labels, inheritable properties, and its own instrument registry.

Implementations§

Source§

impl Component

Source

pub fn new(labels: Labels, props: HashMap<String, String>) -> Self

Create a new detached component with the given labels and props.

The component starts in ComponentState::Starting. Call attach to wire it into the tree and compute effective labels.

Source

pub fn root(labels: Labels, props: HashMap<String, String>) -> Arc<RwLock<Self>> ⓘ

Create a root component (session level). No parent.

Source

pub fn labels(&self) -> &Labels

This component’s own labels (not including ancestors).

Source

pub fn effective_labels(&self) -> &Labels

Effective labels: all ancestor labels merged with own labels.

Source

pub fn state(&self) -> ComponentState

Current lifecycle state.

Source

pub fn set_state(&mut self, state: ComponentState)

Transition to a new lifecycle state.

Reaching ComponentState::Stopped drops the liveness token, which is what releases this component’s claim on its label set among its siblings. Every stop path goes through here, so there is exactly one place that can forget to do it.

Source

pub fn register_instrument( &mut self, family: impl Into<String>, instrument: InstrumentRef, ) -> Result<(), String>

Register an instrument under family on this component.

Returns Err when family is already registered on this component — duplicate-family declarations on the same dimensional cell surface as a workload error here, before any cycle runs (SRD-40b §7.2). The component’s effective_labels define the dimensional cell; the same family on a different component is a different cell and produces no collision.

The collision check is a linear scan over the registry Vec — see the storage-shape note on Self::instruments.

Source

pub fn register_instrument_with_unit( &mut self, family: impl Into<String>, unit: Option<String>, instrument: InstrumentRef, ) -> Result<(), String>

Variant of Self::register_instrument that records an OpenMetrics unit (ms, bytes, …).

At capture time the unit drives the _<unit> suffix on metric_family.name and populates the unit column per SRD-40a §4.3 / SRD-40b §1. None is identical to the no-unit register_instrument path.

Source

pub fn instruments(&self) -> &[RegisteredInstrument]

Read-only view of every registered instrument on this component, in insertion order. Walked by the cadence reporter on every tick.

Source

pub fn find_instrument(&self, family: &str) -> Option<&InstrumentRef>

Linear scan by family name — diagnostic / rare-path only.

Hot-path callers must use the typed Arc<...> they captured at registration time. The Vec storage and linear scan are deliberate: registration is once-at-init, per-cycle access is pre-bound, and a HashMap probe would add API + Hash bound for ~40 ns saved once per workload load.

If you find yourself reaching for this on a per-cycle code path, that’s a design bug in the caller — pre-bind the Arc<...> you got from [register_instrument] instead.

Source

pub fn set_dynamic_capture(&mut self, hook: Arc<dyn DynamicCapture>)

Install a DynamicCapture hook for instruments whose existence isn’t known at init time. Replaces any prior installation. See the trait doc.

Source

pub fn capture_delta(&self, interval: Duration) -> MetricSet

Capture a delta snapshot covering interval.

Drains histogram/timer reservoirs; counters report their absolute running total (no draining). Called by the scheduler on every tick — the result feeds the cadence reporter’s smallest-cadence accumulator. The caller-supplied interval is recorded on the snapshot verbatim; the scheduler passes its nominal base_interval so the “canonical scheduler cadence” property is preserved in storage even when wall-clock between ticks drifts (drift surfaces via the scheduler’s tick warning, not by mutating the snapshot’s interval).

Also stamps last_capture_instant so the phase-end flush path (capture_delta_auto) can compute true elapsed time since the previous capture.

Source

pub fn capture_delta_auto(&self, fallback: Duration) -> MetricSet

Phase-end variant of [capture_delta] that stamps the snapshot with real elapsed wall time since the previous capture, rather than a caller-supplied nominal interval.

Eliminates the 1-second quantization that surfaced as the spurious cycles_total_rate = 10000/8 = 1250.0 cluster for short phases — a 7.84-second phase will now carry a 7843-ms interval (subject to storage precision) instead of being padded to the scheduler’s nominal 1s final-flush stamp.

fallback covers the edge case where no prior capture has happened (a phase that ended before the first scheduler tick). The phase-end caller passes the scheduler’s nominal base_interval here — a phase shorter than one tick still gets stamped with that nominal duration rather than zero.

Source

pub fn capture_current(&self) -> MetricSet

Capture a non-mutating snapshot of current state.

  • Counters: absolute totals (atomic load).
  • Gauges: current value.
  • Histograms / Timers: non-draining clone (peek_snapshot).

Never touches internal accumulators — callers may invoke this arbitrarily often without perturbing the scheduler’s per-tick cascade.

Source

pub fn get_prop(&self, name: &str) -> Option<String>

Get a property by name, walking up the tree.

Checks this component’s props first, then each ancestor in order until found. Returns None if no ancestor has the key.

Source

pub fn set_prop(&mut self, name: &str, value: &str)

Set a property on this component.

Source

pub fn child_count(&self) -> usize

Number of child components.

Source

pub fn children(&self) -> impl Iterator<Item = &Arc<RwLock<Component>>>

Iterator over this component’s direct children.

Source

pub fn controls(&self) -> &ControlRegistry

Borrow this component’s dynamic-controls registry. Every component carries one; empty until something declares a control on it. See SRD 23.

Source

pub fn cells(&self) -> Arc<CellMap> ⓘ

This component’s data-materialised cells. See crate::cells::CellMap: one series per dimension instance is one CHILD per instance, not a label bag on an instrument.

Returns the Arc by value ON PURPOSE — see the field docs. Resolving takes this component’s write lock, so the caller must be able to drop its read guard first:

ⓘ
let cells = parent.read().unwrap().cells();  // guard dropped here
let cell  = cells.resolve(&parent, &coord);  // takes the write lock
Source

pub fn find_control_up<T>(&self, name: &str) -> Option<Control<T>>
where T: Clone + Send + Sync + 'static,

Resolve a typed control by name, walking up the parent chain. This component’s registry is checked first; then each ancestor in order. An ancestor declaration is only honored if its [BranchScope] is Subtree — [BranchScope::Local] declarations do not propagate to descendants. Returns None if no in-scope declaration matches the <name, T> pair.

Mirrors Self::get_prop but for typed controls (SRD 23 §“Branch-scoped and final controls”).

Source

pub fn find_control_erased_up( &self, name: &str, ) -> Option<Arc<dyn ErasedControl>>

Erased variant of Self::find_control_up — returns just the enumeration handle, useful for diagnostics (dryrun=controls, TUI surfaces) that don’t need the typed value.

Source

pub fn control_snapshot( start: &Arc<RwLock<Component>>, ) -> HashMap<String, Arc<dyn ErasedControl>>

SRD-89 — flatten the up-walk control resolution starting at start into a name → erased-handle map, computed without nested locks.

This has the same visibility as calling Self::find_control_erased_up for every name — the start component’s own controls plus any BranchScope::Subtree control on an ancestor, nearest-wins — but it acquires and releases one tier’s lock at a time (never holding a child’s guard while reading a parent), so it is immune to the writer-preferring RwLock starvation that a nested up-walk hits under concurrent in-process execution (a hot-path per-cycle find_control_erased_up deadlocks against the cadence path’s instrument-registration writes; this is built once per phase and read lock-free thereafter — see SRD-89 §3c-i).

Source

pub fn running_descendant_count(&self) -> usize

Count of Running-state descendants (this component’s children, grandchildren, …). Used by callers that want a structural “how many phases are in flight?” query against the live component tree — e.g. the TUI’s Focus-LOD placeholder decision (SRD 62 §“Scenario done?”).

The component itself is NOT counted — the query is meant to traverse from an activity root into its phases.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.