Introduction.
The IOBuf is a simple implementation of a ring buffer. It is used by several HAL modules and can also be used as a general-purpose buffer by the application.
Inside IOBuf.
The IOBuf consists of a descriptor and memory space (pool) used for storing data. The descriptor holds all the information needed for IOBuf to operate. The IOBuf stores elements of data. A signle element is an array of bytes. The bytesize of an element is fixed for every IOBuf during initialization. Typical examples of elements are bytes (bytesize is simply one), but it could also be pointers or structures.
Using IOBufs.
The IOBuf object must be declared or created at runtime by a call to IOBUF_Create. To declare IOBuf at compile time you must provide the memory pool. The buffer must be then initialized by a call to IOBUF_Init. The following code declares a buffer for 2-byte elements. The IOBuf descriptor is placed on top of the memory pool, so the actual memory pool size is sizeof(IOBufDesc) less.
char iobuf_pool[100];
IOBUF iobuf;
To create IOBuf at runtime you need a dynamic memory manager (see also notes below). Then all you need to do is call IOBUF_Create. You DO NOT call IOBUF_Init as the buffer is already initialized. The following example allocates a buffer for maximum of 10 elements, each of bytesize 2.
To destroy it you must call IOBUF_Destroy.
The buffer can be written by a call to IOBUF_Write and read from by a call to IOBUF_Read. The IOBUF_GetCount function returns the number of elements currently stored in the buffer. The IOBUF_GetSpace function returns the number of elements that can still fit into the buffer.
Dynamic memory and IOBufs.
Creating and destroying dynamic IOBufs requires dynamic memory manager. You can select one in your config.h in the HEAP module section.
|
typedef size_t | iobuf_size_t |
|
typedef struct IOBufDesc * | IOBuf |
|
|
IOBuf | IOBUF_Create (iobuf_size_t elem_size, iobuf_size_t max_elem_count) |
|
IOBuf | IOBUF_Destroy (IOBuf iobuf) |
|
iobuf_size_t | IOBUF_GetCount (IOBuf iobuf) |
|
iobuf_size_t | IOBUF_GetSpace (IOBuf iobuf) |
|
iobuf_size_t | IOBUF_GetSize (IOBuf iobuf) |
|
IOBuf | IOBUF_Init (void *buf_ptr, iobuf_size_t buf_size, iobuf_size_t elem_size) |
|
iobuf_size_t | IOBUF_Read (IOBuf iobuf, void *data, iobuf_size_t elem_count) |
|
iobuf_size_t | IOBUF_Write (IOBuf iobuf, const void *data, iobuf_size_t elem_count) |
|
iobuf_size_t | IOBUF_ReadNextFragment (IOBuf iobuf, iobuf_size_t fragment_size, void **next_fragment_ptr, iobuf_size_t *next_fragment_size) |
|
iobuf_size_t | IOBUF_WriteNextFragment (IOBuf iobuf, iobuf_size_t fragment_size, void **next_fragment_ptr, iobuf_size_t *next_fragment_size) |
|
iobuf_size_t | IOBUF_ReadFast (IOBuf iobuf, void *elem) |
|
iobuf_size_t | IOBUF_WriteFast (IOBuf iobuf, const void *elem) |
|
void | IOBUF_Clear (IOBuf iobuf) |
|
iobuf_size_t | IOBUF_Peek (IOBuf iobuf, void *data, iobuf_size_t elem_count) |
|
iobuf_size_t | IOBUF_Move (IOBuf dst_iobuf, IOBuf src_iobuf, iobuf_size_t elem_count) |
|
iobuf_size_t | IOBUF_Remove (IOBuf iobuf, iobuf_size_t elem_count) |
|
#define IOBUF_DECLARE |
( |
|
name, |
|
|
|
count, |
|
|
|
size |
|
) |
| |
Value:static uint8_t name##_mempool[(count)*(size)]; \
static
IOBufDesc name = { 0, size, count, &name##_mempool, &name##_mempool, &name##_mempool };
Definition: hal_iobuf.h:88
Macro that declares a static IOBuffer
IOBuf IOBUF_Create |
( |
iobuf_size_t |
elem_size, |
|
|
iobuf_size_t |
max_elem_count |
|
) |
| |
Creates a buffer. Allocates the memory for the buffer and its descriptor.
- Returns
- handle of the created buffer or NULL, if there were errors.
- Parameters
-
elem_size | size in bytes of asingle element that can be stored in a buffer |
max_elem_count | maximum number of elements that the buffer can store (size of bufer) |
Destroys a buffer, freeing memory for the buffer pool and the descriptor.
- Parameters
-
iobuf | handle of the buffer to destroy |
iobuf_size_t IOBUF_GetCount |
( |
IOBuf |
iobuf | ) |
|
Returns the number of elements stored in a buffer.
- Parameters
-
iobuf | handle of the buffer |
iobuf_size_t IOBUF_GetSpace |
( |
IOBuf |
iobuf | ) |
|
Returns the number of elements that can still be written to a buffer.
- Returns
- actual number of elements that can be written or 0, if the buffer handle is invalid or buffer is full.
- Parameters
-
iobuf | handle of the buffer |
iobuf_size_t IOBUF_GetSize |
( |
IOBuf |
iobuf | ) |
|
Returns the total number of elements that the buffer can store (buffer capacity).
- Returns
- buffer capacity
- Parameters
-
iobuf | handle of the buffer |
IOBuf IOBUF_Init |
( |
void * |
buf_ptr, |
|
|
iobuf_size_t |
buf_size, |
|
|
iobuf_size_t |
elem_size |
|
) |
| |
Initializes a buffer inside the specified memory area, allowing static memory allocation. This area must be big enough to hold the iobuf memory pool and the iobuf descriptor. The actual memory usage for the buffer is elem_size * buf_count + sizeof(IOBufDesc). The buffer descriptor is placed at the beginning of the specified memory area, so after successful initialization, the returned handle will be the same as buf_ptr.
- Returns
- handle of a newly initialized buffer or NULL if initialization failed
- Parameters
-
buf_ptr | pointer to a memory area that will be used by the buffer |
buf_size | size of the memory area |
elem_size | size in bytes of a single element in the buffer |
iobuf_size_t IOBUF_Read |
( |
IOBuf |
iobuf, |
|
|
void * |
data, |
|
|
iobuf_size_t |
elem_count |
|
) |
| |
Reads a specified number of elements from a buffer. The data is copied from the buffer's internal memory pool to the destination space, pointed by the data parameter.
- Returns
- number of elements actually read
- Parameters
-
iobuf | handle of the buffer |
data | pointer to the destination space |
elem_count | number of elements to read |
iobuf_size_t IOBUF_Write |
( |
IOBuf |
iobuf, |
|
|
const void * |
data, |
|
|
iobuf_size_t |
elem_count |
|
) |
| |
Writes a specified number of elements to a buffer. The data is copied from the provided source space to the buffer's internal memory pool.
- Returns
- number of elements actually written
- Parameters
-
iobuf | handle of the buffer |
data | pointer to the source data |
elem_count | number of elements to write |
iobuf_size_t IOBUF_ReadNextFragment |
( |
IOBuf |
iobuf, |
|
|
iobuf_size_t |
fragment_size, |
|
|
void ** |
next_fragment_ptr, |
|
|
iobuf_size_t * |
next_fragment_size |
|
) |
| |
Reads a portion of data from a buffer by returning a pointer to the next fragment of data. This function differs from IOBUF_Read, because in this case there is no data copying. This function gives out a pointer to sequential memory blocks from the buffer's internal memory pool, and acts like the caller actualy read it (by progressing buffer's internal read mark).
This function tries to read as much as possible at once. This means, that it will try to read max_fragment_size elements. However, this may not be possible for two reasons:
- the buffer stores less elements (obvious)
- the requested data wraps around the buffer's internal memory pool (that's because of the ring-nature of the buffer)
In the second case, the requested data is actually split in the memory, and no consistent memory block can be returned. Only the first data block will be returned, the second one will be read during the next function call, even though it stored in the buffer already.
- Parameters
-
iobuf | handle of the buffer |
fragment_size | specifies the maximum amount of elements that can be read by this call (the requested data size) |
next_fragment_ptr | pointer to a variable, where a pointer to the next portion of data to read will be stored |
next_fragment_size | pointer to a variable, where the size of the next portion of data to read will be stored |
iobuf_size_t IOBUF_WriteNextFragment |
( |
IOBuf |
iobuf, |
|
|
iobuf_size_t |
fragment_size, |
|
|
void ** |
next_fragment_ptr, |
|
|
iobuf_size_t * |
next_fragment_size |
|
) |
| |
Allows to write data directly to the buffer's internal memory pool avoiding in some cases the unnecessary data copying, while still operating in the ring-buffer fashion. This function gets a pointer and size of the memory block and acts as it was actually written (by progressing buffer's internal write mark). By using this function, the caller actually requests sequential blocks of space in the ring-buffer.
This function tries to get as much space as possible at once. This means, that it will try to get space for fragment_size elements. However, this may not be possible for two reasons:
- the buffer capacity is exceeded (obvious)
- the requested data space wraps around the buffer's internal memory pool (that's because of the ring-nature of the buffer)
In the second case, the requested data space is actually split in the memory, and no consistent memory block can be requested. Only the first data block will be returned, the second one will be returned during the next function call, even though it may be ready in the buffer.
- Parameters
-
iobuf | handle of the buffer |
fragment_size | specifies the amount of elements that the caller wants to write to the buffer |
next_fragment_ptr | pointer to a variable, where a pointer to the next available data chunk will be stored |
next_fragment_size | pointer to a variable, where the size of the available data chunk will be stored. This can be less or equal to the fragment_size parameter. |
iobuf_size_t IOBUF_ReadFast |
( |
IOBuf |
iobuf, |
|
|
void * |
elem |
|
) |
| |
Reads a single element from a buffer, without utilizing any critical sections (fast call). This function is only safe to call when global interrupts are disabled, in example inside non-nestable interrupt service routine.
- Parameters
-
iobuf | handle of the buffer |
elem | destination buffer |
- Returns
- number of element read (0 or 1)
iobuf_size_t IOBUF_WriteFast |
( |
IOBuf |
iobuf, |
|
|
const void * |
elem |
|
) |
| |
Writes a single element to a buffer, without utilizing any critical sections (fast call). This function is only safe to call when global interrupts are disabled, in example inside non-nestable interrupt service routine.
- Parameters
-
iobuf | handle of the buffer |
elem | source data buffer |
- Returns
- number of element written (0 or 1)
void IOBUF_Clear |
( |
IOBuf |
iobuf | ) |
|
Clears the content stored in the buffer, making it return to initial state.
- Parameters
-
iobuf | handle of the buffer |
iobuf_size_t IOBUF_Peek |
( |
IOBuf |
iobuf, |
|
|
void * |
data, |
|
|
iobuf_size_t |
elem_count |
|
) |
| |
Reads a specified number of elements from a buffer, but without altering the state of the buffer. The data read is not removed from the buffer. This means that two sequential calls will return the same data. The data is copied from the buffer's internal memory pool to the destination space, pointed by the data parameter.
- Returns
- number of elements actually read
- Parameters
-
iobuf | handle of the buffer |
data | pointer to the destination space |
elem_count | number of elements to read |
iobuf_size_t IOBUF_Move |
( |
IOBuf |
dst_iobuf, |
|
|
IOBuf |
src_iobuf, |
|
|
iobuf_size_t |
elem_count |
|
) |
| |
Moves a specified number of elements from the source buffer into the destination buffer. It may fail to move the desired number of elements due to:
- destination buffer overrun
- source buffer underrun In any of the above cases, this function will move as much data as possible.
- Returns
- number of elements actually moved
- Parameters
-
dst_iobuf | handle of the destination buffer |
src_iobuf | handle of the source buffer |
elem_count | number of elements to move |
iobuf_size_t IOBUF_Remove |
( |
IOBuf |
iobuf, |
|
|
iobuf_size_t |
elem_count |
|
) |
| |
Removes a specified number of elements from a buffer. The data is removed from the buffer's internal memory pool and discarded.
- Returns
- number of elements actually removed
- Parameters
-
iobuf | handle of the buffer |
elem_count | number of elements to remove |