Skip to content

SPSC Lock-Free Queue

Overview

This is a lock-free, high-performance queue that supports one producer and one consumer thread, without any locks or blocking.


Requirements

  • The queue should be implemented as a circular buffer (ring buffer).
  • Use head and tail indices to manage enqueue and dequeue.
  • Ensure proper memory ordering using std::atomic or volatile-style behavior.
  • You are guaranteed that:
    • Only one thread will call push() (producer)
    • Only one thread will call pop() (consumer)

What You Should Not Use

  • std::mutex
  • std::condition_variable
  • Any blocking construct

Notes

  • Ensure wrap-around using % capacity or bitmasking if capacity is power-of-2.
  • Only overwrite tail if there's space. Only consume head if there's data.
  • Real systems may require memory fences (platform-specific). We'll keep it simple and safe using std::atomic<size_t> for indices.

Implement a single-producer, single-consumer lock-free queue using a ring buffer.

cpp
#include <atomic>
#include <vector>

template <typename T>
class SPSCQueue {
public:
    explicit SPSCQueue(size_t capacity)
        : buffer_(capacity), capacity_(capacity), head_(0), tail_(0) {}

    bool push(const T& item) {
        // TODO
        return false;
    }

    bool pop(T& item) {
        // TODO
        return false;
    }

private:
    std::vector<T> buffer_;
    size_t capacity_;
    std::atomic<size_t> head_;
    std::atomic<size_t> tail_;
};