Browse Source

ringbuffer: converted to item_size units

this fixes a number of indexing bugs
sbg
Andrew Tridgell 12 years ago committed by Lorenz Meier
parent
commit
760b3ab2e7
  1. 42
      src/drivers/device/ringbuffer.h

42
src/drivers/device/ringbuffer.h

@ -155,21 +155,21 @@ public:
void print_info(const char *name); void print_info(const char *name);
private: private:
unsigned _ring_size; unsigned _num_items;
const size_t _item_size; const size_t _item_size;
char *_buf; char *_buf;
volatile unsigned _head; /**< insertion point */ volatile unsigned _head; /**< insertion point in _item_size units */
volatile unsigned _tail; /**< removal point */ volatile unsigned _tail; /**< removal point in _item_size units */
unsigned _next(unsigned index); unsigned _next(unsigned index);
}; };
RingBuffer::RingBuffer(unsigned ring_size, size_t item_size) : RingBuffer::RingBuffer(unsigned num_items, size_t item_size) :
_ring_size((ring_size + 1) * item_size), _num_items(num_items),
_item_size(item_size), _item_size(item_size),
_buf(new char[_ring_size]), _buf(new char[(_num_items+1) * item_size]),
_head(ring_size), _head(_num_items),
_tail(ring_size) _tail(_num_items)
{} {}
RingBuffer::~RingBuffer() RingBuffer::~RingBuffer()
@ -181,7 +181,7 @@ RingBuffer::~RingBuffer()
unsigned unsigned
RingBuffer::_next(unsigned index) RingBuffer::_next(unsigned index)
{ {
return (0 == index) ? _ring_size : (index - _item_size); return (0 == index) ? _num_items : (index - 1);
} }
bool bool
@ -199,7 +199,7 @@ RingBuffer::full()
unsigned unsigned
RingBuffer::size() RingBuffer::size()
{ {
return (_buf != nullptr) ? _ring_size : 0; return (_buf != nullptr) ? _num_items : 0;
} }
void void
@ -216,7 +216,7 @@ RingBuffer::put(const void *val, size_t val_size)
if (next != _tail) { if (next != _tail) {
if ((val_size == 0) || (val_size > _item_size)) if ((val_size == 0) || (val_size > _item_size))
val_size = _item_size; val_size = _item_size;
memcpy(&_buf[_head], val, val_size); memcpy(&_buf[_head * _item_size], val, val_size);
_head = next; _head = next;
return true; return true;
} else { } else {
@ -377,7 +377,7 @@ RingBuffer::get(void *val, size_t val_size)
/* go ahead and read from this index */ /* go ahead and read from this index */
if (val != NULL) if (val != NULL)
memcpy(val, &_buf[candidate], val_size); memcpy(val, &_buf[candidate * _item_size], val_size);
/* if the tail pointer didn't change, we got our item */ /* if the tail pointer didn't change, we got our item */
} while (!__sync_bool_compare_and_swap(&_tail, candidate, next)); } while (!__sync_bool_compare_and_swap(&_tail, candidate, next));
@ -466,9 +466,7 @@ RingBuffer::space(void)
tail = _tail; tail = _tail;
} while (head != _head); } while (head != _head);
unsigned reported_space = (tail >= head) ? (_ring_size - (tail - head)) : (head - tail - 1); return (tail >= head) ? (_num_items - (tail - head)) : (head - tail - 1);
return reported_space / _item_size;
} }
unsigned unsigned
@ -478,21 +476,20 @@ RingBuffer::count(void)
* Note that due to the conservative nature of space(), this may * Note that due to the conservative nature of space(), this may
* over-estimate the number of items in the buffer. * over-estimate the number of items in the buffer.
*/ */
return (_ring_size / _item_size) - space(); return _num_items - space();
} }
bool bool
RingBuffer::resize(unsigned new_size) RingBuffer::resize(unsigned new_size)
{ {
unsigned new_ring_size = (new_size + 1) * _item_size;
char *old_buffer; char *old_buffer;
char *new_buffer = new char [new_ring_size]; char *new_buffer = new char [(new_size+1) * _item_size];
if (new_buffer == nullptr) { if (new_buffer == nullptr) {
return false; return false;
} }
old_buffer = _buf; old_buffer = _buf;
_buf = new_buffer; _buf = new_buffer;
_ring_size = new_ring_size; _num_items = new_size;
_head = new_size; _head = new_size;
_tail = new_size; _tail = new_size;
delete[] old_buffer; delete[] old_buffer;
@ -503,5 +500,10 @@ void
RingBuffer::print_info(const char *name) RingBuffer::print_info(const char *name)
{ {
printf("%s %u/%u (%u/%u @ %p)\n", printf("%s %u/%u (%u/%u @ %p)\n",
name, _ring_size/_item_size, _head, _tail, _buf); name,
_num_items,
_num_items * _item_size,
_head,
_tail,
_buf);
} }

Loading…
Cancel
Save