freertos/ringbuf: Add an API xRingbufferGetCurFreeSize() to fetch current free size available
The earlier available API (xRingbufferGetMaxItemSize())just gives a static max entry value possible for given ring buffer. There was a feature request for an API which could provide a real time available buffer size. See below: https://github.com/espressif/esp-idf/issues/806 Signed-off-by: Piyush Shah <piyush@espressif.com>
This commit is contained in:
parent
c4b861ad65
commit
50637f638f
2 changed files with 80 additions and 1 deletions
|
@ -94,6 +94,21 @@ void vRingbufferDelete(RingbufHandle_t ringbuf);
|
|||
*/
|
||||
size_t xRingbufferGetMaxItemSize(RingbufHandle_t ringbuf);
|
||||
|
||||
/**
|
||||
* @brief Get current free size available in the buffer
|
||||
*
|
||||
* This gives the real time free space available in the ring buffer. So basically,
|
||||
* this will be the maximum size of the entry that can be sent into the buffer.
|
||||
*
|
||||
* @note This API is not thread safe. So, if multiple threads are accessing the same
|
||||
* ring buffer, it is the application's responsibility to ensure atomic access to this
|
||||
* API and the subsequent Send
|
||||
*
|
||||
* @param ringbuf - Ring buffer to query
|
||||
*
|
||||
* @return Current free size, in bytes, available for an entry
|
||||
*/
|
||||
size_t xRingbufferGetCurFreeSize(RingbufHandle_t ringbuf);
|
||||
|
||||
/**
|
||||
* @brief Insert an item into the ring buffer
|
||||
|
|
|
@ -53,6 +53,7 @@ struct ringbuf_t {
|
|||
BaseType_t (*copyItemToRingbufImpl)(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size);
|
||||
uint8_t *(*getItemFromRingbufImpl)(ringbuf_t *rb, size_t *length, int wanted_length);
|
||||
void (*returnItemToRingbufImpl)(ringbuf_t *rb, void *item);
|
||||
size_t (*getFreeSizeImpl)(ringbuf_t *rb);
|
||||
};
|
||||
|
||||
|
||||
|
@ -82,7 +83,6 @@ static int ringbufferFreeMem(ringbuf_t *rb)
|
|||
return free_size-1;
|
||||
}
|
||||
|
||||
|
||||
//Copies a single item to the ring buffer; refuses to split items. Assumes there is space in the ringbuffer and
|
||||
//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on
|
||||
//success, pdFALSE if it can't make the item fit and the calling routine needs to retry
|
||||
|
@ -415,6 +415,67 @@ void xRingbufferPrintInfo(RingbufHandle_t ringbuf)
|
|||
}
|
||||
|
||||
|
||||
size_t xRingbufferGetCurFreeSize(RingbufHandle_t ringbuf)
|
||||
{
|
||||
ringbuf_t *rb=(ringbuf_t *)ringbuf;
|
||||
configASSERT(rb);
|
||||
configASSERT(rb->getFreeSizeImpl);
|
||||
int free_size = rb->getFreeSizeImpl(rb);
|
||||
//Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation
|
||||
//where read_ptr == free_ptr, messing up the next calculation.
|
||||
return free_size - 1;
|
||||
}
|
||||
|
||||
static size_t getCurFreeSizeByteBuf(ringbuf_t *rb)
|
||||
{
|
||||
//Return whatever space is available depending on relative positions of
|
||||
//the free pointer and write pointer. There is no overhead of headers in
|
||||
//this mode
|
||||
int free_size = rb->free_ptr-rb->write_ptr;
|
||||
if (free_size <= 0)
|
||||
free_size += rb->size;
|
||||
return free_size;
|
||||
}
|
||||
|
||||
static size_t getCurFreeSizeAllowSplit(ringbuf_t *rb)
|
||||
{
|
||||
int free_size;
|
||||
//If Both, the write and free pointer are at the start. Hence, the entire buffer
|
||||
//is available (minus the space for the header)
|
||||
if (rb->write_ptr == rb->free_ptr && rb->write_ptr == rb->data) {
|
||||
free_size = rb->size - sizeof(buf_entry_hdr_t);
|
||||
} else if (rb->write_ptr < rb->free_ptr) {
|
||||
//Else if the free pointer is beyond the write pointer, only the space between
|
||||
//them would be available (minus the space for the header)
|
||||
free_size = rb->free_ptr - rb->write_ptr - sizeof(buf_entry_hdr_t);
|
||||
} else {
|
||||
//Else the data can wrap around and 2 headers will be required
|
||||
free_size = rb->free_ptr - rb->write_ptr + rb->size - (2 * sizeof(buf_entry_hdr_t));
|
||||
}
|
||||
return free_size;
|
||||
}
|
||||
|
||||
static size_t getCurFreeSizeNoSplit(ringbuf_t *rb)
|
||||
{
|
||||
int free_size;
|
||||
//If the free pointer is beyond the write pointer, only the space between
|
||||
//them would be available
|
||||
if (rb->write_ptr < rb->free_ptr) {
|
||||
free_size = rb->free_ptr - rb->write_ptr;
|
||||
} else {
|
||||
//Else check which one is bigger amongst the below 2
|
||||
//1) Space from the write pointer to the end of buffer
|
||||
int size1 = rb->data + rb->size - rb->write_ptr;
|
||||
//2) Space from the start of buffer to the free pointer
|
||||
int size2 = rb->free_ptr - rb->data;
|
||||
//And then select the larger of the two
|
||||
free_size = size1 > size2 ? size1 : size2;
|
||||
}
|
||||
//In any case, a single header will be used, so subtracting the space that
|
||||
//would be required for it
|
||||
return free_size - sizeof(buf_entry_hdr_t);
|
||||
}
|
||||
|
||||
|
||||
RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type)
|
||||
{
|
||||
|
@ -437,6 +498,7 @@ RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type)
|
|||
rb->returnItemToRingbufImpl=returnItemToRingbufDefault;
|
||||
//Calculate max item size. Worst case, we need to split an item into two, which means two headers of overhead.
|
||||
rb->maxItemSize=rb->size-(sizeof(buf_entry_hdr_t)*2)-4;
|
||||
rb->getFreeSizeImpl=getCurFreeSizeAllowSplit;
|
||||
} else if (type==RINGBUF_TYPE_BYTEBUF) {
|
||||
rb->flags|=flag_bytebuf;
|
||||
rb->copyItemToRingbufImpl=copyItemToRingbufByteBuf;
|
||||
|
@ -444,6 +506,7 @@ RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type)
|
|||
rb->returnItemToRingbufImpl=returnItemToRingbufBytebuf;
|
||||
//Calculate max item size. We have no headers and can split anywhere -> size is total size minus one.
|
||||
rb->maxItemSize=rb->size-1;
|
||||
rb->getFreeSizeImpl=getCurFreeSizeByteBuf;
|
||||
} else if (type==RINGBUF_TYPE_NOSPLIT) {
|
||||
rb->copyItemToRingbufImpl=copyItemToRingbufNoSplit;
|
||||
rb->getItemFromRingbufImpl=getItemFromRingbufDefault;
|
||||
|
@ -453,6 +516,7 @@ RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type)
|
|||
//(item_data-4) bytes of buffer, then we only have (size-(item_data-4) bytes left to fill
|
||||
//with the real item. (item size being header+data)
|
||||
rb->maxItemSize=(rb->size/2)-sizeof(buf_entry_hdr_t)-4;
|
||||
rb->getFreeSizeImpl=getCurFreeSizeNoSplit;
|
||||
} else {
|
||||
configASSERT(0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue