pub struct Ring<T> { /* private fields */ }Expand description
Fixed-capacity bounded ring with lock-free multi-producer, multi-consumer access.
Any number of threads may call Ring::push concurrently; ownership of
each slot is linearised by a CAS on enqueue_pos, so two producers never
touch the same cell. Likewise any number of threads may Ring::dequeue
(or drain via Drainer::drain_into) concurrently; each pop is linearised
by a CAS on dequeue_pos, so two consumers never read the same cell. This
lets a background drainer and an overflowing producer (elastic
producer-assist) drain the same ring at once. Capacity is rounded up to a
power of two (minimum 2) at construction; no resize occurs. Full pushes
return the record via Err without blocking; empty dequeues return None.
Implementations§
Source§impl<T> Ring<T>
impl<T> Ring<T>
Sourcepub fn new(cap: usize) -> Result<Self, CapacityError>
pub fn new(cap: usize) -> Result<Self, CapacityError>
Allocate a ring. cap is rounded up to a power of two, minimum 2 (the
Vyukov protocol is degenerate at capacity 1: pos and pos + 1 alias
the lone cell). Returns CapacityError only for cap == 0.
Sourcepub fn with_capacity(cap: usize) -> Self
pub fn with_capacity(cap: usize) -> Self
Allocate a ring without the Result — cap is clamped to at least 1,
then rounded up to a power of two (minimum 2) exactly as new.
Use when the capacity comes from a validated config or a max(1) clamp, so
new’s cap == 0 arm is unreachable and threading a Result through every
caller is noise.
Sourcepub fn push(&self, record: T) -> Result<(), T>
pub fn push(&self, record: T) -> Result<(), T>
Push one record. Safe to call from any number of threads concurrently.
On success the record is consumed. If the ring is at capacity the record
is handed back via Err(record) (no blocking) so the caller can retry it
under a lossless overflow policy instead of losing it.
Sourcepub fn dequeue(&self) -> Option<T>
pub fn dequeue(&self) -> Option<T>
Pop one record in FIFO order. Safe to call from any number of threads concurrently (multi-consumer).
Returns None if the ring is empty (no blocking). The CAS on
dequeue_pos is the linearisation point: exactly one consumer wins each
position, so two consumers never read the same cell. This is the mirror
of push — see the cell sequence protocol there.
Trait Implementations§
Source§impl<T> RingStorage for Ring<T>
Available on crate feature alloc only.
impl<T> RingStorage for Ring<T>
alloc only.Source§fn push(&self, item: T) -> Result<(), T>
fn push(&self, item: T) -> Result<(), T>
Err.impl<T: Send> Send for Ring<T>
alloc only.impl<T: Send> Sync for Ring<T>
alloc only.