Path: blob/master/dep/cubeb/src/cubeb_triple_buffer.h
4246 views
/*1* Copyright © 2022 Mozilla Foundation2*3* This program is made available under an ISC-style license. See the4* accompanying file LICENSE for details.5*/67/**8* Adapted and ported to C++ from https://crates.io/crates/triple_buffer9*/1011#ifndef CUBEB_TRIPLE_BUFFER12#define CUBEB_TRIPLE_BUFFER1314#include <atomic>1516// Single producer / single consumer wait-free triple buffering17// implementation, for when a producer wants to publish data to a consumer18// without blocking, but when a queue is wastefull, because it's OK for the19// consumer to miss data updates.20template <typename T> class triple_buffer {21public:22// Write a new value into the triple buffer. Returns true if a value was23// overwritten.24// Producer-side only.25bool write(T & input)26{27storage[input_idx] = input;28return publish();29}30// Get the latest value from the triple buffer.31// Consumer-side only.32T & read()33{34update();35return storage[output_idx];36}37// Returns true if a new value has been published by the consumer without38// having been consumed yet.39// Consumer-side only.40bool updated()41{42return (shared_state.load(std::memory_order_relaxed) & BACK_DIRTY_BIT) != 0;43}44// Reset state and indices to initial values.45void invalidate()46{47shared_state.store(0, std::memory_order_release);48input_idx = 1;49output_idx = 2;50}5152private:53// Publish a value to the consumer. Returns true if the data was overwritten54// without having been read.55bool publish()56{57auto former_back_idx = shared_state.exchange(input_idx | BACK_DIRTY_BIT,58std::memory_order_acq_rel);59input_idx = former_back_idx & BACK_INDEX_MASK;60return (former_back_idx & BACK_DIRTY_BIT) != 0;61}62// Get a new value from the producer, if a new value has been produced.63bool update()64{65bool was_updated = updated();66if (was_updated) {67auto former_back_idx =68shared_state.exchange(output_idx, std::memory_order_acq_rel);69output_idx = former_back_idx & BACK_INDEX_MASK;70}71return was_updated;72}73T storage[3];74// Mask used to extract back-buffer index75const uint8_t BACK_INDEX_MASK = 0b11;76// Bit set by producer to signal updates77const uint8_t BACK_DIRTY_BIT = 0b100;78// Shared state: a dirty bit, and an index.79std::atomic<uint8_t> shared_state = {0};80// Output index, private to the consumer.81uint8_t output_idx = 1;82// Input index, private to the producer.83uint8_t input_idx = 2;84};8586#endif // CUBEB_TRIPLE_BUFFER878889