A lock-free circular buffer for embedded systems, real-time applications, and multi-threaded environments. This library provides a thread-safe ring buffer with ISR-safe operations and comprehensive error handling.
- Features
- Getting Started
- API Reference
- Usage Examples
- Configuration Options
- Platform Support
- Performance
- Support
- Lock-free design: Works safely with one producer and one consumer
- Dual API: Simple boolean returns or detailed error codes (see API Reference)
- Cross-platform: Runs on Linux, Windows, macOS, and embedded systems
- Zero dynamic memory: Uses only static buffer allocation
- ISR-safe: Safe for interrupt service routines
- Memory barriers: Ensures correct memory ordering between threads
- Thoroughly tested: 37 tests with 100% pass rate
- Bulk operations: Efficiently transfer multiple items at once
- Overwrite mode: Optional automatic overwrite of oldest data
- Peek functionality: Read data without removing it
- Buffer validation: Integrity checks to detect corruption
- C compiler (GCC, Clang, MSVC, or embedded toolchain)
- CMake (>= 3.10)
- GoogleTest (for running tests)
# Clone the repository
git clone https://github.com/diffstorm/cb.git
cd cb
# Create build directory
mkdir build && cd build
# Configure and build
cmake ..
make
# Run lock-free demo
./demo
# Run mutex-protected demo
./demo_mutex
# Run bulk operations demo
./demo_bulk
# Run overwrite mode demo
./demo_overwrite
# Run enhanced error handling demo
./demo_enhanced
# Run statistics demo
./demo_stats
# Run timeout operations demo
./demo_timeout
# Run basic tests
./tests/test_basic
# Run advanced tests
./tests/test_advanced
# Run error handling tests
./tests/test_error
# Run timeout functionality tests
./tests/test_timeout
# Run statistics tests
./tests/test_stats
For detailed API documentation, please see the API Reference file.
The library provides two complementary APIs:
Simple API | Detailed API |
---|---|
Returns true /false |
Returns specific error codes |
Minimal overhead | Comprehensive error information |
Good for embedded systems | Good for production systems |
Best for prototyping | Best for safety-critical applications |
For guidance on when to use each API style, see the API Design Philosophy section in the API Reference.
The library provides functions in these categories:
- Initialization: Initialize buffer with static storage
- Basic Operations: Insert, remove, and peek operations
- Bulk Operations: Efficiently transfer multiple items at once
- State Information: Get buffer status and validate integrity
- Overwrite Control: Configure automatic overwrite behavior
- Error Handling: Get human-readable error messages
Each function has both a simple version (e.g., cb_insert()
) and a detailed version with error codes (e.g., cb_insert_ex()
).
See the API Reference for complete function signatures and detailed documentation.
The following examples demonstrate basic usage patterns. For more advanced usage patterns including thread-safe producer-consumer scenarios, ISR-safe usage, and batch processing, see the Usage Patterns section in the API Reference.
#include "cb.h"
#define BUFFER_SIZE 128
CbItem storage[BUFFER_SIZE];
cb my_buffer;
// Initialize buffer
cb_init(&my_buffer, storage, BUFFER_SIZE);
// Producer: Add data
if (cb_insert(&my_buffer, sensor_reading)) {
// Success
} else {
// Buffer full
}
// Consumer: Get data
CbItem data;
if (cb_remove(&my_buffer, &data)) {
process_data(data);
}
#include "cb.h"
#define BUFFER_SIZE 128
CbItem storage[BUFFER_SIZE];
cb my_buffer;
// Initialize with error checking
cb_result_t result = cb_init_ex(&my_buffer, storage, BUFFER_SIZE);
if (result != CB_SUCCESS) {
log_error("Buffer init failed: %s", cb_error_string(result));
return -1;
}
// Producer with detailed error handling
result = cb_insert_ex(&my_buffer, sensor_reading);
switch (result) {
case CB_SUCCESS:
break;
case CB_ERROR_BUFFER_FULL:
// Enable overwrite mode and retry
cb_set_overwrite(&my_buffer, true);
cb_insert_ex(&my_buffer, sensor_reading);
break;
default:
log_error("Insert failed: %s", cb_error_string(result));
break;
}
The circular buffer is designed for single-producer, single-consumer scenarios:
- One thread/ISR can safely call insert functions
- Another thread/ISR can safely call remove functions
- Both can happen concurrently without locks
For detailed thread safety guidelines and limitations, see the Thread Safety Considerations section in the API Reference.
The library provides several configuration options:
- Memory Barriers: Enable/disable with
#define CB_USE_MEMORY_BARRIERS
- Overwrite Mode: Control with
cb_set_overwrite()
function - Item Type: Customize with
#define CB_ITEM_TYPE
See the API Reference for detailed configuration information.
- Linux, Windows, macOS
- Embedded systems (ARM Cortex, AVR, MSP430, RISC-V)
- RTOS environments (FreeRTOS, Zephyr, VxWorks)
- Multiple compilers (GCC, Clang, MSVC, IAR, Keil)
For platform-specific considerations, see the Memory Barriers and Thread Safety Considerations sections in the API Reference.
Operation | x86 (ns) | ARM Cortex-M (ns) | RISC-V (ns) |
---|---|---|---|
Insert | 15-25 | 40-60 | 50-80 |
Remove | 12-22 | 35-55 | 45-75 |
Bulk (16) | 80-120 | 200-300 | 250-400 |
Measured on 128-byte buffer, 3.2GHz x86, 72MHz ARM Cortex-M4, 100MHz RISC-V
For performance optimization tips, see the Performance Considerations section in the API Reference.
Eray Öztürk (@diffstorm)
MIT License - see the LICENSE file for details.
Contributions welcome! Fork the repository, create a feature branch, and open a pull request.
For questions or issues, please open an issue.