lpcware

RingBuffer library, suggestion for V2.13

Discussion created by lpcware Employee on Jun 15, 2016
Content originally posted in LPCWare by mch0 on Tue Sep 09 06:43:52 MST 2014
Hello,

I would like to propose an addition to the current ringbuffer library.
A ringbuffer naturally must wrap around at some address and there is no problem with the library.
However, there are at least two other libraries (USB and LWIP) which can use linear memory space only or very efficiently (zero copy model).
If you want to combine the two libraries it is necessary to know the number of bytes in the ringbuffer that can be accessed in a linear fashion, i.e. before the wrap.

For example, in my application, I "printf()" into a ringbuffer and likewise "scanf()" from another ringbuffer.
On the other side of each ringbuffer I can attach different channels for input/output. Currently these include USB, the UARTs and Ethernet via LWIP. All channels tested and working so far.

Now LWIP wants to copy from/to a linear buffer, no matter if you use zero-copy or not.
To achieve this I have added the following code to the ringbuffer library (note that I have not modified any existing code):

**
* @briefReturn number of bytes in the ring buffer that can be retrieved in ascending linear order from tail
* @paramRingBuff: Pointer to ring buffer
* @returnNumber of bytes in linear order
*/

int RingBuffer_GetCountLinear(RINGBUFF_T *RingBuff)
{
return MIN(RingBuffer_GetCount(RingBuff),RingBuff->count - RB_INDT(RingBuff));
}

/**
* @briefReturn pointer to tail
* @paramRingBuff: Pointer to ring buffer
* @returnPointer to tail
*/

STATIC INLINE void* RingBuffer_GetTail(RINGBUFF_T *RingBuff)
{
return RingBuff->data+RB_INDT(RingBuff);
}

/**
* @briefMove tail pointer by n bytes (deletes n oldest bytes)
* @paramRingBuff: Pointer to ring buffer
* @paramn: number of bytes to be deleted
* @returnNumber of bytes deleted
*/

int RingBuffer_MoveTail(RINGBUFF_T *RingBuff, int n)
{
if (RingBuffer_GetCount(RingBuff) < n) n=RingBuffer_GetCount(RingBuff);
RingBuff->tail+=n;
return n;
}


These functions now allow me to determine the number of bytes I can read in ascending order. When read, I can discard them from the buffer.

I have tested these fucnctions in my telnet-application.
A use case, here for LWIP, could look like this:


// if the buffer is not empty, then stuff as much as possible into the LWIP buffers again
if (!RingBuffer_IsEmpty(&out.rb))
{
// get number of bytes that can be copied/accessed in ascending order
n=MIN(tcp_sndbuf(lwip_dbg.accepted), RingBuffer_GetCountLinear(&out.rb));

// copy data directly from ringbuffer memory to LWIP memory
tcp_write(lwip_dbg.accepted, RingBuffer_GetTail(&out.rb), n, TCP_WRITE_FLAG_COPY);

// free ringbuffer memory
RingBuffer_MoveTail(&out.rb, n);
}


In this example I do not use the zero-copy strategy, but this is just a matter of deferring the last line to the next callback of data_sent().

Right now I have placed these additional three functions outside the V2.12 ringbuffer libray to keep it in the original state. However, if deemed useful by the LPCOpen developers, I would suggest to include these functions after additional test in the next version.
I think they could be useful for others and they cannot break any existing code.

Best regards,

Mike

Outcomes