← Questions
Fixed-capacity circular buffer with O(1) push and pop
0
I was asked this
No reports yet. Sign in to say where you were asked it.
Implement a generic first-in, first-out buffer with a fixed capacity. Its storage is allocated once, when the buffer is created, and never grows; pushing and popping are constant time. Then discuss how the buffer should report full and empty, and how one producer and one consumer could share it.
Interface
Unless you agree on a different interface with the interviewer, assume (shown in Python; a C++ template RingBuffer<T> is equally fine):
-
RingBuffer(capacity: int): allocates storage forcapacityitems;capacity >= 1. -
push(item) -> bool: appends at the back; returnsFalseand changes nothing when full. -
pop() -> item | None: removes and returns the front item;Nonewhen empty. -
peek() -> item | None,size() -> int,is_empty() -> bool,is_full() -> bool.
Example
b = RingBuffer(3)
b.push(1), b.push(2), b.push(3) -> True, True, True
b.push(4) -> False # full
b.pop() -> 1
b.push(4) -> True # wraps into the freed slot
b.pop(), b.pop(), b.pop() -> 2, 3, 4
b.pop() -> None # empty
Constraints
- No allocation after construction; every operation O(1).
- Items are of any type; the buffer must not keep references to popped items alive.
Clarifying questions
- When full, should
pushfail, overwrite the oldest item, or block? - Should errors be return values, exceptions, or optional types?
- Single-threaded, or one producer and one consumer, or many of each?
- In C++, must items be default-constructible, and who destroys them?
What a strong answer covers
- A fixed array with head and tail indices that wrap with modulo (or a power-of-two mask), plus a count, or one slot left empty, to tell full from empty; the trade-off between the two.
- Clearing a popped slot so the object can be freed; in C++, placement new and explicit destruction with raw storage so
Tneeds no default constructor. - Edge cases: capacity 1, many wrap-arounds, alternating push and pop at the boundary.
- For one producer and one consumer: a lock-free design where only the producer writes the tail and only the consumer writes the head, with acquire/release ordering; a mutex and condition variables for blocking or many producers.
- Tests that wrap many times and compare against a reference queue.
Follow-ups
- Add an overwrite-oldest mode for streaming sensor data.
- Make it safe for one producer and one consumer without locks. Which memory orderings do you need, and why?
- Add
push_manyandpop_manythat copy in at most two contiguous chunks.
No official answer yet. Write yours on the right and run it.
Nothing published yet.
Sign in to submit your code; every attempt is kept here.
Write and test your solution herePython in your browser, the question's tests level by level, every submission kept for you.Sign in to start coding


