From d4fc002d8a46675e01fe4c63fc68634debb85e29 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 28 Jul 2023 17:28:18 +0200 Subject: [PATCH] libluna: Add a variant of CircularQueue that dynamically allocates its buffer at runtime This is needed to implement the backlog queue for listening sockets. --- libluna/include/luna/CircularQueue.h | 67 ++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/libluna/include/luna/CircularQueue.h b/libluna/include/luna/CircularQueue.h index 3960854e..583bcbae 100644 --- a/libluna/include/luna/CircularQueue.h +++ b/libluna/include/luna/CircularQueue.h @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include template class CircularQueue @@ -55,3 +57,68 @@ template class CircularQueue Atomic m_head = 0; Atomic m_tail = 0; }; + +template class DynamicCircularQueue +{ + + public: + DynamicCircularQueue() + { + } + + ~DynamicCircularQueue() + { + if (m_data) free_impl(m_data); + } + + Result set_size(usize size) + { + m_data = (T*)TRY(calloc_impl(size + 1, sizeof(T), false)); + m_capacity = size + 1; + return {}; + } + + bool try_push(const T& value) + { + check(m_capacity); + usize current_tail = m_tail.load(MemoryOrder::Relaxed); + const usize new_tail = (current_tail + 1) % m_capacity; + if (new_tail == m_head.load(MemoryOrder::Acquire)) + { + // Queue is full + return false; + } + m_data[current_tail] = value; + if (!m_tail.compare_exchange_strong(current_tail, new_tail, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the tail + return false; + } + return true; + } + + bool try_pop(T& value) + { + check(m_capacity); + usize current_head = m_head.load(MemoryOrder::Relaxed); + if (current_head == m_tail.load(MemoryOrder::Acquire)) + { + // Queue is empty + return false; + } + value = m_data[current_head]; + const usize new_head = (current_head + 1) % m_capacity; + if (!m_head.compare_exchange_strong(current_head, new_head, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the head + return false; + } + return true; + } + + private: + T* m_data = nullptr; + usize m_capacity = 0; + Atomic m_head = 0; + Atomic m_tail = 0; +};