API Reference
Complete reference for all methods generated by ring-buffer-macro, organized by mode.
Standard Mode
The default mode. Single-threaded, uses &mut self for mutations. Requires T: Clone for dequeue and drain.
new
Creates a new empty buffer with the compile-time capacity. Head, tail, and size are initialized to 0.
let mut buf = Buffer::new();assert!(buf.is_empty());assert_eq!(buf.capacity(), 8); // from #[ring_buffer(8)]enqueue
Adds an item to the back of the buffer. Returns Err(item) if the buffer is full, allowing you to recover the rejected value.
buf.enqueue(42).unwrap();
// Handle full bufferif let Err(rejected) = buf.enqueue(99) { println!("Buffer full, {} rejected", rejected);}dequeue
Removes and returns the oldest item from the front. Returns None if the buffer is empty. Requires T: Clone because it copies the value out of the internal Vec.
buf.enqueue(1).unwrap();buf.enqueue(2).unwrap();assert_eq!(buf.dequeue(), Some(1)); // FIFO orderassert_eq!(buf.dequeue(), Some(2));assert_eq!(buf.dequeue(), None); // emptypeek / peek_mut / peek_back
View items without removing them. peek() returns the front (oldest), peek_back() returns the back (newest), and peek_mut() gives a mutable reference to the front.
buf.enqueue(1).unwrap();buf.enqueue(2).unwrap();buf.enqueue(3).unwrap();
assert_eq!(buf.peek(), Some(&1)); // oldestassert_eq!(buf.peek_back(), Some(&3)); // newest
// Modify the front itemif let Some(front) = buf.peek_mut() { *front = 10;}assert_eq!(buf.dequeue(), Some(10));is_full / is_empty
Check buffer state. is_full() returns true when len equals capacity.
let mut buf = Buffer::new(); // capacity 4assert!(buf.is_empty());assert!(!buf.is_full());
for i in 0..4 { buf.enqueue(i).unwrap(); }assert!(buf.is_full());assert!(!buf.is_empty());len / capacity
len() returns the current number of items. capacity() returns the compile-time maximum.
let mut buf = Buffer::new(); // #[ring_buffer(8)]assert_eq!(buf.len(), 0);assert_eq!(buf.capacity(), 8);
buf.enqueue(1).unwrap();assert_eq!(buf.len(), 1);clear
Removes all items from the buffer. Resets head, tail, and size to 0. Does not deallocate the underlying Vec.
buf.enqueue(1).unwrap();buf.enqueue(2).unwrap();buf.clear();assert!(buf.is_empty());assert_eq!(buf.len(), 0);iter / drain
iter() provides a non-consuming iterator over buffer contents in FIFO order. drain() returns a consuming iterator that removes items as it goes. The drain iterator cleans up remaining items on drop.
buf.enqueue(1).unwrap();buf.enqueue(2).unwrap();buf.enqueue(3).unwrap();
// Non-consuming iterationfor item in buf.iter() { println!("{}", item);}assert_eq!(buf.len(), 3); // unchanged
// Consuming iterationlet items: Vec<_> = buf.drain().collect();assert_eq!(items, vec![1, 2, 3]);assert!(buf.is_empty());SPSC Mode
Lock-free single-producer single-consumer mode. Uses atomic operations with Acquire/Release memory ordering. Requires T: Send.
new / split
Create the buffer with new(), then split() into producer and consumer handles. The split enforces the SPSC contract at the type level.
use std::sync::Arc;
#[ring_buffer(capacity = 256, mode = "spsc")]struct SpscBuffer(i32);
let buf = Arc::new(SpscBuffer::new());let (producer, consumer) = buf.split();try_enqueue
Non-blocking enqueue. Returns Err(item) if the buffer is full. Uses Acquire load of head and Release store of tail.
match producer.try_enqueue(42) { Ok(()) => println!("sent"), Err(item) => println!("full, {} rejected", item),}try_dequeue / peek
Non-blocking dequeue. Returns None if empty. Uses Acquire load of tail and Release store of head. peek() views the front item without consuming it.
if let Some(item) = consumer.try_dequeue() { println!("received: {}", item);}
if let Some(front) = consumer.peek() { println!("next: {}", front);}Blocking Operations
Available when blocking = true. Uses Condvar to sleep instead of spinning. The data path remains lock-free — Mutex is only used for Condvar signaling.
#[ring_buffer(capacity = 64, mode = "spsc", blocking = true)]struct BlockingSpsc(i32);
let buf = Arc::new(BlockingSpsc::new());let (producer, consumer) = buf.split();
// These block instead of returning Err/Noneproducer.enqueue_blocking(42);let item = consumer.dequeue_blocking();MPSC Mode
Multiple producers, single consumer. Producers coordinate via CAS (Compare-And-Swap) on the tail index. Per-slot written flags ensure the consumer only reads completed writes. Requires T: Send.
new / producer / consumer
Create the buffer, then obtain producer and consumer handles. Producer handles are Clone — create one per producer thread.
#[ring_buffer(capacity = 128, mode = "mpsc")]struct MpscBuffer(i32);
let buf = Arc::new(MpscBuffer::new());let consumer = buf.consumer();
// Clone producers for each threadlet p1 = buf.producer();let p2 = buf.producer();try_enqueue
CAS-based non-blocking enqueue. Each producer atomically claims a slot via compare_exchange_weak on the tail, writes the item, then sets the written flag.
// Safe to call from multiple threads simultaneouslywhile producer.try_enqueue(value).is_err() { std::hint::spin_loop();}try_dequeue / peek
Non-blocking dequeue. Checks the written flag before reading to ensure the producer has finished writing. peek() views the front item without consuming.
if let Some(item) = consumer.try_dequeue() { process(item);}Blocking Operations
Available when blocking = true. Same Condvar-based approach as SPSC blocking.
#[ring_buffer(capacity = 64, mode = "mpsc", blocking = true)]struct BlockingMpsc(i32);
let buf = Arc::new(BlockingMpsc::new());let producer = buf.producer();let consumer = buf.consumer();
producer.enqueue_blocking(42);let item = consumer.dequeue_blocking();