From 44516e8a40c5c8a7d3997de7f6b2111213bb2bff Mon Sep 17 00:00:00 2001 From: miha_vitorovic Date: Mon, 10 Jan 2011 15:37:25 +0100 Subject: [PATCH] GrowingCircularBuffer template specialization for pointers done. --- pvAccessApp/utils/growingCircularBuffer.h | 166 +++++++++++++++++--- testApp/utils/arrayFIFOTest.cpp | 138 ++++++++-------- testApp/utils/growingCircularBufferTest.cpp | 49 +++++- 3 files changed, 261 insertions(+), 92 deletions(-) diff --git a/pvAccessApp/utils/growingCircularBuffer.h b/pvAccessApp/utils/growingCircularBuffer.h index 6a993a1..63bb242 100644 --- a/pvAccessApp/utils/growingCircularBuffer.h +++ b/pvAccessApp/utils/growingCircularBuffer.h @@ -28,8 +28,8 @@ namespace epics { * Create a GrowingCircularBuffer with the given capacity. **/ GrowingCircularBuffer(size_t capacity = 16) : - _elements(new T[capacity]), _takePointer(0), _putPointer(0), _count(0), _size(capacity) - { + _elements(new T[capacity]), _takePointer(0), _putPointer(0), + _count(0), _size(capacity) { } ~GrowingCircularBuffer() { @@ -94,13 +94,9 @@ namespace epics { size_t length); }; - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * g++ requires template definition inside a header file. - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - template - void GrowingCircularBuffer::arraycopy(T* src, size_t srcPos, T* dest, - size_t destPos, size_t length) { + void GrowingCircularBuffer::arraycopy(T* src, size_t srcPos, + T* dest, size_t destPos, size_t length) { if(srcPos=0; i--) dest[destPos+i] = src[srcPos+i]; @@ -111,17 +107,16 @@ namespace epics { template bool GrowingCircularBuffer::insert(const T x) { - if (_count == _size) - { + if(_count==_size) { // we are full, grow by factor 2 - T* newElements = new T[_size * 2]; + T* newElements = new T[_size*2]; // invariant: _takePointer < _size - size_t split = _size - _takePointer; - if (split > 0) - arraycopy(_elements, _takePointer, newElements, 0, split); - if (_takePointer != 0) - arraycopy(_elements, 0, newElements, split, _putPointer); + size_t split = _size-_takePointer; + if(split>0) arraycopy(_elements, _takePointer, newElements, 0, + split); + if(_takePointer!=0) arraycopy(_elements, 0, newElements, split, + _putPointer); _takePointer = 0; _putPointer = _size; @@ -132,8 +127,8 @@ namespace epics { _count++; _elements[_putPointer] = x; - if (++_putPointer >= _size) _putPointer = 0; - return _count == 1; + if(++_putPointer>=_size) _putPointer = 0; + return _count==1; } template @@ -146,6 +141,141 @@ namespace epics { return old; } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Template specialization for pointers. + * Implementation of circular FIFO unbouded buffer. + * Instance is not thread safe. + * @author Miha Vitorovic + */ + template + class GrowingCircularBuffer { + public: + + /** + * Create a GrowingCircularBuffer with the given capacity. + **/ + GrowingCircularBuffer(size_t capacity = 16) : + _elements(new T*[capacity]), _takePointer(0), _putPointer(0), + _count(0), _size(capacity) { + } + + ~GrowingCircularBuffer() { + delete[] _elements; + } + + /** + * Get number of elements in the buffer. + * @return number of elements in the buffer. + */ + inline size_t size() { + return _count; + } + + /** + * Get current buffer capacity. + * @return buffer current capacity. + */ + inline size_t capacity() { + return _size; + } + + /** + * Insert a new element in to the buffer. + * If buffer full the buffer is doubled. + * + * @param x element to insert. + * @return true if first element. + */ + bool insert(const T* x); + + /** + * Extract the oldest element from the buffer. + * @return the oldest element from the buffer. + */ + T* extract(); + + private: + /** + * Array (circular buffer) of elements. + */ + T** _elements; + + /** + * Take (read) pointer. + */ + size_t _takePointer; + + /** + * Put (write) pointer. + */ + size_t _putPointer; + + /** + * Number of elements in the buffer. + */ + size_t _count; + + size_t _size; + + void arraycopy(T** src, size_t srcPos, T** dest, size_t destPos, + size_t length); + }; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * g++ requires template definition inside a header file. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + template + void GrowingCircularBuffer::arraycopy(T** src, size_t srcPos, + T** dest, size_t destPos, size_t length) { + if(srcPos=0; i--) + dest[destPos+i] = src[srcPos+i]; + else + for(size_t i = 0; i + bool GrowingCircularBuffer::insert(const T* x) { + if(_count==_size) { + // we are full, grow by factor 2 + T** newElements = new T*[_size*2]; + + // invariant: _takePointer < _size + size_t split = _size-_takePointer; + if(split>0) arraycopy(_elements, _takePointer, newElements, 0, + split); + if(_takePointer!=0) arraycopy(_elements, 0, newElements, split, + _putPointer); + + _takePointer = 0; + _putPointer = _size; + _size *= 2; + delete[] _elements; + _elements = newElements; + } + _count++; + + _elements[_putPointer] = const_cast(x); + if(++_putPointer>=_size) _putPointer = 0; + return _count==1; + } + + template + T* GrowingCircularBuffer::extract() { + if(_count==0) return NULL; + + _count--; + T* old = _elements[_takePointer]; + if(++_takePointer>=_size) _takePointer = 0; + return old; + } + } } #endif /* GROWINGCIRCULARBUFFER_H_ */ diff --git a/testApp/utils/arrayFIFOTest.cpp b/testApp/utils/arrayFIFOTest.cpp index 88617e1..966d2c1 100644 --- a/testApp/utils/arrayFIFOTest.cpp +++ b/testApp/utils/arrayFIFOTest.cpp @@ -140,7 +140,7 @@ void testSimpleType() { void testPointerType() { cout<<"\nTests for pointer type template."< fifoInt; @@ -148,110 +148,110 @@ void testPointerType() { assert(fifoInt.isEmpty()); cout<<"Testing clear."< cb(CAPACITY); - cout<<"Testing circular buffer."< cb(CAPACITY); + int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20}; + + cout<<"Testing circular buffer pointer type."<