← Lab

Ring Buffer

Circular buffer with read/write pointers, modular arithmetic, and wrap-around.

1x 55%
Count: 0/8 | Head: 0 | Tail: 0 | State: empty
Click Enqueue to start, or toggle Auto mode.

How It Works

A ring buffer is a fixed-size array that wraps around. Two pointers track the state: a read pointer (head) where the next value will be consumed, and a write pointer (tail) where the next value will be placed. Both advance forward and wrap using modular arithmetic: pointer = (pointer + 1) % capacity.

The buffer is empty when head equals tail (and count is zero). It's full when count equals capacity. In memory it's a flat array. The "ring" is an illusion created by the modulo operation.

Why Not a Naive Array Queue

If you use a plain array as a queue, every dequeue shifts all elements left — O(n) per operation. A ring buffer dequeues in O(1) by just moving a pointer. No shifting, no copying, no allocation. The trade-off is a fixed capacity, but for most systems that's a feature, not a limitation.

Where Ring Buffers Show Up

They're everywhere in systems programming. Linux kernel network stacks use ring buffers for packet rx/tx queues. io_uring — Linux's async I/O interface — is literally two ring buffers (submission and completion). Audio drivers use them to stream samples between hardware and software without allocation. Embedded systems use them for UART serial buffers. Log systems write to circular buffers so old entries get overwritten rather than causing allocation.

Producer-Consumer

A ring buffer is the natural data structure for the producer-consumer pattern. The producer writes at the tail, the consumer reads from the head. When the buffer is full, the producer must wait (backpressure). When it's empty, the consumer must wait. With a single producer and single consumer, you can even make it lock-free — each side owns its own pointer and only reads the other's.