Line data Source code
1 : #pragma once
2 :
3 : #include <jage/engine/memory/cacheline_size.hpp>
4 : #include <jage/engine/memory/cacheline_slot.hpp>
5 :
6 : #include <array>
7 : #include <atomic>
8 : #include <cstdint>
9 :
10 : namespace jage::engine::concurrency {
11 : template <class T, template <class> class TAtomic = std::atomic>
12 : class alignas(memory::cacheline_size) double_buffer {
13 : alignas(
14 : memory::cacheline_size) std::array<memory::cacheline_slot<T>, 2> buffer_;
15 : alignas(memory::cacheline_size) TAtomic<std::uint8_t> index_{0U};
16 :
17 : static_assert(alignof(decltype(buffer_)) >= memory::cacheline_size);
18 : static_assert(sizeof(decltype(buffer_)) % memory::cacheline_size == 0);
19 :
20 : public:
21 2 : [[nodiscard]] auto read() const -> T {
22 2 : const auto active_index = index_.load(std::memory_order::acquire);
23 2 : return buffer_[active_index];
24 : }
25 :
26 1 : auto write(const T &desired) -> void {
27 1 : const auto active_index = index_.load(std::memory_order::acquire);
28 1 : const auto inactive_index = static_cast<std::uint8_t>(active_index ^ 1U);
29 1 : buffer_[inactive_index] = desired;
30 1 : index_.store(inactive_index, std::memory_order::release);
31 1 : }
32 : };
33 : } // namespace jage::engine::concurrency
|