Skip to main content

Ring

Struct Ring 

Source
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>

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn len(&self) -> usize

Number of items currently in the ring (snapshot, not linearizable).

Source

pub fn is_empty(&self) -> bool

True if the ring contains no items (snapshot).

Source

pub fn cap(&self) -> usize

The ring’s actual capacity (the power-of-two new rounded up to).

Trait Implementations§

Source§

impl<T> Drop for Ring<T>

Available on crate feature alloc only.
Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<T> RingStorage for Ring<T>

Available on crate feature alloc only.
Source§

type Item = T

The queued element.
Source§

fn push(&self, item: T) -> Result<(), T>

Push one item; on a full ring the item is handed back via Err.
Source§

fn dequeue(&self) -> Option<T>

Pop the oldest item, or None when empty.
Source§

fn len(&self) -> usize

Snapshot of the number of queued items (not linearizable).
Source§

fn capacity(&self) -> usize

The ring’s capacity (a power of two).
Source§

fn drain_into(&self, out: &mut [T]) -> usize

Pop up to out.len() items FIFO into out, returning the count filled. Default is a dequeue loop; the heap Ring overrides it with its prefetching batch Drainer.
Source§

fn is_empty(&self) -> bool

True when the ring holds nothing (snapshot).
Source§

impl<T: Send> Send for Ring<T>

Available on crate feature alloc only.
Source§

impl<T: Send> Sync for Ring<T>

Available on crate feature alloc only.

Auto Trait Implementations§

§

impl<T> !Freeze for Ring<T>

§

impl<T> !RefUnwindSafe for Ring<T>

§

impl<T> Unpin for Ring<T>
where Box<[Cell<T>]>: Unpin,

§

impl<T> UnsafeUnpin for Ring<T>
where Box<[Cell<T>]>: UnsafeUnpin,

§

impl<T> UnwindSafe for Ring<T>
where Box<[Cell<T>]>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.