Lumi/companion/native/obs-bridge/include/bounded_spsc_queue.hpp
2026-07-22 11:02:04 +02:00

33 lines
1.2 KiB
C++

#pragma once
#include <array>
#include <atomic>
#include <cstddef>
#include <optional>
namespace lumi {
template <typename T, std::size_t Capacity> class bounded_spsc_queue {
static_assert(Capacity > 1);
std::array<T, Capacity> values_{};
alignas(64) std::atomic<std::size_t> head_{0};
alignas(64) std::atomic<std::size_t> tail_{0};
std::atomic<std::uint64_t> dropped_{0};
public:
bool try_push(T value) noexcept {
const auto head = head_.load(std::memory_order_relaxed);
const auto next = (head + 1) % Capacity;
if (next == tail_.load(std::memory_order_acquire)) { dropped_.fetch_add(1, std::memory_order_relaxed); return false; }
values_[head] = std::move(value);
head_.store(next, std::memory_order_release);
return true;
}
std::optional<T> try_pop() noexcept {
const auto tail = tail_.load(std::memory_order_relaxed);
if (tail == head_.load(std::memory_order_acquire)) return std::nullopt;
T value = std::move(values_[tail]);
tail_.store((tail + 1) % Capacity, std::memory_order_release);
return value;
}
std::uint64_t dropped() const noexcept { return dropped_.load(std::memory_order_relaxed); }
};
}