The Ring Buffer module provides a fast implementation of a circular buffer. Data can be written to (u_rb_write), or read (u_rb_read) from the buffer. When the buffer fills up (i.e. the reader is less efficient that the writer) any subsequent u_rb_write operation will fail until more space is made available either by an explicit reset of the buffer - which is done via u_rb_clear - or by an u_rb_read operation. The u_rb_avail and u_rb_ready functions can be used by the writer and the reader respectively to test if their actions can be taken. Initialization:
size_t rb_sz, to_write, to_read; u_rb_t *rb = NULL; // create a ring buffer of size (at least) 1024 bytes dbg_err_if (u_rb_create(1024, U_RB_OPT_NONE, &rb)); // you can get the actual size of the buffer by using u_rb_size con("ring buffer (@%p) of size %zu", rb, (rb_sz = u_rb_size(rb)));
The writer:
// assuming ibufp is an ideal, infinite size buffer :) while ((to_write = u_rb_avail(rb)) > 0) { (void) u_rb_write(rb, ibufp, to_write); ibufp += to_write; }
The reader is actually the dual:
// assuming obufp is the same class as ibufp while ((to_read = u_rb_ready(rb)) > 0) { (void) u_rb_read(rb, obufp, to_read); obufp += to_read; }
There exist two distinct implementation of the underlying machinery, one is malloc(3) based, the other is mmap(2) based. The latter is the default on platforms supporting the mmap syscall. Anyway, the user can choose to use the malloc implementation by supplying U_RB_OPT_IMPL_MALLOC as an option parameter at creation time. The malloc implementation comes in two different flavours: one using a double-size buffer which enables the u_rb_fast_read (no-copy) interface, the other using a buffer exactly the size requested by the user, but disallowing the "no-copy-read" interface (this is the default). The user can always enable the contiguous mode by supplying the U_RB_OPT_USE_CONTIGUOUS_MEM as a u_rb_create option.
Typedefs | |
typedef struct u_rb_s | u_rb_t |
The ring buffer type. | |
Enumerations | |
enum | u_rb_opts_t { U_RB_OPT_NONE = 0x00, U_RB_OPT_USE_CONTIGUOUS_MEM = 0x01, U_RB_OPT_IMPL_MALLOC = 0x02 } |
Options to tweak the ring buffer implementation. More... | |
Functions | |
int | u_rb_create (size_t hint_sz, int opts, u_rb_t **prb) |
Create a new ring buffer object. | |
int | u_rb_clear (u_rb_t *rb) |
Reset the ring buffer. | |
void | u_rb_free (u_rb_t *rb) |
Dispose a ring buffer object. | |
size_t | u_rb_size (u_rb_t *rb) |
Return the size of the ring buffer. | |
ssize_t | u_rb_read (u_rb_t *rb, void *b, size_t b_sz) |
Read from the ring buffer. | |
void * | u_rb_fast_read (u_rb_t *rb, size_t *pb_sz) |
Read from the ring buffer with minimum overhead. | |
ssize_t | u_rb_write (u_rb_t *rb, const void *b, size_t b_sz) |
Write to the ring buffer. | |
size_t | u_rb_ready (u_rb_t *rb) |
Return the number of bytes ready to be consumed. | |
size_t | u_rb_avail (u_rb_t *rb) |
Return the unused buffer space. |
enum u_rb_opts_t |
U_RB_OPT_NONE |
use default (depending on platform) creation method |
U_RB_OPT_USE_CONTIGUOUS_MEM |
force implementation to use a contiguous memory buffer to store ringbuffer data. This option enables the u_rb_fast_read interface. |
U_RB_OPT_IMPL_MALLOC |
Force use of malloc(3) based implementation. The default is to use the mmap(2) implementation on platforms supporting it. |
size_t u_rb_avail | ( | u_rb_t * | rb | ) |
Return number of unused bytes in the supplied u_rb_t object, i.e. the dual of u_rb_ready.
rb | reference to an already allocated u_rb_t object |
Definition at line 330 of file srcs/toolbox/rb.c.
int u_rb_clear | ( | u_rb_t * | rb | ) |
Reset read and write offset counters of the supplied u_rb_t object rb
rb | reference to an already allocated u_rb_t object |
0 | on success | |
-1 | on failure |
Definition at line 296 of file srcs/toolbox/rb.c.
int u_rb_create | ( | size_t | hint_sz, | |
int | opts, | |||
u_rb_t ** | prb | |||
) |
Create a new u_rb_t object of size (at least) hint_sz
and return it at *prb
. The memory region used to hold the buffer is mmap'd
and as such it has "page alignment" constraint which could make it space-inefficient in case a very tiny (i.e. much smaller than the system page size) ring buffer is needed. In fact, optimal size for a u_rb_t object is a multiple of the target system page size.
hint_sz | the suggested size in bytes for the ring buffer (the actual size could be more than that because of alignment needs) | |
opts | Bitwise inclusive OR of u_rb_opts_t values | |
prb | result argument which holds the reference to the newly created u_rb_t object |
0 | on success | |
-1 | on error |
Definition at line 153 of file srcs/toolbox/rb.c.
References U_RB_OPT_IMPL_MALLOC.
void * u_rb_fast_read | ( | u_rb_t * | rb, | |
size_t * | pb_sz | |||
) |
Try to read *pb_sz
bytes of data from the ring buffer rb
and return the pointer to the start of data. The U_RB_OPT_USE_CONTIGUOUS_MEM option must have been set when creating rb
.
rb | reference to an already allocated u_rb_t object where data will be read from | |
pb_sz | number of bytes that the caller wants to be read. On successful return (i.e. non NULL ) the value will be filled with the number of bytes actually read. |
NULL
on error (which includes the "no data ready" condition).NULL
is returned, with *pb_sz == 0
. Any other error condition won't touch the supplied *pb_sz
value. Definition at line 278 of file srcs/toolbox/rb.c.
void u_rb_free | ( | u_rb_t * | rb | ) |
Dispose the previously allocated u_rb_t object rb
rb | reference to the u_rb_t object that must be disposed |
Definition at line 176 of file srcs/toolbox/rb.c.
ssize_t u_rb_read | ( | u_rb_t * | rb, | |
void * | b, | |||
size_t | b_sz | |||
) |
Try to read b_sz
bytes of data from the ring buffer rb
and copy it to b
rb | reference to an already allocated u_rb_t object where data will be read from | |
b | reference to the memory block where data will be copied (must be pre-allocated by the caller and of b_sz bytes at least) | |
b_sz | number of bytes that the caller wants to be copied into b |
Definition at line 244 of file srcs/toolbox/rb.c.
size_t u_rb_ready | ( | u_rb_t * | rb | ) |
Return the number of bytes ready to be consumed for the supplied u_rb_t object rb
rb | reference to an already allocated u_rb_t object |
0
) Definition at line 313 of file srcs/toolbox/rb.c.
size_t u_rb_size | ( | u_rb_t * | rb | ) |
Return the real size (as possibly rounded by the u_rb_create routine) of the supplied u_rb_t object rb
rb | reference to an already allocated u_rb_t object |
Definition at line 193 of file srcs/toolbox/rb.c.
ssize_t u_rb_write | ( | u_rb_t * | rb, | |
const void * | b, | |||
size_t | b_sz | |||
) |
Try to write b_sz
bytes of data from the memory block b
to the u_rb_t object rb
rb | reference to an already allocated u_rb_t object where data will be written to | |
b | reference to the memory block which will be copied-in | |
b_sz | number of bytes starting from b that the caller wants to be copied into rb |
Definition at line 213 of file srcs/toolbox/rb.c.