Lockless, thread-safe, single-producer, single-consumer, FIFO queue for Python — implemented on a ring buffer in C.
Built on a Lamport ring buffer with C11 _Atomic read/write indexes (acquire/release ordering). Producer and consumer never contend with eachother.
Features:
- Single producer, single consumer, FIFO semantics
- Lockless (no mutexes or spinlocks)
- Non-blocking / async-friendly
- Suitable for shared memory and IPC
- Compatible with no-GIL & subinterpreters
- Low overhead, especially for small messages
- Up to 100x faster than
multiprocessing.Queuein the standard library
import spsc_ring_threadsafe as srt
buf = bytearray(4096)
srt.init(buf) # initialize as ring buffer
item = b"this is a bytestring message"
srt.put(buf, item)
result = srt.get(buf)
print(result.decode())Output:
this is a bytestring message
from multiprocessing import shared_memory
import spsc_ring_threadsafe as srt
shm_name = "app_123456"
# Process 1 (producer)
a = shared_memory.SharedMemory(create=True, size=4096, name=shm_name)
srt.init(a.buf) # initialize as ring buffer
item = b"hello from shared memory!"
srt.put(a.buf, item)
a.close()
# Process 2 (consumer)
b = shared_memory.SharedMemory(name=shm_name)
result = srt.get(b.buf)
print(result.decode())
b.close()
b.unlink()Output:
hello from shared memory!
| Exception | Raised when |
|---|---|
spsc_ring_threadsafe.QueueFullError |
put() called on a full buffer |
spsc_ring_threadsafe.QueueEmptyError |
get() called on an empty buffer |
Initialize a mutable buffer as a ring buffer (this function sets the read + write indexes to zero).
| Parameter | Description |
|---|---|
buf |
Mutable buffer-compatible object (bytearray, memoryview, etc.). Size must be a power-of-two anywhere from 256 bytes to 2 GiB. Also accepts shared memory buffers. |
⚠️ Thread safety: Initialization is not thread-safe. Initialize once before any concurrent access, or provide your own synchronization.
Insert an item into the ring buffer. Non-blocking.
| Parameter | Description |
|---|---|
buf |
Mutable buffer-compatible object. Size must be a power-of-two anywhere from 256 bytes to 2 GiB. Also accepts shared memory buffers. |
item |
Buffer-compatible object to insert |
Raises: QueueFullError if the buffer has insufficient space.
⚠️ Buffer must be zeroed or initialized before use.
⚠️ Thread safety: Only a single producer is allowed for a given queue! Multiple producers are NOT thread-safe.
Remove and return an item from the ring buffer. Non-blocking.
| Parameter | Description |
|---|---|
buf |
Mutable buffer-compatible object. Size must be a power-of-two anywhere from 256 bytes to 2 GiB. Also accepts shared memory buffers. |
Returns: Buffer-compatible object containing the message.
Raises: QueueEmptyError if no message is available.
⚠️ Buffer must be zeroed or initialized before use.
⚠️ Thread safety: Only a single consumer is allowed for a given queue! Multiple consumers are NOT thread-safe.
uv add spsc-ring-threadsafeor
pip install spsc-ring-threadsafeuv run python -m unittest discover -s tests -vuv pip install -e . --force-reinstall --no-deps
uv run python tests/benchmark.pyuv pip install -e . --force-reinstall --no-deps
uv run python tests/dev.pyTests and benchmarks were written with assistance from AI models. All C code is written by hand.
