BBQueue
BBQueue, short for "BipBuffer Queue", is a (work in progress) Single Producer Single Consumer,
lockless, no_std, thread safe, queue, based on BipBuffers.
It is designed (primarily) to be a First-In, First-Out queue for use with DMA on embedded
systems.
While Circular/Ring Buffers allow you to send data between two threads (or from an interrupt to
main code), you must push the data one piece at a time. With BBQueue, you instead are granted a
block of contiguous memory, which can be filled (or emptied) by a DMA engine.
Using in a single threaded context
use bbqueue::{BBQueue, bbq};
fn main() {
let bbq = bbq!(1024).unwrap();
let mut wgr = bbq.grant(128).unwrap();
wgr.copy_from_slice(&[0xAFu8; 128]);
bbq.commit(wgr.len(), wgr);
let rgr = bbq.read().unwrap();
for i in 0..128 {
assert_eq!(rgr[i], 0xAFu8);
}
bbq.release(rgr.len(), rgr);
}
Using in a multi-threaded environment (or with interrupts, etc.)
use bbqueue::{BBQueue, bbq};
use std::thread::spawn;
fn main() {
let bbq = bbq!(1024).unwrap();
let (mut tx, mut rx) = bbq.split();
let txt = spawn(move || {
for tx_i in 0..128 {
'inner: loop {
match tx.grant(4) {
Ok(mut gr) => {
gr.copy_from_slice(&[tx_i as u8; 4]);
tx.commit(4, gr);
break 'inner;
}
_ => {}
}
}
}
});
let rxt = spawn(move || {
for rx_i in 0..128 {
'inner: loop {
match rx.read() {
Ok(mut gr) => {
if gr.len() < 4 {
rx.release(0, gr);
continue 'inner;
}
assert_eq!(&gr[..4], &[rx_i as u8; 4]);
rx.release(4, gr);
break 'inner;
}
_ => {}
}
}
}
});
txt.join().unwrap();
rxt.join().unwrap();
}