PebbleOS
Loading...
Searching...
No Matches
Data Structures | Functions
Shared circular buffer

Circular buffer with one writer and several independent readers. More...

Data Structures

struct  pbl_shared_cbuf_client
 Read client, allocated by the caller. More...
 
struct  pbl_shared_cbuf
 Shared circular buffer state. More...
 
struct  pbl_shared_cbuf_subsampled_client
 Read client that keeps only a fraction of fixed-size items. More...
 

Functions

void pbl_shared_cbuf_init (struct pbl_shared_cbuf *buffer, uint8_t *storage, uint16_t storage_size)
 Initialize a shared circular buffer, without clients.
 
bool pbl_shared_cbuf_write (struct pbl_shared_cbuf *buffer, const uint8_t *data, uint16_t length, bool advance_slackers)
 Write data to the buffer.
 
bool pbl_shared_cbuf_write_reserve (struct pbl_shared_cbuf *buffer, uint16_t length, bool advance_slackers, uint8_t **seg1, uint16_t *seg1_length, uint8_t **seg2)
 Reserve write space to fill in place.
 
void pbl_shared_cbuf_write_commit (struct pbl_shared_cbuf *buffer, uint16_t length)
 Commit a reservation made with pbl_shared_cbuf_write_reserve().
 
bool pbl_shared_cbuf_add_client (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client)
 Add a read client.
 
void pbl_shared_cbuf_remove_client (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client)
 Remove a read client.
 
bool pbl_shared_cbuf_read (const struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client, uint16_t length, const uint8_t **data_out, uint16_t *length_out)
 Get a pointer to the oldest data of a client, without consuming it.
 
bool pbl_shared_cbuf_consume (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client, uint16_t length)
 Remove the oldest data of a client.
 
uint16_t pbl_shared_cbuf_get_write_space_remaining (const struct pbl_shared_cbuf *buffer)
 Get the free space, limited by the client farthest behind.
 
uint16_t pbl_shared_cbuf_get_read_space_remaining (const struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client)
 Get the amount of data available to a client.
 
bool pbl_shared_cbuf_read_consume (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client, uint16_t length, uint8_t *data, uint16_t *length_out)
 Copy out and consume data of a client, handling the wrap.
 
void pbl_shared_cbuf_add_subsampled_client (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_subsampled_client *client, uint32_t subsample_numerator, uint32_t subsample_denominator)
 Add a read client that subsamples the data.
 
void pbl_shared_cbuf_remove_subsampled_client (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_subsampled_client *client)
 Remove a subsampling read client.
 
void pbl_shared_cbuf_subsampled_client_set_ratio (struct pbl_shared_cbuf_subsampled_client *client, uint32_t numerator, uint32_t denominator)
 Change the subsampling ratio of a client.
 
size_t pbl_shared_cbuf_read_subsampled (struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_subsampled_client *client, size_t item_size, void *data, uint16_t num_items)
 Read and consume items with subsampling.
 

Detailed Description

Circular buffer with one writer and several independent readers.

Data stays available until every client has read it; each client has its own read index. The writer can force the clients that fall behind forward to make room for new data. Writes are dropped while there are no clients. One byte of the storage is never used. There is no locking.

static uint8_t s_storage[512];
static struct pbl_shared_cbuf s_buf;
static struct pbl_shared_cbuf_client s_client;
pbl_shared_cbuf_init(&s_buf, s_storage, sizeof(s_storage));
pbl_shared_cbuf_add_client(&s_buf, &s_client);
pbl_shared_cbuf_write(&s_buf, sample, sizeof(sample), true);
uint16_t len;
pbl_shared_cbuf_read_consume(&s_buf, &s_client, sizeof(out), out, &len);
Shared circular buffer state.
Definition shared_cbuf.h:47
Read client, allocated by the caller.
Definition shared_cbuf.h:39
bool pbl_shared_cbuf_read_consume(struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client, uint16_t length, uint8_t *data, uint16_t *length_out)
Copy out and consume data of a client, handling the wrap.
void pbl_shared_cbuf_init(struct pbl_shared_cbuf *buffer, uint8_t *storage, uint16_t storage_size)
Initialize a shared circular buffer, without clients.
bool pbl_shared_cbuf_add_client(struct pbl_shared_cbuf *buffer, struct pbl_shared_cbuf_client *client)
Add a read client.
bool pbl_shared_cbuf_write(struct pbl_shared_cbuf *buffer, const uint8_t *data, uint16_t length, bool advance_slackers)
Write data to the buffer.

