pub struct ObservationRing { /* private fields */ }Expand description
SPSC ring used by one producer thread (push) and one consumer (sidecar).
Head is written by the consumer, read by the producer. Tail is written by the producer, read by the consumer.
Implementations§
Source§impl ObservationRing
impl ObservationRing
pub const fn new() -> Self
Sourcepub fn push(&self, obs: Observation) -> bool
pub fn push(&self, obs: Observation) -> bool
Push one observation. Returns true on success, false if the
ring was full (observation dropped).
If obs.producer_thread_id is 0 (the default), the current
thread’s id is stamped in automatically via thread_id. Call
sites that prefer explicit attribution can pre-fill the field;
the auto-stamp keeps the per-primitive push sites mechanical.
Sourcepub fn push_op(&self, op_kind: u16, flags: u16) -> bool
pub fn push_op(&self, op_kind: u16, flags: u16) -> bool
Push an observation described by just its op kind and flags - the
shape essentially every primitive uses. Passing scalars (not a built
Observation) is what keeps the win whole: the struct is constructed
only inside the #[cold] body, so the caller’s hot path is a lone
relaxed load + predicted branch and nothing materializes on it. This
is the preferred per-op observation entry point; reserve
push for the rare site that pre-fills
latency_ticks / instance_id.
Sourcepub fn pop(&self) -> Option<Observation>
pub fn pop(&self) -> Option<Observation>
Consumer-side pop. Single-consumer; caller must serialize.
Sourcepub fn arm(&self)
pub fn arm(&self)
Arm the ring so producers begin pushing observations. Called once
when a consumer (the sidecar) registers the owning instance. This
lazily allocates the ~96 KiB observation buffer (zero-filled, i.e.
all Observation::ZERO) and publishes it before setting armed,
so a raw create() handle that never arms pays nothing - neither
the per-push work nor the buffer allocation. Until armed,
push is a single relaxed load + return. Idempotent;
the buffer is allocated at most once even under racing callers.