From b53db4c792444b4b3acea377a1fe2381b8eec4d9 Mon Sep 17 00:00:00 2001 From: miha_vitorovic Date: Thu, 11 Nov 2010 14:03:53 +0100 Subject: [PATCH] GrowingCircularBuffer added and tested. --- configure/RELEASE | 2 +- pvAccessApp/testUtils/Makefile | 3 + .../testUtils/growingCircularBufferTest.cpp | 50 ++++++ pvAccessApp/utils/Makefile | 3 +- pvAccessApp/utils/growingCircularBuffer.h | 152 ++++++++++++++++++ 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 pvAccessApp/testUtils/growingCircularBufferTest.cpp create mode 100644 pvAccessApp/utils/growingCircularBuffer.h diff --git a/configure/RELEASE b/configure/RELEASE index 4a040e9..119108e 100644 --- a/configure/RELEASE +++ b/configure/RELEASE @@ -25,7 +25,7 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top #SNCSEQ=$(EPICS_BASE)/../modules/soft/seq # EPICS_BASE usually appears last so other apps can override stuff: -EPICS_BASE=/Users/msekoranja/Work/EPICS/base-3.14.11 +EPICS_BASE=/opt/epics/base # Set RULES here if you want to take build rules from somewhere # other than EPICS_BASE: diff --git a/pvAccessApp/testUtils/Makefile b/pvAccessApp/testUtils/Makefile index 58d8f96..0a5f1d9 100644 --- a/pvAccessApp/testUtils/Makefile +++ b/pvAccessApp/testUtils/Makefile @@ -14,6 +14,9 @@ PROD_HOST += arrayFIFOTest arrayFIFOTest_SRCS += arrayFIFOTest.cpp arrayFIFOTest_LIBS += pvAccUtils Com +PROD_HOST += growingCircularBufferTest +growingCircularBufferTest_SRCS += growingCircularBufferTest.cpp +growingCircularBufferTest_LIBS += pvAccUtils Com include $(TOP)/configure/RULES #---------------------------------------- diff --git a/pvAccessApp/testUtils/growingCircularBufferTest.cpp b/pvAccessApp/testUtils/growingCircularBufferTest.cpp new file mode 100644 index 0000000..933a006 --- /dev/null +++ b/pvAccessApp/testUtils/growingCircularBufferTest.cpp @@ -0,0 +1,50 @@ +/* + * growingCircularBufferTest.cpp + * + * Created on: Nov 11, 2010 + * Author: Miha Vitorovic + */ + +#include "growingCircularBuffer.h" + +#include +#include + +using namespace epics::pvAccess; +using std::cout; +using std::endl; + +const int CAPACITY = 10; + +int main(int argc, char *argv[]) { + GrowingCircularBuffer cb(CAPACITY); + + cout<<"Testing circular buffer."< + +using epics::pvData::BaseException; + +namespace epics { + namespace pvAccess { + + /** + * 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) : + _takePointer(0), _putPointer(0), _count(0), _size(capacity), + _elements(new T[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] = x; + if (++_putPointer >= _size) _putPointer = 0; + return _count == 1; + + } + + template + T GrowingCircularBuffer::extract() { + if(_count==0) THROW_BASE_EXCEPTION("Buffer empty."); + + _count--; + T old = _elements[_takePointer]; + if(++_takePointer>=_size) _takePointer = 0; + return old; + } + + } +} +#endif /* GROWINGCIRCULARBUFFER_H_ */