Ring Buffer


Overview

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.

Note:

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.

Enumeration Type Documentation

Enumerator:
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.

Definition at line 32 of file rb.h.


Function Documentation

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.

Parameters:
rb reference to an already allocated u_rb_t object
Returns:
the number of bytes that can be u_rb_write'd before old data starts being overwritten

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

Parameters:
rb reference to an already allocated u_rb_t object
Return values:
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.

Parameters:
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
Return values:
0 on success
-1 on error
Note:
We try to use the mmap-based implementation whenever possible.

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.

Parameters:
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.
Returns:
the address to the start of read data, or NULL on error (which includes the "no data ready" condition).
Note:
In case there is no data ready to be read a 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

Parameters:
rb reference to the u_rb_t object that must be disposed
Returns:
nothing

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

Parameters:
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
Returns:
the number of bytes actually read from the ring buffer (may be less than the requested size)

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

Parameters:
rb reference to an already allocated u_rb_t object
Returns:
the number of bytes ready to be consumed (could be 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

Parameters:
rb reference to an already allocated u_rb_t object
Returns:
the size in bytes of the ring buffer

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

Parameters:
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
Returns:
the number of bytes actually written to the ring buffer (may be less than the requested size)

Definition at line 213 of file srcs/toolbox/rb.c.


←Products
© 2005-2012 - KoanLogic S.r.l. - All rights reserved