Circular Buffer Use Cases
This sections cover some typical use cases for a circular buffer, for a description of the all functionality refer to the API section. The examples below use uint32_t, but other types work the same way with the interface.
Note that for simplicity, there is no error handling in the examples shown.
#1: Writing, reading and other operations
#include <stdint.h>
#include "cb/cb.h"
// Circular buffer structure.
cb_t cbuf;
// Underlying linear buffer for the circular buffer, with required extra element.
uint32_t lcbuf[10U + 1U];
// Linear buffer where data read from the circular buffer will be written.
uint32_t ldbuf[5U];
// Linear buffer with data to write to the circular buffer.
const uint32_t lsbuf[10U] = {0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0AU};
// Other variables.
size_t filled = 0U, unfilled = 0U;
bool is_full = false, is_empty = false;
// Initialize circular buffer, without subscribing to any events.
cb_init(&cbuf, lcbuf, 10U + 1U, sizeof(uint32_t), NULL, cb_evt_id_none, NULL);
// Write five elements, and obtain five filled elements, five unfilled elements, not full and not empty.
cb_write(&cbuf, lsbuf, 5U);
cb_get_filled(&cbuf, &filled);
cb_get_unfilled(&cbuf, &unfilled);
cb_is_full(&cbuf, &is_full);
cb_is_empty(&cbuf, &is_empty);
// Write five elements, and obtain ten filled elements, zero unfilled elements, full and not empty.
cb_write(&cbuf, lsbuf, 5U);
cb_get_filled(&cbuf, &filled);
cb_get_unfilled(&cbuf, &unfilled);
cb_is_full(&cbuf, &is_full);
cb_is_empty(&cbuf, &is_empty);
// Read five elements, and obtain five filled elements, five unfilled elements, not full and not empty.
cb_read(&cbuf, ldbuf, 5U);
cb_get_filled(&cbuf, &filled);
cb_get_unfilled(&cbuf, &unfilled);
cb_is_full(&cbuf, &is_full);
cb_is_empty(&cbuf, &is_empty);
// Read five elements, and obtain zero filled elements, ten unfilled elements, not full and empty.
cb_read(&cbuf, ldbuf, 5U);
cb_get_filled(&cbuf, &filled);
cb_get_unfilled(&cbuf, &unfilled);
cb_is_full(&cbuf, &is_full);
cb_is_empty(&cbuf, &is_empty);
// Deinitialize circular buffer.
cb_deinit(&cbuf);
#2: Using events
#include <stdint.h>
#include "cb/cb.h"
// Event handler for the circular buffer.
cb_error_t cb_evt_handler(cb_evt_t * const evt)
{
switch (evt->id)
{
case cb_evt_id_read:
{
// User provided read function, the event provides all the details of the operation.
memcpy(evt->data.read.buffer, evt->data.read.read_ptr, evt->data.read.bytes);
}
break;
case cb_evt_id_write:
{
// User provided write function, the event provides all the details of the operation.
memcpy(evt->data.write.write_ptr, evt->data.write.buffer, evt->data.write.bytes);
}
break;
case cb_evt_id_lock:
{
// User provided locking mechanism, this event must return cb_error_ok.
}
break;
case cb_evt_id_unlock:
{
// User provided unlocking mechanism, this event must return cb_error_ok.
}
break;
}
return cb_error_ok;
}
// Circular buffer structure.
cb_t cbuf;
// Underlying linear buffer for the circular buffer, with required extra element.
uint32_t lcbuf[10U + 1U];
// Linear buffer where data read from the circular buffer will be written.
uint32_t ldbuf[5U];
// Linear buffer with data to write to the circular buffer.
const uint32_t lsbuf[10U] = {0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0AU};
// Initialize circular buffer, providing an event handler and subscribing to events.
const cb_evt_id_t sub_evts = cb_evt_id_read | cb_evt_id_write | cb_evt_id_lock | cb_evt_id_unlock;
cb_init(&cbuf, lcbuf, 10U + 1U, sizeof(uint32_t), cb_evt_handler, sub_evts, NULL);
// Write five elements, this will trigger write and lock/unlock events.
cb_write(&cbuf, lsbuf, 5U);
// Read five elements, this will trigger read and lock/unlock events.
cb_read(&cbuf, lsbuf, 5U);
// Deinitialize circular buffer.
cb_deinit(&cbuf);