[common] ringbuffer: added shift and locking for thread safety

This commit is contained in:
Geoffrey McRae 2021-12-24 18:41:33 +11:00
parent d69069fb09
commit 8ba4b56dba
2 changed files with 26 additions and 2 deletions

View File

@ -27,6 +27,7 @@ RingBuffer ringbuffer_new(int length, size_t valueSize);
void ringbuffer_free(RingBuffer * rb); void ringbuffer_free(RingBuffer * rb);
void ringbuffer_push(RingBuffer rb, const void * value); void ringbuffer_push(RingBuffer rb, const void * value);
bool ringbuffer_shift(RingBuffer rb, void * dst);
void ringbuffer_reset(RingBuffer rb); void ringbuffer_reset(RingBuffer rb);
int ringbuffer_getLength(const RingBuffer rb); int ringbuffer_getLength(const RingBuffer rb);

View File

@ -19,6 +19,7 @@
*/ */
#include "common/ringbuffer.h" #include "common/ringbuffer.h"
#include "common/locking.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -30,6 +31,7 @@ struct RingBuffer
int length; int length;
size_t valueSize; size_t valueSize;
LG_Lock lock;
int start, pos, count; int start, pos, count;
char values[0]; char values[0];
}; };
@ -39,6 +41,7 @@ RingBuffer ringbuffer_new(int length, size_t valueSize)
struct RingBuffer * rb = calloc(1, sizeof(*rb) + valueSize * length); struct RingBuffer * rb = calloc(1, sizeof(*rb) + valueSize * length);
rb->length = length; rb->length = length;
rb->valueSize = valueSize; rb->valueSize = valueSize;
LG_LOCK_INIT(rb->lock);
return rb; return rb;
} }
@ -47,14 +50,15 @@ void ringbuffer_free(RingBuffer * rb)
if (!*rb) if (!*rb)
return; return;
LG_LOCK_FREE(rb->lock);
free(*rb); free(*rb);
*rb = NULL; *rb = NULL;
} }
void ringbuffer_push(RingBuffer rb, const void * value) void ringbuffer_push(RingBuffer rb, const void * value)
{ {
LG_LOCK(rb->lock);
void * dst = rb->values + rb->pos * rb->valueSize; void * dst = rb->values + rb->pos * rb->valueSize;
if (rb->count < rb->length) if (rb->count < rb->length)
++rb->count; ++rb->count;
else else
@ -67,16 +71,33 @@ void ringbuffer_push(RingBuffer rb, const void * value)
} }
memcpy(dst, value, rb->valueSize); memcpy(dst, value, rb->valueSize);
if (++rb->pos == rb->length) if (++rb->pos == rb->length)
rb->pos = 0; rb->pos = 0;
LG_UNLOCK(rb->lock);
}
bool ringbuffer_shift(RingBuffer rb, void * dst)
{
if (rb->count == 0)
return false;
LG_LOCK(rb->lock);
memcpy(dst, rb->values + rb->start * rb->valueSize, rb->valueSize);
--rb->count;
if (++rb->start == rb->length)
rb->start = 0;
LG_UNLOCK(rb->lock);
return true;
} }
void ringbuffer_reset(RingBuffer rb) void ringbuffer_reset(RingBuffer rb)
{ {
LG_LOCK(rb->lock);
rb->start = 0; rb->start = 0;
rb->pos = 0; rb->pos = 0;
rb->count = 0; rb->count = 0;
LG_UNLOCK(rb->lock);
} }
int ringbuffer_getLength(const RingBuffer rb) int ringbuffer_getLength(const RingBuffer rb)
@ -121,6 +142,7 @@ void ringbuffer_setPreOverwriteFn(const RingBuffer rb, RingBufferValueFn fn,
void ringbuffer_forEach(const RingBuffer rb, RingBufferIterator fn, void * udata, void ringbuffer_forEach(const RingBuffer rb, RingBufferIterator fn, void * udata,
bool reverse) bool reverse)
{ {
LG_LOCK(rb->lock);
if (reverse) if (reverse)
{ {
int index = rb->start + rb->count - 1; int index = rb->start + rb->count - 1;
@ -150,4 +172,5 @@ void ringbuffer_forEach(const RingBuffer rb, RingBufferIterator fn, void * udata
break; break;
} }
} }
LG_UNLOCK(rb->lock);
} }