rtrb
A wait-free, allocation-free single-producer single-consumer ring buffer for real-time Rust systems.
Repository Health
Technical Analysis
rtrb (Real-Time Ring Buffer) is a bounded SPSC queue built for code paths where blocking is not an option, such as audio callbacks, device drivers, or any producer/consumer pair split across a real-time thread and a non-real-time one. A fixed-capacity buffer is allocated once at construction; after that, push() and pop() never allocate, lock, or block — a full or empty buffer simply returns an error immediately so the caller can decide what to do next.
Beyond single-item push/pop, rtrb exposes a chunk API (write_chunk, write_chunk_uninit, read_chunk) for moving multiple items at once via as_mut_slices(), including uninitialized-memory variants for MaybeUninit<T> producers and std::io::Read/Write implementations for Producer<u8>/Consumer<u8>. The crate is #![no_std]-compatible (via the alloc crate) with the std feature enabled by default, making it usable in embedded and other resource-constrained targets as well as ordinary desktop/server Rust.
What You Get
- A
RingBuffer::new(capacity)constructor that returns aProducer<T>andConsumer<T>pair sharing one fixed-capacity buffer - Wait-free single-item
push()/pop()/peek()withPushError/PopError/PeekErrortypes instead of panics or blocking - A chunk API (
write_chunk,write_chunk_uninit,read_chunk) for moving multiple items per call via contiguous or wrap-around slice pairs std::io::WriteforProducer<u8>andstd::io::ReadforConsumer<u8>, pluspush_entire_slice/pop_entire_slicehelpers forT: Copy#![no_std]support (viaalloc) with thestdfeature default-enabled, for embedded and constrained targetsis_abandoned()on both halves so one side can detect the other has been dropped without deadlocking
Common Use Cases
- Passing audio samples from a real-time DSP/audio-callback thread to a UI or logging thread without ever blocking the audio thread
- Streaming sensor or device-driver data from an interrupt-context or embedded producer to a consumer that processes it later
- Any single-writer/single-reader pipeline where allocation-free, deterministic-latency handoff matters more than raw throughput
- Building higher-level MPSC/MPMC or actor-style messaging primitives on top of a proven SPSC core
Under The Hood
Architecture
The crate is split into three files with a clear ownership story: lib.rs defines the public RingBuffer<T>, Producer<T>, and Consumer<T> types plus the cache-padded atomic head/tail cursors that encode position modulo 2 * capacity; arc_ring_buffer.rs implements ArcRingBuffer, a hand-rolled reference-counted pointer (via Box::leak/Box::from_raw and an IS_ABANDONED flag on an AtomicU8) that lets Producer and Consumer each hold a raw pointer to one heap-allocated RingBuffer and safely tear it down whichever side drops last; and chunks.rs layers a batched read/write API (WriteChunk, WriteChunkUninit, ReadChunk) on top of the same cursors for moving multiple elements per call. Every unsafe block that manipulates the raw pointer or crosses the atomic boundary carries an explicit // SAFETY: comment enforced by clippy::undocumented_unsafe_blocks, and the abandonment protocol is documented inline with the exact Release/Acquire ordering it relies on to avoid a race on the final drop.
Tech Stack
rtrb is pure Rust with a deliberately minimal dependency footprint: it depends on nothing outside core/alloc at build time, targets edition 2018 with an MSRV of Rust 1.38, and gates std-only functionality (like the io::Read/Write impls) behind a default-on std feature so the crate still builds #![no_std] when that feature is disabled. Dev-dependencies are limited to rand and criterion for benchmarking plus a submoduled copy of crossbeam-utils’s cache_padded.rs, vendored directly into src/ via a symlink rather than pulled in as a runtime dependency, keeping the published crate’s dependency tree effectively empty.
Code Quality
Testing here goes well beyond typical unit tests: tests/ covers capacity edge cases (zero capacity, zero-sized types), single- and multi-threaded push/pop correctness, and the chunk API; CI additionally runs the full suite under Miri twice (once with -Zmiri-preemption-rate=0 targeting a specific no-race regression test) and under ThreadSanitizer with -Z sanitizer=thread, which is the level of rigor expected of a crate whose entire value proposition is race-free concurrent access. cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --check, and cargo rustdoc -- -D warnings all run in CI, the crate denies missing_docs and missing_debug_implementations at the lint level, and no_std compatibility is checked separately with cargo-nono. There are no half-measures visible in this pipeline.
What Makes It Unique
Most SPSC ring buffer crates stop at single-item push/pop; rtrb’s chunk API returns direct mutable/immutable slice pairs (handling the wrap-around split transparently) so callers can memcpy or iterate in bulk without per-item atomic overhead, while still supporting a zero-copy uninitialized-memory path via MaybeUninit<T> for producers that want to write into place. Combining that with genuine #![no_std] support, a documented abandonment protocol for graceful cross-thread teardown, and a test matrix that includes Miri and ThreadSanitizer runs (not just cargo test) sets it apart from most concurrency-primitive crates, which typically ship far lighter verification for the same correctness claims. The maintainer’s own README candidly lists over a dozen comparable crates, positioning rtrb as a carefully verified, narrowly-scoped alternative rather than a novel algorithmic breakthrough.