10static inline uint32_t rotl32(uint32_t n,
unsigned int c)
12 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
16 return (n << c) | (n >> ((-c) & mask));
19static inline uint32_t rotr32(uint32_t n,
unsigned int c)
21 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
25 return (n >> c) | (n << ((-c) & mask));
34 template<
typename T,
size_t buffsize>
38 static_assert((buffsize > 0) && ((buffsize& (buffsize - 1)) == 0),
39 "Buffer size must be a power of 2 to gain performance.");
40 static_assert((!std::is_abstract_v<T>),
"Abstract types can cause issues.");
41 static_assert((!std::is_array_v<T>),
"Cannot store arrays in the ring buffer. Although, support maybe added if a need ever arises.");
43 std::array<T, buffsize> buffer;
44 std::atomic<size_t> head{ 0 };
45 std::atomic<size_t> tail{ 0 };
46 const size_t mask = buffsize - 1;
51 constexpr size_t Capacity()const noexcept {
return buffsize; };
57 head.store(0, std::memory_order_relaxed);
58 tail.store(0, std::memory_order_relaxed);
64 size_t current_tail = tail.load(std::memory_order_relaxed);
65 size_t next_tail = (current_tail + 1) & mask;
67 if (next_tail == head.load(std::memory_order_acquire)) {
72 buffer[current_tail] = element;
73 tail.store(next_tail, std::memory_order_release);
79 size_t current_head = head.load(std::memory_order_relaxed);
81 if (current_head == tail.load(std::memory_order_acquire)) {
86 element = buffer[current_head];
87 head.store((current_head + 1) & mask, std::memory_order_release);
92 inline bool IsFull() const noexcept {
93 size_t next_tail = (tail.load(std::memory_order_relaxed) + 1) & mask;
94 return next_tail == head.load(std::memory_order_acquire);
99 return head.load(std::memory_order_acquire) == tail.load(std::memory_order_relaxed);
103 inline size_t Size() const noexcept {
104 size_t current_tail = tail.load(std::memory_order_relaxed);
105 size_t current_head = head.load(std::memory_order_relaxed);
106 return (current_tail - current_head) & mask;
RingBuffer() noexcept=default
constexpr size_t Capacity() const noexcept
Evaluated at compile time, returns the size of the buffer which is already known.
bool Enqueue(const T &element) noexcept
size_t Size() const noexcept
bool IsEmpty() const noexcept
bool Dequeue(T &element) noexcept
bool IsFull() const noexcept
The Hubris Engine main namespace.