diff options
Diffstat (limited to 'include/raul/DoubleBuffer.hpp')
-rw-r--r-- | include/raul/DoubleBuffer.hpp | 120 |
1 files changed, 62 insertions, 58 deletions
diff --git a/include/raul/DoubleBuffer.hpp b/include/raul/DoubleBuffer.hpp index 95ece0f..1c1ee69 100644 --- a/include/raul/DoubleBuffer.hpp +++ b/include/raul/DoubleBuffer.hpp @@ -32,67 +32,71 @@ namespace Raul { * \ingroup raul */ template<typename T> -class DoubleBuffer { +class DoubleBuffer +{ public: - explicit DoubleBuffer(T val) - : _state(State::READ_WRITE) - { - _vals[0] = std::move(val); - } - - DoubleBuffer(const DoubleBuffer&) = delete; - DoubleBuffer& operator=(const DoubleBuffer&) = delete; - - DoubleBuffer(DoubleBuffer&&) = delete; - DoubleBuffer& operator=(DoubleBuffer&&) = delete; - - ~DoubleBuffer() = default; - - inline const T& get() const { - switch (_state.load(std::memory_order_acquire)) { - case State::READ_WRITE: - case State::READ_LOCK: - return _vals[0]; - case State::WRITE_READ: - case State::LOCK_READ: - break; - } - return _vals[1]; - } - - inline bool set(T new_val) { - if (transition(State::READ_WRITE, State::READ_LOCK)) { - // Locked _vals[1] for writing - _vals[1] = std::move(new_val); - _state.store(State::WRITE_READ, std::memory_order_release); - return true; - } - - if (transition(State::WRITE_READ, State::LOCK_READ)) { - // Locked _vals[0] for writing - _vals[0] = std::move(new_val); - _state.store(State::READ_WRITE, std::memory_order_release); - return true; - } - - return false; - } + explicit DoubleBuffer(T val) + : _state(State::READ_WRITE) + { + _vals[0] = std::move(val); + } + + DoubleBuffer(const DoubleBuffer&) = delete; + DoubleBuffer& operator=(const DoubleBuffer&) = delete; + + DoubleBuffer(DoubleBuffer&&) = delete; + DoubleBuffer& operator=(DoubleBuffer&&) = delete; + + ~DoubleBuffer() = default; + + inline const T& get() const + { + switch (_state.load(std::memory_order_acquire)) { + case State::READ_WRITE: + case State::READ_LOCK: + return _vals[0]; + case State::WRITE_READ: + case State::LOCK_READ: + break; + } + return _vals[1]; + } + + inline bool set(T new_val) + { + if (transition(State::READ_WRITE, State::READ_LOCK)) { + // Locked _vals[1] for writing + _vals[1] = std::move(new_val); + _state.store(State::WRITE_READ, std::memory_order_release); + return true; + } + + if (transition(State::WRITE_READ, State::LOCK_READ)) { + // Locked _vals[0] for writing + _vals[0] = std::move(new_val); + _state.store(State::READ_WRITE, std::memory_order_release); + return true; + } + + return false; + } private: - enum class State { - READ_WRITE, ///< Read vals[0], Write vals[1] - READ_LOCK, ///< Read vals[0], Lock vals[1] - WRITE_READ, ///< Write vals[0], Read vals[1] - LOCK_READ ///< Lock vals[0], Read vals[1] - }; - - bool transition(State from, const State to) { - return _state.compare_exchange_strong( - from, to, std::memory_order_release, std::memory_order_relaxed); - } - - std::atomic<State> _state; - T _vals[2]; + enum class State { + READ_WRITE, ///< Read vals[0], Write vals[1] + READ_LOCK, ///< Read vals[0], Lock vals[1] + WRITE_READ, ///< Write vals[0], Read vals[1] + LOCK_READ ///< Lock vals[0], Read vals[1] + }; + + bool transition(State from, const State to) + { + return _state.compare_exchange_strong( + from, to, std::memory_order_release, std::memory_order_relaxed); + } + + std::atomic<State> _state; + T _vals[2]; }; } // namespace Raul |