GrowingCircularBuffer template specialization for pointers done.
This commit is contained in:
@@ -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<class T>
|
||||
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos, T* dest,
|
||||
size_t destPos, size_t length) {
|
||||
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos,
|
||||
T* dest, size_t destPos, size_t length) {
|
||||
if(srcPos<destPos) // this takes care of same-buffer copy
|
||||
for(int i = length-1; i>=0; i--)
|
||||
dest[destPos+i] = src[srcPos+i];
|
||||
@@ -111,17 +107,16 @@ namespace epics {
|
||||
|
||||
template<class T>
|
||||
bool GrowingCircularBuffer<T>::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<class T>
|
||||
@@ -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 T>
|
||||
class GrowingCircularBuffer<T*> {
|
||||
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 <code>true</code> 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<class T>
|
||||
void GrowingCircularBuffer<T*>::arraycopy(T** src, size_t srcPos,
|
||||
T** dest, size_t destPos, size_t length) {
|
||||
if(srcPos<destPos) // this takes care of same-buffer copy
|
||||
for(int i = length-1; i>=0; i--)
|
||||
dest[destPos+i] = src[srcPos+i];
|
||||
else
|
||||
for(size_t i = 0; i<length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool GrowingCircularBuffer<T*>::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<T*>(x);
|
||||
if(++_putPointer>=_size) _putPointer = 0;
|
||||
return _count==1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* GrowingCircularBuffer<T*>::extract() {
|
||||
if(_count==0) return NULL;
|
||||
|
||||
_count--;
|
||||
T* old = _elements[_takePointer];
|
||||
if(++_takePointer>=_size) _takePointer = 0;
|
||||
return old;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* GROWINGCIRCULARBUFFER_H_ */
|
||||
|
||||
@@ -140,7 +140,7 @@ void testSimpleType() {
|
||||
void testPointerType() {
|
||||
cout<<"\nTests for pointer type template."<<endl;
|
||||
|
||||
int buffer[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
|
||||
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
|
||||
|
||||
ArrayFIFO<int*> fifoInt;
|
||||
|
||||
@@ -148,110 +148,110 @@ void testPointerType() {
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing clear."<<endl;
|
||||
fifoInt.push(&buffer[3]);
|
||||
fifoInt.push(&testVals[3]);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
fifoInt.clear();
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing push/pop."<<endl;
|
||||
fifoInt.push(&buffer[5]);
|
||||
fifoInt.push(&buffer[6]);
|
||||
fifoInt.push(&buffer[7]);
|
||||
fifoInt.push(&testVals[5]);
|
||||
fifoInt.push(&testVals[6]);
|
||||
fifoInt.push(&testVals[7]);
|
||||
assert(fifoInt.size()==3);
|
||||
|
||||
assert(fifoInt.pop()==&buffer[7]);
|
||||
assert(fifoInt.pop()==&testVals[7]);
|
||||
assert(fifoInt.size()==2);
|
||||
|
||||
assert(fifoInt.pop()==&buffer[6]);
|
||||
assert(fifoInt.pop()==&testVals[6]);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
assert(fifoInt.pop()==&buffer[5]);
|
||||
assert(fifoInt.pop()==&testVals[5]);
|
||||
assert(fifoInt.size()==0);
|
||||
|
||||
cout<<"Testing FIFO ops (first/last)."<<endl;
|
||||
fifoInt.addFirst(&buffer[1]);
|
||||
fifoInt.addFirst(&buffer[2]);
|
||||
fifoInt.addFirst(&buffer[3]);
|
||||
fifoInt.addFirst(&buffer[4]);
|
||||
fifoInt.addFirst(&buffer[5]);
|
||||
fifoInt.addFirst(&testVals[1]);
|
||||
fifoInt.addFirst(&testVals[2]);
|
||||
fifoInt.addFirst(&testVals[3]);
|
||||
fifoInt.addFirst(&testVals[4]);
|
||||
fifoInt.addFirst(&testVals[5]);
|
||||
|
||||
assert(fifoInt.size()==5);
|
||||
assert(fifoInt.pollLast()==&buffer[1]);
|
||||
assert(fifoInt.pollLast()==&buffer[2]);
|
||||
assert(fifoInt.pollLast()==&buffer[3]);
|
||||
assert(fifoInt.pollLast()==&buffer[4]);
|
||||
assert(fifoInt.pollLast()==&buffer[5]);
|
||||
assert(fifoInt.pollLast()==&testVals[1]);
|
||||
assert(fifoInt.pollLast()==&testVals[2]);
|
||||
assert(fifoInt.pollLast()==&testVals[3]);
|
||||
assert(fifoInt.pollLast()==&testVals[4]);
|
||||
assert(fifoInt.pollLast()==&testVals[5]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing FIFO ops (last/first)."<<endl;
|
||||
fifoInt.addLast(&buffer[7]);
|
||||
fifoInt.addLast(&buffer[8]);
|
||||
fifoInt.addLast(&buffer[9]);
|
||||
fifoInt.addLast(&buffer[10]);
|
||||
fifoInt.addLast(&buffer[11]);
|
||||
fifoInt.addLast(&testVals[7]);
|
||||
fifoInt.addLast(&testVals[8]);
|
||||
fifoInt.addLast(&testVals[9]);
|
||||
fifoInt.addLast(&testVals[10]);
|
||||
fifoInt.addLast(&testVals[11]);
|
||||
assert(fifoInt.size()==5);
|
||||
|
||||
assert(fifoInt.pollFirst()==&buffer[7]);
|
||||
assert(fifoInt.pollFirst()==&buffer[8]);
|
||||
assert(fifoInt.pollFirst()==&buffer[9]);
|
||||
assert(fifoInt.pollFirst()==&buffer[10]);
|
||||
assert(fifoInt.pollFirst()==&buffer[11]);
|
||||
assert(fifoInt.pollFirst()==&testVals[7]);
|
||||
assert(fifoInt.pollFirst()==&testVals[8]);
|
||||
assert(fifoInt.pollFirst()==&testVals[9]);
|
||||
assert(fifoInt.pollFirst()==&testVals[10]);
|
||||
assert(fifoInt.pollFirst()==&testVals[11]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing remove, peek."<<endl;
|
||||
fifoInt.addFirst(&buffer[1]);
|
||||
fifoInt.addFirst(&buffer[2]);
|
||||
fifoInt.addFirst(&buffer[3]);
|
||||
fifoInt.addFirst(&buffer[4]);
|
||||
fifoInt.addFirst(&buffer[5]);
|
||||
fifoInt.addFirst(&buffer[6]);
|
||||
fifoInt.addFirst(&buffer[7]);
|
||||
fifoInt.addFirst(&testVals[1]);
|
||||
fifoInt.addFirst(&testVals[2]);
|
||||
fifoInt.addFirst(&testVals[3]);
|
||||
fifoInt.addFirst(&testVals[4]);
|
||||
fifoInt.addFirst(&testVals[5]);
|
||||
fifoInt.addFirst(&testVals[6]);
|
||||
fifoInt.addFirst(&testVals[7]);
|
||||
// - - - - - - - - - - - -
|
||||
fifoInt.addFirst(&buffer[8]);
|
||||
fifoInt.addFirst(&buffer[9]);
|
||||
fifoInt.addFirst(&buffer[10]);
|
||||
fifoInt.addFirst(&testVals[8]);
|
||||
fifoInt.addFirst(&testVals[9]);
|
||||
fifoInt.addFirst(&testVals[10]);
|
||||
|
||||
assert(fifoInt.peekFirst()==&buffer[10]);
|
||||
assert(fifoInt.peekLast()==&buffer[1]);
|
||||
assert(fifoInt.peekFirst()==&testVals[10]);
|
||||
assert(fifoInt.peekLast()==&testVals[1]);
|
||||
|
||||
assert(fifoInt.size()==10);
|
||||
assert(fifoInt.remove(&buffer[9]));
|
||||
assert(fifoInt.remove(&testVals[9]));
|
||||
assert(fifoInt.size()==9);
|
||||
assert(!fifoInt.remove(&buffer[15]));
|
||||
assert(!fifoInt.remove(&testVals[15]));
|
||||
assert(fifoInt.size()==9);
|
||||
|
||||
assert(fifoInt.pollLast()==&buffer[1]);
|
||||
assert(fifoInt.pollLast()==&buffer[2]);
|
||||
assert(fifoInt.pollLast()==&buffer[3]);
|
||||
assert(fifoInt.pollLast()==&buffer[4]);
|
||||
assert(fifoInt.pollLast()==&buffer[5]);
|
||||
assert(fifoInt.pollLast()==&buffer[6]);
|
||||
assert(fifoInt.pollLast()==&buffer[7]);
|
||||
assert(fifoInt.pollLast()==&buffer[8]);
|
||||
assert(fifoInt.pollLast()==&testVals[1]);
|
||||
assert(fifoInt.pollLast()==&testVals[2]);
|
||||
assert(fifoInt.pollLast()==&testVals[3]);
|
||||
assert(fifoInt.pollLast()==&testVals[4]);
|
||||
assert(fifoInt.pollLast()==&testVals[5]);
|
||||
assert(fifoInt.pollLast()==&testVals[6]);
|
||||
assert(fifoInt.pollLast()==&testVals[7]);
|
||||
assert(fifoInt.pollLast()==&testVals[8]);
|
||||
// - - - - - - - - - - - -
|
||||
assert(fifoInt.pollLast()==&buffer[10]);
|
||||
assert(fifoInt.pollLast()==&testVals[10]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing increase buffer."<<endl;
|
||||
fifoInt.addLast(&buffer[2]);
|
||||
fifoInt.addLast(&buffer[3]);
|
||||
fifoInt.addLast(&buffer[4]);
|
||||
fifoInt.addLast(&buffer[5]);
|
||||
fifoInt.addLast(&buffer[6]);
|
||||
fifoInt.addLast(&buffer[7]);
|
||||
fifoInt.addLast(&buffer[8]);
|
||||
fifoInt.addLast(&buffer[9]);
|
||||
fifoInt.addLast(&buffer[10]);
|
||||
fifoInt.addLast(&buffer[11]);
|
||||
fifoInt.addLast(&buffer[12]);
|
||||
fifoInt.addLast(&buffer[13]);
|
||||
fifoInt.addLast(&buffer[14]);
|
||||
fifoInt.addLast(&buffer[15]);
|
||||
fifoInt.addLast(&buffer[16]);
|
||||
fifoInt.addLast(&buffer[17]);
|
||||
fifoInt.addLast(&buffer[18]);
|
||||
fifoInt.addLast(&buffer[19]);
|
||||
fifoInt.addLast(&testVals[2]);
|
||||
fifoInt.addLast(&testVals[3]);
|
||||
fifoInt.addLast(&testVals[4]);
|
||||
fifoInt.addLast(&testVals[5]);
|
||||
fifoInt.addLast(&testVals[6]);
|
||||
fifoInt.addLast(&testVals[7]);
|
||||
fifoInt.addLast(&testVals[8]);
|
||||
fifoInt.addLast(&testVals[9]);
|
||||
fifoInt.addLast(&testVals[10]);
|
||||
fifoInt.addLast(&testVals[11]);
|
||||
fifoInt.addLast(&testVals[12]);
|
||||
fifoInt.addLast(&testVals[13]);
|
||||
fifoInt.addLast(&testVals[14]);
|
||||
fifoInt.addLast(&testVals[15]);
|
||||
fifoInt.addLast(&testVals[16]);
|
||||
fifoInt.addLast(&testVals[17]);
|
||||
fifoInt.addLast(&testVals[18]);
|
||||
fifoInt.addLast(&testVals[19]);
|
||||
|
||||
assert(fifoInt.size()==18);
|
||||
fifoInt.debugState();
|
||||
|
||||
@@ -16,19 +16,19 @@ using std::endl;
|
||||
|
||||
const size_t CAPACITY = 10;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void testSimpleType() {
|
||||
GrowingCircularBuffer<int> cb(CAPACITY);
|
||||
|
||||
cout<<"Testing circular buffer."<<endl;
|
||||
cout<<"Testing circular buffer simple type."<<endl;
|
||||
|
||||
assert(cb.capacity()==CAPACITY);
|
||||
assert(cb.size()==0);
|
||||
|
||||
// insert, get test
|
||||
bool first = cb.insert(1);
|
||||
assert(first);
|
||||
assert(cb.size()==1);
|
||||
assert(cb.extract()==1);
|
||||
assert(first);
|
||||
assert(cb.size()==0);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
@@ -45,6 +45,45 @@ int main(int argc, char *argv[]) {
|
||||
assert(cb.size()==0);
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void testPointerType() {
|
||||
GrowingCircularBuffer<int*> 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."<<endl;
|
||||
|
||||
assert(cb.capacity()==CAPACITY);
|
||||
assert(cb.size()==0);
|
||||
|
||||
// insert, get test
|
||||
bool first = cb.insert(&testVals[1]);
|
||||
assert(first);
|
||||
assert(cb.size()==1);
|
||||
assert(cb.extract()==&testVals[1]);
|
||||
assert(cb.size()==0);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
first = cb.insert(&testVals[i]);
|
||||
assert(cb.size()==i+1);
|
||||
assert((cb.size() == 1)==first);
|
||||
}
|
||||
assert(cb.size()==2*CAPACITY);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
assert(cb.extract()==&testVals[i]);
|
||||
assert(cb.size()==2*CAPACITY-i-1);
|
||||
}
|
||||
assert(cb.size()==0);
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
testSimpleType();
|
||||
cout<<endl;
|
||||
testPointerType();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user