pub struct BoundedMpmcQueue<T> { /* private fields */ }Expand description
Lock-free bounded multi-producer/multi-consumer FIFO queue of fixed
capacity.
try_push/try_pop never block; they return Err/None
immediately if the queue is full/empty rather than waiting — callers
needing to wait layer their own backoff/parking on top (this is what
sync::mpsc does with its WaitQueue-based registration).
Implementations§
Source§impl<T> BoundedMpmcQueue<T>
impl<T> BoundedMpmcQueue<T>
Sourcepub fn new(capacity: usize) -> Self
pub fn new(capacity: usize) -> Self
Build an empty queue holding up to capacity elements (rounded up
to at least 1).
Sourcepub fn try_push(&self, value: T) -> Result<(), T>
pub fn try_push(&self, value: T) -> Result<(), T>
Push value, returning it back in Err if the queue is currently
full. Never blocks.
§Errors
Returns value back, unmodified, if the queue is at capacity.
Sourcepub fn try_pop(&self) -> Option<T>
pub fn try_pop(&self) -> Option<T>
Pop the oldest pushed value, or None if the queue is currently
empty. Never blocks.
Sourcepub fn enqueue_snapshot(&self) -> usize
pub fn enqueue_snapshot(&self) -> usize
A snapshot of how many try_push calls have claimed a slot so
far (via winning the enqueue_pos CAS), including any still
in-flight (claimed but not yet published). Paired with
[Self::try_pop_until] so a drain-everything caller can wait out
an in-flight push rather than mistaking it for “queue empty”.
Sourcepub fn drain_until(&self, target: usize, on_pop: impl FnMut(T))
pub fn drain_until(&self, target: usize, on_pop: impl FnMut(T))
Pop everything pushed up to (not including) target (an
Self::enqueue_snapshot taken earlier), spin-waiting out any
push that’s claimed a slot but not yet published rather than
treating a transient empty read as “done”.
Ordinary Self::try_pop alone can’t safely implement “drain
every currently-registered entry”: it returns None the instant
dequeue catches up to a slot that’s been claimed (CAS won) but
not yet published (its value written and sequence released),
which looks identical to a genuinely empty queue. A caller that
stops draining on the first None can permanently miss that
about-to-be-published entry if this was the last drain anyone
will ever perform (see sync::broadcast’s module doc for the
real, reproducible hang this caused via WaitQueue::wake_all).
Looping until target is reached closes that window: any slot
below target was claimed before this call started, so it can
only be transiently unpublished, never permanently absent.