freref/spsc-queue
Fast bounded SPSC queue written in Zig
325b0765de97362e50ccc0eefbb4df09c7ef808a.tar.gz
A single producer single consumer wait-free and lock-free fixed size queue written in Zig. Inspired by rigtorp's implementation in C++. This implementation is faster than rigtorp/SPSCQueue, boost::lockfree::spsc, cdolan/zig-spsc-ring, and folly::ProducerConsumerQueue.
This library provides a managed and an unmanaged version of the queue, following the Zig standard library conventions. There are 2 implementations of the queue:
The user can choose which implementation they want to use by setting the enforce_po2
flag to true
when defining the queue type. I opted for this interface over detecting if the capacity is po2, because the flag makes the choice explicit and known at comptime. It's clear to the user that there are two distinct implementations with different trade-offs. I borrowed this idea from joadnacer/atomic_queue.
You can find a basic example here. You can run this example with the following command:
zig build run-example
Unmanaged version:
pub fn initBuffer(buffer: []T) Self
pub fn initCapacity(allocator: std.mem.Allocator, num: usize) !Self
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void
Managed version:
pub fn initCapacity(allocator: std.mem.Allocator, num: usize) !Self
pub fn fromOwnedSlice(allocator: std.mem.Allocator, buffer: []T) Self
pub fn deinit(self: *Self) void
General API:
pub fn isEmpty(self: *Self) bool
pub fn size(self: *Self) usize
pub fn push(self: *Self, value: T) void
pub fn tryPush(self: *Self, value: T) bool
pub fn front(self: *Self) ?*T
pub fn pop(self: *Self) void
I made a seperate repo for benchmarking various SPSC queue implementations, more info on the benchmarks can be found there. These benchmarks are currently not very rigorous, but they give a rudimentary idea of the performance of this implementation compared to others. The benchmarks were run on a MacBook Pro (Apple M4 Pro, 14 cores: 10 performance + 4 efficiency) with 48 GB unified memory.