Data Structure Documentation

◆ pbl_shared_cbuf_client

struct pbl_shared_cbuf_client

Read client, allocated by the caller.

Data Fields
ListNode list_node Node in the client list of the buffer.
uint16_t read_index Offset of the next byte to read for this client.

◆ pbl_shared_cbuf

struct pbl_shared_cbuf

Shared circular buffer state.

Data Fields
uint8_t * buffer Storage.
uint16_t buffer_size Size of buffer in bytes.
ListNode * clients List of clients.
uint16_t write_index Offset where the next byte is written; a client whose read index equals it has no data.

◆ pbl_shared_cbuf_subsampled_client

struct pbl_shared_cbuf_subsampled_client

Read client that keeps only a fraction of fixed-size items.

Data Fields
struct pbl_shared_cbuf_client buffer_client Underlying client.
uint32_t denominator Denominator of the subsampling ratio.
uint32_t numerator Numerator of the subsampling ratio.
uint32_t subsample_state Tracks whether to copy or discard each successive item.

Function Documentation

◆ pbl_shared_cbuf_add_client()

bool pbl_shared_cbuf_add_client ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client 
)

Add a read client.

The client starts with no data: it only sees what is written after it is added.

Parameters
bufferBuffer.
clientClient, must stay valid until removed. Must not be added already.
Returns
true.

◆ pbl_shared_cbuf_add_subsampled_client()

void pbl_shared_cbuf_add_subsampled_client ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_subsampled_client *  client,
uint32_t  subsample_numerator,
uint32_t  subsample_denominator 
)

Add a read client that subsamples the data.

Parameters
bufferBuffer.
clientClient, must stay valid until removed.
subsample_numeratorNumerator of the initial subsampling ratio, at least 1.
subsample_denominatorDenominator of the initial subsampling ratio, at least subsample_numerator.
See also
pbl_shared_cbuf_subsampled_client_set_ratio()

◆ pbl_shared_cbuf_consume()

bool pbl_shared_cbuf_consume ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client,
uint16_t  length 
)

Remove the oldest data of a client.

Parameters
bufferBuffer.
clientClient.
lengthNumber of bytes to remove.
Returns
false if the client has fewer than length bytes available (nothing is removed).

◆ pbl_shared_cbuf_get_read_space_remaining()

uint16_t pbl_shared_cbuf_get_read_space_remaining ( const struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client 
)

Get the amount of data available to a client.

Parameters
bufferBuffer.
clientClient.
Returns
Number of bytes the client can read.

◆ pbl_shared_cbuf_get_write_space_remaining()

uint16_t pbl_shared_cbuf_get_write_space_remaining ( const struct pbl_shared_cbuf *  buffer)

Get the free space, limited by the client farthest behind.

Parameters
bufferBuffer.
Returns
Number of bytes that can be written without advancing any client.

◆ pbl_shared_cbuf_init()

void pbl_shared_cbuf_init ( struct pbl_shared_cbuf *  buffer,
uint8_t *  storage,
uint16_t  storage_size 
)

Initialize a shared circular buffer, without clients.

Parameters
[out]bufferBuffer.
storageStorage, must outlive buffer.
storage_sizeSize of storage in bytes.

◆ pbl_shared_cbuf_read()

bool pbl_shared_cbuf_read ( const struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client,
uint16_t  length,
const uint8_t **  data_out,
uint16_t *  length_out 
)

Get a pointer to the oldest data of a client, without consuming it.

When the requested data wraps around the end of the storage, only the part up to the end is returned and length_out is smaller than length; read again after consuming it to get the rest. data_out stays valid until the data is consumed.

