[common] ringbuffer: add pre value overwrite callback

This allows us to set a callback to read a value out before it's about
to be overwritten which can be useful for things like calculating a
running average.
This commit is contained in:
Geoffrey McRae 2021-07-18 20:42:29 +10:00
parent 42d8f31eba
commit 45e1b5bce0
2 changed files with 25 additions and 1 deletions

View File

@ -24,6 +24,7 @@
typedef struct RingBuffer * RingBuffer;
RingBuffer ringbuffer_new(int length, size_t valueSize);
void ringbuffer_free(RingBuffer * rb);
void ringbuffer_push(RingBuffer rb, const void * value);
void ringbuffer_reset(RingBuffer rb);
@ -33,6 +34,12 @@ int ringbuffer_getStart (const RingBuffer rb);
int ringbuffer_getCount (const RingBuffer rb);
void * ringbuffer_getValues(const RingBuffer rb);
typedef void (*RingBufferValueFn)(void * value, void * udata);
// set a function to call before a value is about to be overwritten
void ringbuffer_setPreOverwriteFn(RingBuffer rb, RingBufferValueFn fn,
void * udata);
typedef bool (*RingBufferIterator)(int index, void * value, void * udata);
void ringbuffer_forEach(const RingBuffer rb, RingBufferIterator fn,
void * udata);

View File

@ -25,6 +25,9 @@
struct RingBuffer
{
RingBufferValueFn preOverwriteFn;
void * preOverwriteUdata;
int length;
size_t valueSize;
int start, pos, count;
@ -50,13 +53,20 @@ void ringbuffer_free(RingBuffer * rb)
void ringbuffer_push(RingBuffer rb, const void * value)
{
void * dst = rb->values + rb->pos * rb->valueSize;
if (rb->count < rb->length)
++rb->count;
else
{
if (++rb->start == rb->length)
rb->start = 0;
memcpy(rb->values + rb->pos * rb->valueSize, value, rb->valueSize);
if (rb->preOverwriteFn)
rb->preOverwriteFn(dst, rb->preOverwriteUdata);
}
memcpy(dst, value, rb->valueSize);
if (++rb->pos == rb->length)
rb->pos = 0;
@ -89,6 +99,13 @@ void * ringbuffer_getValues(const RingBuffer rb)
return rb->values;
}
void ringbuffer_setPreOverwriteFn(const RingBuffer rb, RingBufferValueFn fn,
void * udata)
{
rb->preOverwriteFn = fn;
rb->preOverwriteUdata = udata;
}
void ringbuffer_forEach(const RingBuffer rb, RingBufferIterator fn, void * udata)
{
int index = rb->start;