pub struct SpscQueue<T> { /* private fields */ }Expand description
A lock-free single-producer single-consumer bounded queue.
This queue is designed for high-performance inter-core communication. It uses atomic operations with Acquire/Release ordering to ensure correct synchronization without locks.
§Safety
This queue is only safe when there is exactly one producer thread and one consumer thread. Multiple producers or consumers will cause data races.
§Example
use laminar_core::tpc::SpscQueue;
let queue: SpscQueue<i32> = SpscQueue::new(1024);
// Producer
assert!(queue.push(42).is_ok());
// Consumer
assert_eq!(queue.pop(), Some(42));Implementations§
Source§impl<T> SpscQueue<T>
impl<T> SpscQueue<T>
Sourcepub fn new(capacity: usize) -> Self
pub fn new(capacity: usize) -> Self
Creates a new SPSC queue with the given capacity.
The capacity will be rounded up to the next power of 2 for efficiency.
§Panics
Panics if capacity is 0 or would overflow when rounded to power of 2.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the queue is empty.
Note: This is a snapshot and may change immediately after returning.
Sourcepub fn is_full(&self) -> bool
pub fn is_full(&self) -> bool
Returns true if the queue is full.
Note: This is a snapshot and may change immediately after returning.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the current number of items in the queue.
Note: This is a snapshot and may change immediately after returning.
Sourcepub fn pop(&self) -> Option<T>
pub fn pop(&self) -> Option<T>
Pop an item from the queue.
Returns Some(item) if successful, or None if the queue is empty.
§Safety
This method must only be called by the single consumer thread.
Sourcepub fn push_batch(&self, items: impl IntoIterator<Item = T>) -> usize
pub fn push_batch(&self, items: impl IntoIterator<Item = T>) -> usize
Push multiple items to the queue.
Returns the number of items successfully pushed. Items are pushed in order, stopping at the first failure.
§Safety
This method must only be called by the single producer thread.
Sourcepub fn pop_batch(&self, max_count: usize) -> Vec<T>
pub fn pop_batch(&self, max_count: usize) -> Vec<T>
Pop multiple items from the queue.
Returns a vector of up to max_count items.
§Safety
This method must only be called by the single consumer thread.
§Note
This method allocates memory. For zero-allocation polling, use
pop_batch_into or pop_each instead.
Sourcepub fn pop_batch_into(&self, buffer: &mut [MaybeUninit<T>]) -> usize
pub fn pop_batch_into(&self, buffer: &mut [MaybeUninit<T>]) -> usize
Pop multiple items into a caller-provided buffer (zero-allocation).
Items are written to buffer starting at index 0. Returns the number
of items actually popped (0 if queue empty or buffer full).
§Safety
This method must only be called by the single consumer thread.
After this method returns n, the first n elements of buffer
are initialized and can be safely read with assume_init_read().
§Example
use laminar_core::tpc::SpscQueue;
use std::mem::MaybeUninit;
let queue: SpscQueue<i32> = SpscQueue::new(16);
queue.push(1).unwrap();
queue.push(2).unwrap();
let mut buffer: [MaybeUninit<i32>; 8] = [MaybeUninit::uninit(); 8];
let count = queue.pop_batch_into(&mut buffer);
assert_eq!(count, 2);
// SAFETY: We just initialized these elements
unsafe {
assert_eq!(buffer[0].assume_init(), 1);
assert_eq!(buffer[1].assume_init(), 2);
}Sourcepub fn pop_each<F>(&self, max_count: usize, f: F) -> usize
pub fn pop_each<F>(&self, max_count: usize, f: F) -> usize
Pop items and call a callback for each one (zero-allocation).
Processing stops when either:
max_countitems have been processed- The queue becomes empty
- The callback returns
false
Returns the number of items processed.
§Safety
This method must only be called by the single consumer thread.
§Example
use laminar_core::tpc::SpscQueue;
let queue: SpscQueue<i32> = SpscQueue::new(16);
queue.push(1).unwrap();
queue.push(2).unwrap();
queue.push(3).unwrap();
let mut sum = 0;
let count = queue.pop_each(10, |item| {
sum += item;
true // Continue processing
});
assert_eq!(count, 3);
assert_eq!(sum, 6);Trait Implementations§
impl<T: Send> Send for SpscQueue<T>
impl<T: Send> Sync for SpscQueue<T>
Auto Trait Implementations§
impl<T> !Freeze for SpscQueue<T>
impl<T> !RefUnwindSafe for SpscQueue<T>
impl<T> Unpin for SpscQueue<T>
impl<T> UnwindSafe for SpscQueue<T>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.