Skip to main content

SharedRingSpsc

Struct SharedRingSpsc 

Source
pub struct SharedRingSpsc;
Expand description

Compile-time-enforced single-producer / single-consumer ring, backed by the Lamport 1983 SPSC core in crate::spsc_ring::SpscRingCore.

The SharedRing type exposes MPMC ops (try_push / try_pop) plus SPSC fast-path ops on the same Vyukov-protocol storage. The fast paths still pay for the per-slot sequence number that MPMC needs - four cross-thread atomics per push.

SharedRingSpsc is the dedicated SPSC primitive. It uses a different on-disk layout (Lamport: head + tail counters on separate cache lines, payload-only slots, no per-slot sequence number) and pays only one Acquire load + one Release store of cross-thread atomics per op. On Zen+ R7 2700 with 100k items the Lamport core lands roughly 2x the throughput of the Vyukov SPSC fast path, and ~7x crossbeam_channel.

The constructor returns an owned (Producer, Consumer) pair; neither half implements Clone, both are Send and !Sync. The compiler guarantees at most one thread holds the Producer (single producer), at most one thread holds the Consumer (single consumer). The SPSC contract that backs the no-CAS Lamport pattern is enforced statically.

Internally the pair shares one SpscRingCore via Arc. The two halves call the core’s try_push / try_pop directly; no per-op cost vs the raw core. The only overhead is the Arc clone at construction.

No stuck-slot recovery needed. The Lamport protocol does not have the claimed-but-never-published pathology Vyukov has. The producer writes payload then Release-stores head to publish in a single observable transition; a producer crash between payload write and Release-store leaves head unchanged and the slot uncommitted - the consumer never reads it because head was not advanced.

Implementations§

Source§

impl SharedRingSpsc

Source

pub fn create_anon_pair( capacity: usize, ) -> Result<(Producer, Consumer), RingError>

Anonymous (in-process, no file) SPSC pair. Skips file create + ftruncate + first-page-fault cost.

Source

pub fn create_pair( path: impl AsRef<Path>, capacity: usize, ) -> Result<(Producer, Consumer), RingError>

File-backed SPSC pair. Cross-process visibility available via SharedRingSpsc::open_pair on the same path.

Source

pub fn open_pair( path: impl AsRef<Path>, expected_capacity: usize, ) -> Result<(Producer, Consumer), RingError>

Open an existing file-backed ring and return an SPSC pair. Caller’s responsibility to ensure only one producer + one consumer attach to the underlying file across all processes; the type system enforces this within one process, not across.

Auto Trait Implementations§

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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.