# [−] [src] Module heapless::spsc

Fixed capacity Single Producer Single Consumer (SPSC) queue

NOTE: This module is not available on targets that do not support atomic loads, e.g. RISC-V cores w/o the A (Atomic) extension

# Examples

- `Queue` can be used as a plain queue

    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));

- `Queue` can be `split` and then be used in Single Producer Single Consumer mode

    use heapless::spsc::Queue;
    use heapless::consts::*;

    static mut Q: Queue<Event, U4> = Queue(heapless::i::Queue::new());

    enum Event { A, B }

    fn main() {
        // NOTE(unsafe) beware of aliasing the `consumer` end point
        let mut consumer = unsafe { Q.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 { Q.split().0 };

        // ..

        if condition {
            producer.enqueue(Event::A).ok().unwrap();
        } else {
            producer.enqueue(Event::B).ok().unwrap();
        }

        // ..
    }

# Benchmarks

Measured on a ARM Cortex-M3 core running at 8 MHz and with zero Flash wait cycles

`-C opt-level` | `3`
--- | ---
`Consumer<u8>::dequeue` | 15
`Queue<u8>::dequeue` | 12
`Producer<u8>::enqueue` | 16
`Queue<u8>::enqueue` | 14

- All execution times are in clock cycles. 1 clock cycle = 125 ns.
- Execution time is dependent of `mem::size_of::<T>()`. Both operations include one `memcpy(T)` in their successful path.
- The optimization level is indicated in the first row.
- The numbers reported correspond to the successful path (i.e. `Some` is returned by `dequeue` and `Ok` is returned by `enqueue`).

## Structs

Consumer | A queue "consumer"; it can dequeue items from the queue
Iter | An iterator over the items of a queue
IterMut | A mutable iterator over the items of a queue
MultiCore | Multi core synchronization - a memory barrier is used for synchronization
Producer | A queue "producer"; it can enqueue items into the queue
Queue | A statically allocated single producer single consumer queue with a capacity of `N` elements
SingleCore | Single core synchronization - no memory barrier synchronization, just a compiler fence