29 if (element_size == 0 || capacity == 0) {
39 size_t actual_capacity = math_next_power_of_two(capacity);
47 atomic_init(&rb->
head, 0);
48 atomic_init(&rb->
tail, 0);
49 atomic_init(&rb->
size, 0);
65 size_t current_size = atomic_load(&rb->
size);
70 size_t head = atomic_load(&rb->
head);
77 atomic_store(&rb->
head, next_head);
78 atomic_fetch_add(&rb->
size, 1);
87 size_t current_size = atomic_load(&rb->
size);
88 if (current_size == 0) {
92 size_t tail = atomic_load(&rb->
tail);
99 atomic_store(&rb->
tail, next_tail);
100 atomic_fetch_sub(&rb->
size, 1);
109 size_t current_size = atomic_load(&rb->
size);
110 if (current_size == 0) {
114 size_t tail = atomic_load(&rb->
tail);
123 return rb ? atomic_load(&rb->
size) : 0;
136 atomic_store(&rb->
head, 0);
137 atomic_store(&rb->
tail, 0);
138 atomic_store(&rb->
size, 0);
223 if (!fb || !frame_data || frame_size == 0)
227 if (frame_size > 10 * 1024 * 1024) {
258 SAFE_MEMCPY(frame_copy, frame_size, frame_data, frame_size);
259 frame_copy[frame_size] =
'\0';
309 if (frame->
size > 10 * 1024 * 1024) {
381 if (!fb || !fb->
rb || !frame_data || frame_size == 0) {
388 SET_ERRNO(
ERROR_MEMORY,
"Failed to allocate %zu bytes from buffer pool for multi-source frame", frame_size);
393 SAFE_MEMCPY(data_copy, frame_size, frame_data, frame_size);
397 .source_client_id = source_client_id,
398 .frame_sequence = frame_sequence,
399 .timestamp = timestamp,
411 log_debug(
"Frame buffer full, dropping multi-source frame from client %u", source_client_id);
419 if (!fb || !fb->
rb || !frame) {
441 if (frame->
size == 0 || !frame->
data) {
454 if (!fb || !fb->
rb || !frame) {
477 if (frame->
size == 0 || !frame->
data) {
495 frame->
data = data_copy;
⚠️‼️ Error and/or exit() when things go bad.
🔢 Bit Manipulation Utilities
🗃️ Lock-Free Unified Memory Buffer Pool with Lazy Allocation
void buffer_pool_free(buffer_pool_t *pool, void *data, size_t size)
Free a buffer back to the pool (lock-free)
void * buffer_pool_alloc(buffer_pool_t *pool, size_t size)
Allocate a buffer from the pool (lock-free fast path)
#define SAFE_MEMSET(dest, dest_size, ch, count)
#define SAFE_CALLOC(count, size, cast)
#define SAFE_MEMCPY(dest, dest_size, src, count)
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
#define log_debug(...)
Log a DEBUG message.
void ringbuffer_clear(ringbuffer_t *rb)
Clear all elements from the buffer.
void framebuffer_destroy(framebuffer_t *fb)
Destroy a frame buffer.
void framebuffer_clear(framebuffer_t *fb)
Clear all frames from the buffer, freeing their data.
bool framebuffer_read_multi_frame(framebuffer_t *fb, multi_source_frame_t *frame)
Read a multi-source frame from the buffer.
framebuffer_t * framebuffer_create_multi(size_t capacity)
Create a multi-source frame buffer for multi-user support.
ringbuffer_t * ringbuffer_create(size_t element_size, size_t capacity)
Create a new ring buffer.
framebuffer_t * framebuffer_create(size_t capacity)
Create a frame buffer for ASCII frames.
size_t ringbuffer_size(const ringbuffer_t *rb)
Get current number of elements in the buffer.
bool framebuffer_read_frame(framebuffer_t *fb, frame_t *frame)
Read a frame from the buffer.
bool ringbuffer_is_full(const ringbuffer_t *rb)
Check if buffer is full.
void ringbuffer_destroy(ringbuffer_t *rb)
Destroy a ring buffer and free its memory.
#define FRAME_MAGIC
Magic number indicating a valid frame (0xDEADBEEF)
bool ringbuffer_is_empty(const ringbuffer_t *rb)
Check if buffer is empty.
bool framebuffer_write_frame(framebuffer_t *fb, const char *frame_data, size_t frame_size)
Write a frame to the buffer.
#define FRAME_FREED
Magic number indicating a freed frame (0xFEEDFACE)
bool framebuffer_write_multi_frame(framebuffer_t *fb, const char *frame_data, size_t frame_size, uint32_t source_client_id, uint32_t frame_sequence, uint32_t timestamp)
Write a multi-source frame to the buffer (for multi-user support)
bool framebuffer_peek_latest_multi_frame(framebuffer_t *fb, multi_source_frame_t *frame)
Peek at the latest multi-source frame without removing it.
bool ringbuffer_read(ringbuffer_t *rb, void *data)
Try to read an element from the ring buffer (non-blocking)
bool ringbuffer_write(ringbuffer_t *rb, const void *data)
Try to write an element to the ring buffer (non-blocking)
bool ringbuffer_peek(ringbuffer_t *rb, void *data)
Peek at the next element without removing it.
🔢 Mathematical Utility Functions
Lock-Free Ring Buffer and Frame Buffer Management.
Frame structure that stores both data and actual size.
char * data
Pointer to frame data (not owned by this struct)
uint32_t magic
Magic number to detect corruption (FRAME_MAGIC when valid)
size_t size
Actual size of frame data in bytes.
Frame buffer structure for managing video frames.
mutex_t mutex
Mutex for thread-safe access to framebuffer operations.
ringbuffer_t * rb
Underlying ring buffer for frame storage.
Multi-source frame structure for multi-user support.
char * data
Pointer to frame data (not owned by this struct)
uint32_t magic
Magic number to detect corruption (FRAME_MAGIC when valid)
uint32_t source_client_id
Client ID that sent this frame.
size_t size
Actual size of frame data in bytes.
Lock-free ring buffer structure.
bool is_power_of_two
Whether capacity is power of 2 (enables bit masking optimization)
size_t capacity
Number of elements that can be stored.
size_t capacity_mask
Mask for fast modulo when capacity is power of 2.
_Atomic size_t tail
Read position (consumer) - atomic for lock-free operations.
_Atomic size_t size
Current number of elements - atomic for fast size checks.
size_t element_size
Size of each element in bytes.
char * buffer
The actual buffer memory.
_Atomic size_t head
Write position (producer) - atomic for lock-free operations.
Common SIMD utilities and structures.