SkillAgentSearch skills...

Bbqueue

A SPSC, lockless, no_std, thread safe, queue, based on BipBuffers

Install / Use

/learn @jamesmunns/Bbqueue
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

BBQueue

Documentation

BBQueue

BBQueue, short for "BipBuffer Queue", is a Single Producer Single Consumer, lockless, no_std, thread safe, queue, based on BipBuffers. For more info on the design of the lock-free algorithm used by bbqueue, see this blog post.

BBQueue 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.

Local usage

// The "Churrasco" flavor has inline storage, hardware atomic
// support, no async support, and is not reference counted.
use bbqueue::nicknames::Churrasco;

// Create a buffer with six elements
let bb: Churrasco<6> = Churrasco::new();
let prod = bb.stream_producer();
let cons = bb.stream_consumer();

// Request space for one byte
let mut wgr = prod.grant_exact(1).unwrap();

// Set the data
wgr[0] = 123;

assert_eq!(wgr.len(), 1);

// Make the data ready for consuming
wgr.commit(1);

// Read all available bytes
let rgr = cons.read().unwrap();

assert_eq!(rgr[0], 123);

// Release the space for later writes
rgr.release(1);

Static usage

use bbqueue::nicknames::Churrasco;
use std::{thread::{sleep, spawn}, time::Duration};

// Create a buffer with six elements
static BB: Churrasco<6> = Churrasco::new();

fn receiver() {
    let cons = BB.stream_consumer();
    loop {
        if let Ok(rgr) = cons.read() {
            assert_eq!(rgr.len(), 1);
            assert_eq!(rgr[0], 123);
            rgr.release(1);
            break;
        }
        // don't do this in real code, use Notify!
        sleep(Duration::from_millis(10));
    }
}

fn main() {
    let prod = BB.stream_producer();

    // spawn the consumer
    let hdl = spawn(receiver);

    // Request space for one byte
    let mut wgr = prod.grant_exact(1).unwrap();

    // Set the data
    wgr[0] = 123;

    assert_eq!(wgr.len(), 1);

    // Make the data ready for consuming
    wgr.commit(1);

    // make sure the receiver terminated
    hdl.join().unwrap();
}

Nicknames

bbqueue uses generics to customize the data structure in four main ways:

  • Whether the byte storage is inline (and const-generic), or heap allocated
  • Whether the queue is polling-only, or supports async/await sending/receiving
  • Whether the queue uses a lock-free algorithm with CAS atomics, or uses a critical section (for targets that don't have CAS atomics)
  • Whether the queue is reference counted, allowing Producer and Consumer halves to be passed around without lifetimes.

See the nicknames module for all sixteen variants.

Stability

bbqueue v0.6 is a breaking change from the older "classic" v0.5 interfaces. The intent is to have a few minor breaking changes in early 2026, and to get to v1.0 as quickly as possible.

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)

  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

View on GitHub
GitHub Stars494
CategoryDevelopment
Updated15d ago
Forks60

Languages

Rust

Security Score

95/100

Audited on Mar 14, 2026

No findings