A single-header, lock-free ring buffer written in C99+. Designed for fast thread-to-thread and cross-process shared memory communication.
- SPSC (Single Producer Single Consumer) - default
- MPMC (Multi Producer Multi Consumer) - enable with
#define RINGBUF_MPMC
- Single header - drop
ringbuf.hinto your project - Lock-free - uses atomics for thread-safe operations without locks
- Cache-line padded - head/tail separated to prevent false sharing
- Variable-length data - automatically prefixes writes with size metadata
- Big & Little Endianess - works with both big & little endian systems
- Optional statistics - enable with
#define RINGBUF_STATISTICSfor timing metrics - Shared memory compatible - works with memory-mapped buffers
- Highly portable - works with any C99+ compiler on architectures including x86, x86-64, ARM, ARM64, RISC-V, and more
- Important - on some non x86/x86-64 based systems (like ARM based systems) they might have cache Lines that are not 64 bytes, its very important to set
RINGBUF_CACHE_LINE_SIZEandRINGBUF_ALIGNMENTcorrectly
- Important - on some non x86/x86-64 based systems (like ARM based systems) they might have cache Lines that are not 64 bytes, its very important to set
By default, ringbuf uses cache-line padding optimized for most architectures. You can customize this:
RINGBUF_CACHE_LINE_SIZE- override the cache line size (default: 64)RINGBUF_ALIGNMENT- override the alignment boundary (default: 0x1000)
Copy ringbuf.h into your project.
Add #define RINGBUF_IMPLEMENTATION before including the header in one source file:
#define RINGBUF_IMPLEMENTATION
#include "ringbuf.h"#define RINGBUF_IMPLEMENTATION
#include "ringbuf.h"
#include <stdint.h>
#include <memory.h>
#include <stdio.h>
int main(void)
{
uint8_t buffer[8192];
struct ringbuf rb;
memset(buffer, 0, sizeof(buffer));
ringbuf_init(&rb, buffer, sizeof(buffer));
uint8_t data[] = "Hello, world!";
ringbuf_write(&rb, data, sizeof(data));
uint8_t out[256];
size_t out_len = sizeof(out);
ringbuf_err_t err = ringbuf_read(&rb, out, &out_len);
assert(err == RbSuccess);
assert(out_len == sizeof(data));
assert(memcmp(out, data, out_len) == 0);
printf("success\n");
return 0;
}For multi-producer multi-consumer use, define RINGBUF_MPMC and use ringbuf_mpmc_write / ringbuf_mpmc_read:
#define RINGBUF_MPMC
#define RINGBUF_IMPLEMENTATION
#include "ringbuf.h"Define RINGBUF_STATISTICS before including the header to enable timing statistics:
#define RINGBUF_STATISTICS
#define RINGBUF_IMPLEMENTATION
#include "ringbuf.h"Functions available:
ringbuf_get_stats(rb, out)- get all statisticsringbuf_avg_write_ns(rb)- average write time in nanosecondsringbuf_avg_read_ns(rb)- average read time in nanoseconds
Licensed under the Apache License, Version 2.0. See LICENSE for details.