Ringbuffer added
This commit is contained in:
75
sequential/ringbuffer.hpp
Normal file
75
sequential/ringbuffer.hpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class RingBuffer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Vector<T> data;
|
||||||
|
std::size_t head, tail;
|
||||||
|
|
||||||
|
void AdvanceHead()
|
||||||
|
{
|
||||||
|
++head;
|
||||||
|
if(head >= data.GetSize())
|
||||||
|
{
|
||||||
|
head = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvanceTail()
|
||||||
|
{
|
||||||
|
++tail;
|
||||||
|
if(tail >= data.GetSize())
|
||||||
|
{
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
|
if(tail == head)
|
||||||
|
{
|
||||||
|
AdvanceHead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Push(const T value)
|
||||||
|
{
|
||||||
|
data[tail] = value;
|
||||||
|
AdvanceTail();
|
||||||
|
}
|
||||||
|
|
||||||
|
T Pop()
|
||||||
|
{
|
||||||
|
if(head == tail)
|
||||||
|
{
|
||||||
|
throw std::out_of_range("Cannot retrieve value when size is 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
T const & toReturn = data[head];
|
||||||
|
AdvanceHead();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t GetSize() const
|
||||||
|
{
|
||||||
|
if(head <= tail)
|
||||||
|
{
|
||||||
|
return tail - head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return tail + (data.GetSize() - head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const
|
||||||
|
{
|
||||||
|
return head == tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
RingBuffer(std::size_t const size)
|
||||||
|
: data(),
|
||||||
|
head(0),
|
||||||
|
tail(0)
|
||||||
|
{
|
||||||
|
data.Resize(size + 1ul);
|
||||||
|
}
|
||||||
|
};
|
||||||
60
test/ringbuffer.cpp
Normal file
60
test/ringbuffer.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#include "../sequential/ringbuffer.hpp"
|
||||||
|
#include "testutil.hpp"
|
||||||
|
|
||||||
|
bool TestInsertion()
|
||||||
|
{
|
||||||
|
std::size_t const testSize = 512u;
|
||||||
|
|
||||||
|
std::vector<unsigned> truth;
|
||||||
|
truth.resize(testSize);
|
||||||
|
RingBuffer<unsigned> ringBuffer(512u);
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
|
{
|
||||||
|
truth[i] = Util::GetRandomNumber();
|
||||||
|
ringBuffer.Push(truth[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
|
{
|
||||||
|
if(truth[i] != ringBuffer.Pop())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestWrapAround()
|
||||||
|
{
|
||||||
|
std::size_t const testSize = 32u;
|
||||||
|
|
||||||
|
RingBuffer<unsigned> ringBuffer(testSize);
|
||||||
|
for(std::size_t i = 0; i < testSize / 2u; ++i)
|
||||||
|
{
|
||||||
|
ringBuffer.Push(42u);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
|
{
|
||||||
|
ringBuffer.Push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
|
{
|
||||||
|
if(ringBuffer.Pop() != i)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Test::Execute(TestInsertion, "Insertion test");
|
||||||
|
Test::Execute(TestWrapAround, "Wrap around test");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user