pub struct Queue<T, N, U = usize, C = MultiCore>where
N: ArrayLength<T>,
U: Uxx,
C: XCore,{ /* private fields */ }
Expand description
A statically allocated single producer single consumer queue with a capacity of N
elements
IMPORTANT: To get better performance use a capacity that is a power of 2 (e.g. U16
, U32
,
etc.).
By default spsc::Queue
will use usize
integers to hold the indices to its head and tail. For
small queues usize
indices may be overkill. However, spsc::Queue
’s index type is generic and
can be changed to u8
or u16
to reduce its footprint. The easiest to construct a
spsc::Queue
with a smaller index type is to use the u8
and u16
constructors.
IMPORTANT: spsc::Queue<_, _, u8>
has a maximum capacity of 255 elements; spsc::Queue<_, _, u16>
has a maximum capacity of 65535 elements.
spsc::Queue
also comes in a single core variant. This variant can be created using the
following constructors: u8_sc
, u16_sc
, usize_sc
and new_sc
. This variant is unsafe
to
create because the programmer must make sure that the queue’s consumer and producer endpoints
(if split) are kept on a single core for their entire lifetime.
Examples
use heapless::spsc::Queue;
use heapless::consts::*;
let mut rb: Queue<u8, U4> = Queue::new();
assert!(rb.enqueue(0).is_ok());
assert!(rb.enqueue(1).is_ok());
assert!(rb.enqueue(2).is_ok());
assert!(rb.enqueue(3).is_ok());
assert!(rb.enqueue(4).is_err()); // full
assert_eq!(rb.dequeue(), Some(0));
Single producer single consumer mode
use heapless::spsc::Queue;
use heapless::consts::*;
// static mut RB: Queue<Event, U4> = Queue::new(); // requires feature `const-fn`
static mut RB: Option<Queue<Event, U4>> = None;
enum Event { A, B }
fn main() {
unsafe { RB = Some(Queue::new()) };
// NOTE(unsafe) beware of aliasing the `consumer` end point
let mut consumer = unsafe { RB.as_mut().unwrap().split().1 };
loop {
// `dequeue` is a lockless operation
match consumer.dequeue() {
Some(Event::A) => { /* .. */ },
Some(Event::B) => { /* .. */ },
None => { /* sleep */},
}
}
}
// this is a different execution context that can preempt `main`
fn interrupt_handler() {
// NOTE(unsafe) beware of aliasing the `producer` end point
let mut producer = unsafe { RB.as_mut().unwrap().split().0 };
// ..
if condition {
producer.enqueue(Event::A).ok().unwrap();
} else {
producer.enqueue(Event::B).ok().unwrap();
}
// ..
}
Implementations§
source§impl<T, N, U, C> Queue<T, N, U, C>where
N: ArrayLength<T>,
U: Uxx,
C: XCore,
impl<T, N, U, C> Queue<T, N, U, C>where
N: ArrayLength<T>,
U: Uxx,
C: XCore,
source§impl<T, N, U, C> Queue<T, N, U, C>where
N: ArrayLength<T>,
U: Uxx,
C: XCore,
impl<T, N, U, C> Queue<T, N, U, C>where
N: ArrayLength<T>,
U: Uxx,
C: XCore,
source§impl<T, N> Queue<T, N, usize, MultiCore>where
N: ArrayLength<T>,
impl<T, N> Queue<T, N, usize, MultiCore>where
N: ArrayLength<T>,
sourcepub fn new() -> Self
pub fn new() -> Self
Alias for spsc::Queue::usize
source§impl<T, N> Queue<T, N, usize, SingleCore>where
N: ArrayLength<T>,
impl<T, N> Queue<T, N, usize, SingleCore>where
N: ArrayLength<T>,
sourcepub unsafe fn new_sc() -> Self
pub unsafe fn new_sc() -> Self
Alias for spsc::Queue::usize_sc
source§impl<T, N> Queue<T, N, usize, SingleCore>where
N: ArrayLength<T>,
impl<T, N> Queue<T, N, usize, SingleCore>where
N: ArrayLength<T>,
source§impl<T, N, C> Queue<T, N, usize, C>where
N: ArrayLength<T>,
C: XCore,
impl<T, N, C> Queue<T, N, usize, C>where
N: ArrayLength<T>,
C: XCore,
sourcepub fn dequeue(&mut self) -> Option<T>
pub fn dequeue(&mut self) -> Option<T>
Returns the item in the front of the queue, or None
if the queue is empty
sourcepub fn enqueue(&mut self, item: T) -> Result<(), T>
pub fn enqueue(&mut self, item: T) -> Result<(), T>
Adds an item
to the end of the queue
Returns back the item
if the queue is full
sourcepub unsafe fn enqueue_unchecked(&mut self, item: T)
pub unsafe fn enqueue_unchecked(&mut self, item: T)
Adds an item
to the end of the queue, without checking if it’s full
Unsafety
If the queue is full this operation will leak a value (T’s destructor won’t run on
the value that got overwritten by item
), and will allow the dequeue
operation
to create a copy of item
, which could result in T
’s destructor running on item
twice.