|
// JLCircBuffer.h: Implementation of circular buffer template.
// The "JL" is the author's initials
//
// T must have:
// T::T() or equivalent
// T::operator=() or equivalent
#ifndef INCL_JLCIRCBUFFER_H
#define INCL_JLCIRCBUFFER_H
template <class T> class JLCircBuffer
{
public:
// ctor/dtor
JLCircBuffer(int minSize = DefaultSize);
JLCircBuffer(const JLCircBuffer& rhs);
~JLCircBuffer();
// assignment
const JLCircBuffer& operator=(const JLCircBuffer& rhs);
//
// operations
//
// Note: does not delete elements in buffer
void clear() { nbrEntries = 0; nextOffset = 0; }
// status of buffer
int entries() const { return nbrEntries; }
int isEmpty() const { return nbrEntries == 0; }
// Index w.r.t. front of queue -- modifyable until next operation
T& operator[](int idx) {
#ifndef NDEBUG
assert(idx >= 0 && idx < nbrEntries);
#endif
return buffer[(nextOffset + idx) & sizeLessOne];
}
// Index w.r.t. front of queue -- const value
const T& operator[](int idx) const {
#ifndef NDEBUG
assert(idx >= 0 && idx < nbrEntries);
#endif
return buffer[(nextOffset + idx) & sizeLessOne];
}
// Remove item from front of queue
void removeFirst() {
#ifndef NDEBUG
assert(!isEmpty());
#endif
nextOffset = (nextOffset+1) & sizeLessOne;
nbrEntries--;
}
// Get and remove item from front of queue
T next() {
#ifndef NDEBUG
assert(!isEmpty());
#endif
T* elt = &buffer[nextOffset];
removeFirst();
return *elt;
}
// Add item to end of queue
void append(const T& elt)
{
if (nbrEntries == size)
{
expand();
}
buffer[(nextOffset + nbrEntries) & sizeLessOne] = elt;
nbrEntries++;
}
// constants
enum { DefaultSize = 32 };
private:
void init();
// double the current buffer size -- this changes the offsets!
void expand();
// data
T* buffer;
int size; // number of allocated entries
int sizeLessOne; // number of allocated entries - 1
T* bufEnd; // == buffer + size
int nextOffset; // index of next entry in queue
int nbrEntries;
};
//////////////////////////////////////////////////////////////////////////
// Out-of-line template functions //
//////////////////////////////////////////////////////////////////////////
template <class T>
JLCircBuffer<T>::JLCircBuffer(int minSize)
{
// Find first power of 2 >= to requested size
for (size = 2; size < minSize; size *= 2) {;}
init();
}
template <class T>
JLCircBuffer<T>::JLCircBuffer(const JLCircBuffer& rhs)
{
for (size = DefaultSize; size < rhs.entries(); size *= 2) {;}
init();
}
template <class T>
void
JLCircBuffer<T>::init()
{
// Allocate buffer
buffer = new T[size];
// Other initialization
sizeLessOne = size - 1;
bufEnd = buffer + size;
nextOffset = 0;
nbrEntries = 0;
}
template <class T>
JLCircBuffer<T>::~JLCircBuffer()
{
delete [] buffer;
}
template <class T>
const JLCircBuffer<T>&
JLCircBuffer<T>::operator=(
const JLCircBuffer& rhs
)
{
if (this != &rhs)
{
clear();
for (int i = 0; i < rhs.entries(); i++)
{
append(rhs[i]);
}
}
return *this;
}
template <class T>
void
JLCircBuffer<T>::expand()
{
// allocate a buffer that is double the current size
T* newBuffer = new T[size*2];
// Copy the contents to the new buffer
// Note that this will store the first logical item in the
// first physical array element.
for (int i = 0; i < entries(); i++)
{
newBuffer[i] = (*this)[i];
}
// delete old buffer
delete [] buffer;
// Re-initialize with new contents, keep old nbrEntries
buffer = newBuffer;
bufEnd = buffer + size;
size = size * 2;
sizeLessOne = size - 1;
nextOffset = 0;
}
#endif
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.