9#include <CoreFoundation/CoreFoundation.h>
14#include <shared_mutex>
97 using BufferIndex =
SInt64;
101 std::optional<T> value = {};
102 std::atomic<BufferIndex> index = -1;
103 mutable std::shared_mutex mutex;
169 buffer_->mutex.unlock_shared();
175 : buffer_(
other.buffer_)
177 other.buffer_ =
nullptr;
189 return *buffer_->value;
193 const Buffer* buffer_ =
nullptr;
205 Set(std::move(value));
239 template <
typename TT>
247 const auto oldIndex = currentIndex_.load(std::memory_order_relaxed);
278 newBuffer.value = std::forward<TT>(value);
286 if constexpr (!std::is_trivial<T>::value) {
303 friend class ReadLock;
305 const Buffer& GetBufferAt(BufferIndex index)
const
307 return buffers_[index % 2];
310 Buffer& GetBufferAt(BufferIndex index)
312 return buffers_[index % 2];
315 std::mutex writeMutex_;
318 std::atomic<BufferIndex> currentIndex_ = 0;
ReadLock(ReadLock &&other)
Move lock.
const T & GetReference() const
Get read-only reference to the value. The reference may be used until read lock destructor is called....
ReadLock(const DoubleBuffer &doubleBuffer)
Acquire the lock. Non-blocking and lock-free. May spin for a while if a setter is running concurrentl...
~ReadLock()
Release the lock.
Doubly-buffered value with non-blocking read and blocking write.
void Set(TT &&value)
Set value.
T Get() const
Get copy of the value. Non-blocking and lock-free, see ReadLock.
ReadLock GetReadLock() const
Get locked read-only reference to the value. Non-blocking and lock-free, see ReadLock.
DoubleBuffer(const T &value)
Initialize buffer with given value.
DoubleBuffer(T &&value=T())
Initialize buffer with given value.