Coding
Data Structures

Ring Buffer From Scratch

Difficulty

Asked at Citadel Securities, Jump Trading

Theory: Data Structures You Implement, Not Import

Read the problem, hints and solution here. The editor needs a bigger screen: open this page on a laptop to write and run your code.

Every low-latency system has a ring buffer somewhere in its hot path: market-data handlers stage packets in one, loggers hand records across threads through one, and exchange gateways queue outbound orders in one. The reason is mechanical sympathy: a fixed block of memory, no allocation after construction, and index arithmetic instead of pointer chasing.

Implement RingBuffer<T>, a fixed-capacity FIFO over a pre-allocated buffer:

  • explicit RingBuffer(std::size_t capacity): allocates storage for exactly capacity elements, once, here. capacity >= 1.
  • bool push(const T& value): appends at the tail; returns false (and changes nothing) when full.
  • std::optional<T> pop(): removes and returns the head; std::nullopt when empty.
  • std::optional<T> front() const: the head without removing it.
  • std::size_t size() const, bool empty() const, bool full() const.

No std::deque, std::queue, or std::list: the point is the index arithmetic over contiguous storage (a std::vector<T> sized once in the constructor is fine as the backing store). Indices must wrap; the buffer must keep working through many times capacity operations.

Examples

[]{ RingBuffer<int> rb(2); std::vector<int> out; out.push_back(rb.push(1)); out.push_back(rb.push(2)); out.push_back(rb.push(3)); return out; }()
// [1, 1, 0]  (third push rejected: full)

[]{ RingBuffer<int> rb(2); rb.push(7); rb.push(8); std::vector<int> out; out.push_back(*rb.pop()); rb.push(9); out.push_back(*rb.pop()); out.push_back(*rb.pop()); return out; }()
// [7, 8, 9]  (wrap-around preserves FIFO order)

Constraints

  • Element type is copyable; capacity up to \(10^6\).
  • All operations must be \(O(1)\): the hidden test drives tens of millions of operations through a small buffer, so per-operation shifting or reallocation will not finish in time.
  • Track size explicitly or reserve a slot; both are acceptable, but full() and empty() must be exact (the classic head==tail ambiguity is yours to resolve).
Rate this problem
Language: C++RingBuffer
Sample tests

Run your code to check it against the sample tests. Results appear here.

Rate this problem
Next in Quant Dev 50Hand-Rolled Hash Map