A small, thread-safe, fixed-capacity circular buffer implementation in plain C. It uses a statically allocated array (no dynamic allocation), a mutex for thread-safety, and a power-of-two capacity for efficient wrap-around.
- Fixed-size buffer (no
malloc/free) - O(1) reads and writes with bitmask wrap-around
- POSIX
pthreadmutex for safe producer/consumer use from threads - Drop counting on overflow (no silent overwrites)
- Simple API and deterministic behavior for real-time systems
ring-buffer/
├── include/
│ └── ring_buffer.h # public API and types
├── src/
│ ├── ring_buffer.c # implementation
│ └── sanity.c # simple walkthrough / demo
├── tests/
│ └── stress_test.c # concurrent producer/consumer verification
└── Makefile
Requires a C compiler and make.
makeThis produces the sanity and stress_test binaries.
Run the sanity check to see the API behavior and example output:
./sanityRun the stress test to verify the correctness invariant under concurrent load (producer + consumer threads):
./stress_testThe stress test checks the invariant:
total_written == total_read + in_buffer + total_dropped
- No dynamic memory: the buffer stores
packet_t slots[RING_CAPACITY]. - Power-of-two capacity enables
index = (index + 1) & RING_MASKwrap. - Mutex-protected operations; every exit path unlocks on error.
- On overflow, the implementation increments a drop counter instead of overwriting oldest data silently.
- API declarations: include/ring_buffer.h
- Implementation: src/ring_buffer.c
- Sanity/demo: src/sanity.c
- Concurrency proof: tests/stress_test.c
This implementation targets deterministic, memory-safe environments such as embedded or real-time systems where dynamic allocation is disallowed.