pub struct BlockingSpscRing { /* private fields */ }Expand description
SPSC ring with cross-process blocking recv / send.
Implementations§
Source§impl BlockingSpscRing
impl BlockingSpscRing
Sourcepub fn create_anon(capacity: usize) -> Result<Self, BlockingError>
pub fn create_anon(capacity: usize) -> Result<Self, BlockingError>
Anon (in-process) ring + both wakers anon.
Sourcepub fn create(
base_path: impl AsRef<Path>,
capacity: usize,
) -> Result<Self, BlockingError>
pub fn create( base_path: impl AsRef<Path>, capacity: usize, ) -> Result<Self, BlockingError>
File-backed ring + both wakers in adjacent files.
Suffixes: .ring.bin, .cw.bin, .pw.bin.
Sourcepub fn open(
base_path: impl AsRef<Path>,
expected_capacity: usize,
) -> Result<Self, BlockingError>
pub fn open( base_path: impl AsRef<Path>, expected_capacity: usize, ) -> Result<Self, BlockingError>
Open an existing file-backed ring + wakers.
Sourcepub fn inner(&self) -> &Arc<SpscRingCore> ⓘ
pub fn inner(&self) -> &Arc<SpscRingCore> ⓘ
Direct access to the underlying SPSC ring for callers that want the non-blocking surface.
Sourcepub fn consumer_waker(&self) -> &Arc<CrossProcessWaker> ⓘ
pub fn consumer_waker(&self) -> &Arc<CrossProcessWaker> ⓘ
Wakers (in case the caller wants to peek wake counts for instrumentation).
pub fn producer_waker(&self) -> &Arc<CrossProcessWaker> ⓘ
Sourcepub fn try_push(&self, payload: &[u8]) -> Result<(), RingError>
pub fn try_push(&self, payload: &[u8]) -> Result<(), RingError>
Hot-path non-blocking push. On success, fires a single-slot wake at the consumer_waker so any blocked recv runs.
Sourcepub fn try_pop(&self, out: &mut [u8]) -> Result<usize, RingError>
pub fn try_pop(&self, out: &mut [u8]) -> Result<usize, RingError>
Hot-path non-blocking pop. On success, fires a wake at the producer_waker so any blocked send runs.
Sourcepub fn send_blocking(
&self,
payload: &[u8],
timeout: Option<Duration>,
) -> Result<(), BlockingError>
pub fn send_blocking( &self, payload: &[u8], timeout: Option<Duration>, ) -> Result<(), BlockingError>
Block until either a push succeeds or timeout elapses.
On Err(Timeout) the caller’s payload is NOT in the ring.
Sourcepub fn set_phase_locking(&self, enabled: bool)
pub fn set_phase_locking(&self, enabled: bool)
Enable or disable predictive (phase-locked) waiting on this
ring’s consumer at runtime. Atomic; takes effect on the next
recv_blocking call. Default is DISABLED - the bare doorbell
wins cross-process (the primary use case). Enable it only for
an IN-PROCESS consumer whose producer contends for cores
(where the doorbell wake inflates and predictive spinning
shaves it); see the phase_lock_probe (in-process win) and
phase_lock_xproc (cross-process loss) benches.
Sourcepub fn phase_locking_enabled(&self) -> bool
pub fn phase_locking_enabled(&self) -> bool
Whether automatic phase-locked waiting is currently enabled.
Sourcepub fn phase_in_wait_mode(&self) -> bool
pub fn phase_in_wait_mode(&self) -> bool
Whether the consumer is currently in wait mode (the estimator is live). Observability; false in steady high-throughput.
Sourcepub fn phase_engaged(&self) -> bool
pub fn phase_engaged(&self) -> bool
Whether the arrival predictor is currently engaged (regular
cadence, enough samples). Observability accessor - locks the
estimator, so not for the hot path. Note: the estimator resets
when the consumer leaves wait mode, so this can read false at
the end of a run even after heavy engagement - use
phase_predictive_catches
for a sticky “did it fire” signal.
Sourcepub fn phase_predictive_catches(&self) -> u64
pub fn phase_predictive_catches(&self) -> u64
Sticky count of items caught by the predictive guard-band spin since construction - the syscall-free path. Nonzero proves the adaptive mechanism engaged and fired.
Sourcepub fn recv_blocking(
&self,
out: &mut [u8],
timeout: Option<Duration>,
) -> Result<usize, BlockingError>
pub fn recv_blocking( &self, out: &mut [u8], timeout: Option<Duration>, ) -> Result<usize, BlockingError>
Block until either a pop succeeds or timeout elapses.
On Err(Timeout) out is unchanged.
By default this is the bare doorbell park (the consumer parks
on the cross-process waker until the producer’s push wakes it).
Predictive (phase-locked) waiting is OPT-IN via
Self::set_phase_locking - it wins only for an in-process consumer
whose producer contends for cores, and LOSES cross-process
where the doorbell is already fast. When enabled and the
consumer waits on a regular-cadence producer, it predicts the
arrival and spins a short guard band instead of paying the
wake propagation; the wait-mode gate keeps the fast path at one
relaxed atomic load. Correctness (exactly-once, FIFO) is
identical in every mode.
Sourcepub fn recv_phase_locked(
&self,
out: &mut [u8],
estimator: &mut PhaseEstimator,
guard_band: Duration,
timeout: Option<Duration>,
stats: &mut PhaseRecvStats,
) -> Result<usize, BlockingError>
pub fn recv_phase_locked( &self, out: &mut [u8], estimator: &mut PhaseEstimator, guard_band: Duration, timeout: Option<Duration>, stats: &mut PhaseRecvStats, ) -> Result<usize, BlockingError>
Predictive blocking pop. When the estimator is engaged (the
producer’s cadence is regular enough), this parks only until
guard_band before the predicted next arrival, then spins
through the guard band catching the item by polling - skipping
the park/wake syscall round-trip the doorbell pays. When the
estimator is disengaged (irregular cadence) or the prediction
is missed, it falls back to the same doorbell park as
Self::recv_blocking, so correctness is identical in every mode.
The estimator is consumer-local state the caller owns; pass the
same &mut instance across calls so it accumulates cadence.
stats accumulates how each item was caught.