pub struct Consumer<T, const CAPACITY: usize, A>where
T: AnyBitPattern,
A: Allocator,{ /* private fields */ }tests_loom only.Expand description
A reading handle of an SPMC broadcast queue.
Each consumer has its own private read cursor: every consumer observes
every value the producer publishes, independently, unless it falls behind
by more than CAPACITY slots.
Consumer is Send but not Sync: at most one thread may call
try_read on a given consumer at a time. To get more
consumers, clone this one. Each clone inherits the parent’s current read
cursor at the time of the clone, so a clone made after the parent has
read N values will not re-observe those N values.
Implementations§
Source§impl<T, const CAPACITY: usize, A> Consumer<T, CAPACITY, A>where
T: AnyBitPattern,
A: Allocator,
impl<T, const CAPACITY: usize, A> Consumer<T, CAPACITY, A>where
T: AnyBitPattern,
A: Allocator,
Sourcepub fn try_read(&mut self) -> ReadResult<T>
pub fn try_read(&mut self) -> ReadResult<T>
Attempts to read the next value.
Wait-free in the common case (value available, or queue empty); lock-free when the producer is actively writing the target slot (the consumer spin-loops until the producer publishes).
§Protocol
Each slot carries an even/odd seq number: even = stable, odd = mid write. The consumer:
- Loads the slot’s seq. If odd, spin until it goes even.
- If the even seq is not the one expected for the current read
cursor, the producer has lapped us; reload the write cursor, jump
to the most recent slot, and return
ReadResult::Lapped. - Otherwise read the slot’s data, then re-load the seq. If the seq
is unchanged the read is committed and a
ReadResult::Valueis returned; if the seq has moved, the read was torn and the loop retries.
§Examples
use low_latency_data_structures::spmc::{self, ReadResult, new};
use low_latency_data_structures::mem::global::GlobalAllocator;
let (producer, mut consumer) = new::<u64, 16, GlobalAllocator>(
spmc::Options::global_mlocked(),
);
assert_eq!(consumer.try_read(), ReadResult::Empty);
producer.publish(7);
assert_eq!(consumer.try_read(), ReadResult::Value(7));