pub struct SpscHandle { /* private fields */ }Expand description
Application-side SPSC SHM handle.
Connect with SpscHandle::connect using the same name passed to
SpscFace::create in the engine process.
Set a CancellationToken via [set_cancel] to abort recv/send when
the router’s control face disconnects (the O_RDWR FIFO trick means EOF
detection alone is unreliable).
Implementations§
Source§impl SpscHandle
impl SpscHandle
Sourcepub fn connect(name: &str) -> Result<Self, ShmError>
pub fn connect(name: &str) -> Result<Self, ShmError>
Open the SHM region created by the engine and set up the wakeup mechanism.
Sourcepub fn set_cancel(&mut self, cancel: CancellationToken)
pub fn set_cancel(&mut self, cancel: CancellationToken)
Attach a cancellation token (typically a child of the control face’s
lifecycle token). When cancelled, recv() returns None and send()
returns Err.
Sourcepub async fn send_batch(&self, pkts: &[Bytes]) -> Result<(), ShmError>
pub async fn send_batch(&self, pkts: &[Bytes]) -> Result<(), ShmError>
Send multiple packets to the engine in one tail advance.
Equivalent in outcome to calling send pkts.len()
times in order, but pays the synchronisation cost once rather than
N times:
- One head load (Acquire) per ring-full check instead of N.
- One tail store (Release) per successful push batch instead of N.
- One wakeup pipe write at the end instead of up to N.
- Far fewer
tokio::task::yield_now().awaitpoints when the ring is not contended: a window-fill of 16 Interests becomes one call, one atomic ring transition, and zero scheduler round trips in the common case (instead of 16 awaits and potentially 16 yields).
Like send, this yields cooperatively if the ring fills mid-batch
and waits (up to a 5 s wall-clock deadline) for the engine to drain
enough slots. Partial progress is preserved across yields — the
caller is guaranteed that all pkts eventually reach the ring or
the call returns Err(Closed).
Every packet in pkts must satisfy pkt.len() <= slot_size, or
the call returns Err(PacketTooLarge) before publishing anything.
The size check is performed up-front so a batch is either fully
publishable or rejected atomically for the over-size case.
Sourcepub async fn send(&self, pkt: Bytes) -> Result<(), ShmError>
pub async fn send(&self, pkt: Bytes) -> Result<(), ShmError>
Send a packet to the engine (enqueue in the a2e ring).
Yields cooperatively if the ring is full (backpressure from the engine).
Returns Err(Closed) if the cancellation token fires (engine dead).
Uses a wall-clock deadline so backpressure tolerance is independent
of system scheduling speed (the old yield-counter approach returned
Closed after ~100k yields ≈ 1s on fast machines, but could be much
shorter under heavy Tokio contention — falsely killing the caller).