diff --git a/sequential/ringbuffer.hpp b/sequential/ringbuffer.hpp new file mode 100644 index 0000000..0a663f1 --- /dev/null +++ b/sequential/ringbuffer.hpp @@ -0,0 +1,75 @@ +#include "vector.hpp" + +template +class RingBuffer +{ +private: + Vector 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); + } +}; \ No newline at end of file diff --git a/test/ringbuffer.cpp b/test/ringbuffer.cpp new file mode 100644 index 0000000..a3e86bd --- /dev/null +++ b/test/ringbuffer.cpp @@ -0,0 +1,60 @@ +#include "../sequential/ringbuffer.hpp" +#include "testutil.hpp" + +bool TestInsertion() +{ + std::size_t const testSize = 512u; + + std::vector truth; + truth.resize(testSize); + RingBuffer 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 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; +} \ No newline at end of file