From 8e626b8d1fe3d2d8ebf195fb51ddab0c5d2a4d05 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 28 Mar 2023 17:57:55 +0300 Subject: [PATCH] BAN: Implement basic Circular Queue --- BAN/include/BAN/CircularQueue.h | 113 ++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 BAN/include/BAN/CircularQueue.h diff --git a/BAN/include/BAN/CircularQueue.h b/BAN/include/BAN/CircularQueue.h new file mode 100644 index 00000000..a0413c12 --- /dev/null +++ b/BAN/include/BAN/CircularQueue.h @@ -0,0 +1,113 @@ +#pragma once + +#include + +#include +#include + +namespace BAN +{ + + template + class CircularQueue + { + public: + using size_type = size_t; + using value_type = T; + + public: + CircularQueue() = default; + ~CircularQueue(); + + void push(const T&); + void push(T&&); + template + void emplace(Args&&... args); + + void pop(); + + const T& front() const; + T& front(); + + size_type size() const { return m_size; } + bool empty() const { return size() == 0; } + bool full() const { return size() == capacity(); } + + static constexpr size_type capacity() { return S; } + + private: + T* element_at(size_type); + const T* element_at(size_type) const; + + private: + alignas(T) uint8_t m_storage[sizeof(T) * capacity()]; + size_type m_first { 0 }; + size_type m_size { 0 }; + }; + + template + CircularQueue::~CircularQueue() + { + for (size_type i = 0; i < m_size; i++) + element_at((m_first + i) % capacity())->~T(); + } + + template + void CircularQueue::push(const T& value) + { + emplace(BAN::move(T(value))); + } + + template + void CircularQueue::push(T&& value) + { + emplace(BAN::move(value)); + } + + template + template + void CircularQueue::emplace(Args&&... args) + { + ASSERT(!full()); + new (element_at(((m_first + m_size) % capacity()))) T(BAN::forward(args)...); + m_size++; + } + + template + void CircularQueue::pop() + { + ASSERT(!empty()); + element_at(m_first)->~T(); + m_first = (m_first + 1) % capacity(); + m_size--; + } + + template + const T& CircularQueue::front() const + { + ASSERT(!empty()); + return *element_at(m_first); + } + + template + T& CircularQueue::front() + { + ASSERT(!empty()); + return *element_at(m_first); + } + + template + const T* CircularQueue::element_at(size_type index) const + { + ASSERT(index < capacity()); + return (const T*)(m_storage + index * sizeof(T)); + } + + template + T* CircularQueue::element_at(size_type index) + { + ASSERT(index < capacity()); + return (T*)(m_storage + index * sizeof(T)); + } + +} \ No newline at end of file