Parameters
bufferBuffer.
clientClient.
lengthNumber of bytes to read.
[out]data_outStart of the data.
[out]length_outNumber of contiguous bytes at data_out.
Returns
false if the client has fewer than length bytes available.

◆ pbl_shared_cbuf_read_consume()

bool pbl_shared_cbuf_read_consume ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client,
uint16_t  length,
uint8_t *  data,
uint16_t *  length_out 
)

Copy out and consume data of a client, handling the wrap.

Parameters
bufferBuffer.
clientClient.
lengthMaximum number of bytes to read.
[out]dataDestination, at least length bytes.
[out]length_outNumber of bytes read.
Returns
true if length bytes were read, false if fewer were available.

◆ pbl_shared_cbuf_read_subsampled()

size_t pbl_shared_cbuf_read_subsampled ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_subsampled_client *  client,
size_t  item_size,
void *  data,
uint16_t  num_items 
)

Read and consume items with subsampling.

Discarded items are consumed too.

Parameters
bufferBuffer.
clientClient.
item_sizeSize of an item in bytes.
[out]dataDestination, at least item_size * num_items bytes.
num_itemsMaximum number of items to return, after subsampling.
Returns
Number of items written to data.

◆ pbl_shared_cbuf_remove_client()

void pbl_shared_cbuf_remove_client ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_client *  client 
)

Remove a read client.

Parameters
bufferBuffer.
clientClient added with pbl_shared_cbuf_add_client().

◆ pbl_shared_cbuf_remove_subsampled_client()

void pbl_shared_cbuf_remove_subsampled_client ( struct pbl_shared_cbuf *  buffer,
struct pbl_shared_cbuf_subsampled_client *  client 
)

Remove a subsampling read client.

Parameters
bufferBuffer.
clientClient added with pbl_shared_cbuf_add_subsampled_client().

◆ pbl_shared_cbuf_subsampled_client_set_ratio()

void pbl_shared_cbuf_subsampled_client_set_ratio ( struct pbl_shared_cbuf_subsampled_client *  client,
uint32_t  numerator,
uint32_t  denominator 
)

Change the subsampling ratio of a client.

A different ratio resets the subsampling state, which may introduce jitter on the next read. A numerator greater than 1 introduces jitter in the subsampled stream.

Parameters
clientClient.
numeratorNumerator of the ratio, at least 1.
denominatorDenominator of the ratio, at least numerator.

◆ pbl_shared_cbuf_write()

bool pbl_shared_cbuf_write ( struct pbl_shared_cbuf *  buffer,
const uint8_t *  data,
uint16_t  length,
bool  advance_slackers 
)

Write data to the buffer.

Parameters
bufferBuffer.
dataData to write.
lengthNumber of bytes to write, less than the storage size.
advance_slackersMake room by moving the read index of the client farthest behind forward, as many times as needed.
Returns
false if there are no clients, length does not fit the storage, or there is not enough space and advance_slackers is false.

◆ pbl_shared_cbuf_write_commit()

void pbl_shared_cbuf_write_commit ( struct pbl_shared_cbuf *  buffer,
uint16_t  length 
)

Commit a reservation made with pbl_shared_cbuf_write_reserve().

Parameters
bufferBuffer.
lengthReserved length.

◆ pbl_shared_cbuf_write_reserve()

bool pbl_shared_cbuf_write_reserve ( struct pbl_shared_cbuf *  buffer,
uint16_t  length,
bool  advance_slackers,
uint8_t **  seg1,
uint16_t *  seg1_length,
uint8_t **  seg2 
)

Reserve write space to fill in place.

Fill the returned segment(s), then call pbl_shared_cbuf_write_commit() with the same length. The reservation is split into two segments when it wraps the end of the storage.

Parameters
bufferBuffer.
lengthNumber of bytes to reserve.
advance_slackersSee pbl_shared_cbuf_write().
[out]seg1First segment.
[out]seg1_lengthLength of the first segment, length when there is no wrap.
[out]seg2Second segment, at the start of the storage, or NULL when there is no wrap.
Returns
false under the same conditions as pbl_shared_cbuf_write().