A no_std SPSC (Single Producer, Single Consumer) ring buffer for embedded systems.
- Fixed capacity set at compile time via const generic
N. Usable capacity isN - 1bytes — one slot is reserved to distinguish full from empty without a separate counter. - Thread-safe for one producer and one consumer.
write_indexis owned by the producer and stored withRelease;read_indexis owned by the consumer and stored withRelease. Each sideAcquire-loads the other's index to establish the happens-before relationship needed to safely read data written by the other thread. - The buffer itself uses
UnsafeCellfor interior mutability. No heap allocation.
use ring_buffer::RingBuffer;
static mut RB: RingBuffer<64> = RingBuffer::new();
let (producer, consumer) = unsafe { RB.split() };
// producer side (e.g. ISR)
producer.write_byte(0x42);
// consumer side (e.g. main loop)
if let Some(byte) = consumer.read_byte() {
// handle byte
}split() takes &mut self, so the borrow checker prevents calling it more than once
while the producer and consumer are alive.
split() takes &mut self and returns a Producer and Consumer that each hold a shared reference to the buffer. Because split() requires exclusive access, it can only be called once while the two halves are alive — the borrow checker makes a second call a compile error. There is no runtime check; the guarantee is zero-cost.
- Bytes only (
u8). For a generic type, seeheapless::spsc. - SPSC only. Multiple producers or consumers require a mutex around the relevant half.
- When the buffer is full,
write_bytedrops the incoming byte and returnsfalse.