// // Copyright 2021 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // CircularBuffer.h: // An array class with an index that loops through the elements. // #ifndef COMMON_CIRCULARBUFFER_H_ #define COMMON_CIRCULARBUFFER_H_ #include "common/debug.h" #include #include namespace angle { template > class CircularBuffer final { public: using value_type = typename Storage::value_type; using size_type = typename Storage::size_type; using reference = typename Storage::reference; using const_reference = typename Storage::const_reference; using pointer = typename Storage::pointer; using const_pointer = typename Storage::const_pointer; using iterator = typename Storage::iterator; using const_iterator = typename Storage::const_iterator; CircularBuffer(); CircularBuffer(const value_type &value); CircularBuffer(const CircularBuffer &other); CircularBuffer(CircularBuffer &&other); CircularBuffer &operator=(const CircularBuffer &other); CircularBuffer &operator=(CircularBuffer &&other); ~CircularBuffer(); // begin() and end() are used to iterate over all elements regardless of the current position of // the front of the buffer. Useful for initialization and clean up, as otherwise only the front // element is expected to be accessed. iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; size_type size() const; reference front(); const_reference front() const; void swap(CircularBuffer &other); // Move the front forward to the next index, looping back to the beginning if the end of the // array is reached. void next(); private: Storage mData; size_type mFrontIndex; }; template CircularBuffer::CircularBuffer() : mFrontIndex(0) {} template CircularBuffer::CircularBuffer(const value_type &value) : CircularBuffer() { std::fill(begin(), end(), value); } template CircularBuffer::CircularBuffer(const CircularBuffer &other) { *this = other; } template CircularBuffer::CircularBuffer(CircularBuffer &&other) : CircularBuffer() { swap(other); } template CircularBuffer &CircularBuffer::operator=( const CircularBuffer &other) { std::copy(other.begin(), other.end(), begin()); mFrontIndex = other.mFrontIndex; return *this; } template CircularBuffer &CircularBuffer::operator=( CircularBuffer &&other) { swap(other); return *this; } template CircularBuffer::~CircularBuffer() = default; template ANGLE_INLINE typename CircularBuffer::iterator CircularBuffer::begin() { return mData.begin(); } template ANGLE_INLINE typename CircularBuffer::const_iterator CircularBuffer::begin() const { return mData.begin(); } template ANGLE_INLINE typename CircularBuffer::iterator CircularBuffer::end() { return mData.end(); } template ANGLE_INLINE typename CircularBuffer::const_iterator CircularBuffer::end() const { return mData.end(); } template ANGLE_INLINE typename CircularBuffer::size_type CircularBuffer::size() const { return N; } template ANGLE_INLINE typename CircularBuffer::reference CircularBuffer::front() { ASSERT(mFrontIndex < size()); return mData[mFrontIndex]; } template ANGLE_INLINE typename CircularBuffer::const_reference CircularBuffer::front() const { ASSERT(mFrontIndex < size()); return mData[mFrontIndex]; } template void CircularBuffer::swap(CircularBuffer &other) { std::swap(mData, other.mData); std::swap(mFrontIndex, other.mFrontIndex); } template void CircularBuffer::next() { mFrontIndex = (mFrontIndex + 1) % size(); } } // namespace angle #endif // COMMON_CIRCULARBUFFER_H_