CircularBuffer.h (5029B)
1 // 2 // Copyright 2021 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // CircularBuffer.h: 7 // An array class with an index that loops through the elements. 8 // 9 10 #ifndef COMMON_CIRCULARBUFFER_H_ 11 #define COMMON_CIRCULARBUFFER_H_ 12 13 #include "common/debug.h" 14 15 #include <algorithm> 16 #include <array> 17 18 namespace angle 19 { 20 template <class T, size_t N, class Storage = std::array<T, N>> 21 class CircularBuffer final 22 { 23 public: 24 using value_type = typename Storage::value_type; 25 using size_type = typename Storage::size_type; 26 using reference = typename Storage::reference; 27 using const_reference = typename Storage::const_reference; 28 using pointer = typename Storage::pointer; 29 using const_pointer = typename Storage::const_pointer; 30 using iterator = typename Storage::iterator; 31 using const_iterator = typename Storage::const_iterator; 32 33 CircularBuffer(); 34 CircularBuffer(const value_type &value); 35 36 CircularBuffer(const CircularBuffer<T, N, Storage> &other); 37 CircularBuffer(CircularBuffer<T, N, Storage> &&other); 38 39 CircularBuffer<T, N, Storage> &operator=(const CircularBuffer<T, N, Storage> &other); 40 CircularBuffer<T, N, Storage> &operator=(CircularBuffer<T, N, Storage> &&other); 41 42 ~CircularBuffer(); 43 44 // begin() and end() are used to iterate over all elements regardless of the current position of 45 // the front of the buffer. Useful for initialization and clean up, as otherwise only the front 46 // element is expected to be accessed. 47 iterator begin(); 48 const_iterator begin() const; 49 50 iterator end(); 51 const_iterator end() const; 52 53 size_type size() const; 54 55 reference front(); 56 const_reference front() const; 57 58 void swap(CircularBuffer<T, N, Storage> &other); 59 60 // Move the front forward to the next index, looping back to the beginning if the end of the 61 // array is reached. 62 void next(); 63 64 private: 65 Storage mData; 66 size_type mFrontIndex; 67 }; 68 69 template <class T, size_t N, class Storage> 70 CircularBuffer<T, N, Storage>::CircularBuffer() : mFrontIndex(0) 71 {} 72 73 template <class T, size_t N, class Storage> 74 CircularBuffer<T, N, Storage>::CircularBuffer(const value_type &value) : CircularBuffer() 75 { 76 std::fill(begin(), end(), value); 77 } 78 79 template <class T, size_t N, class Storage> 80 CircularBuffer<T, N, Storage>::CircularBuffer(const CircularBuffer<T, N, Storage> &other) 81 { 82 *this = other; 83 } 84 85 template <class T, size_t N, class Storage> 86 CircularBuffer<T, N, Storage>::CircularBuffer(CircularBuffer<T, N, Storage> &&other) 87 : CircularBuffer() 88 { 89 swap(other); 90 } 91 92 template <class T, size_t N, class Storage> 93 CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=( 94 const CircularBuffer<T, N, Storage> &other) 95 { 96 std::copy(other.begin(), other.end(), begin()); 97 mFrontIndex = other.mFrontIndex; 98 return *this; 99 } 100 101 template <class T, size_t N, class Storage> 102 CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=( 103 CircularBuffer<T, N, Storage> &&other) 104 { 105 swap(other); 106 return *this; 107 } 108 109 template <class T, size_t N, class Storage> 110 CircularBuffer<T, N, Storage>::~CircularBuffer() = default; 111 112 template <class T, size_t N, class Storage> 113 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::begin() 114 { 115 return mData.begin(); 116 } 117 118 template <class T, size_t N, class Storage> 119 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator 120 CircularBuffer<T, N, Storage>::begin() const 121 { 122 return mData.begin(); 123 } 124 125 template <class T, size_t N, class Storage> 126 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::end() 127 { 128 return mData.end(); 129 } 130 131 template <class T, size_t N, class Storage> 132 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator 133 CircularBuffer<T, N, Storage>::end() const 134 { 135 return mData.end(); 136 } 137 138 template <class T, size_t N, class Storage> 139 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::size_type CircularBuffer<T, N, Storage>::size() 140 const 141 { 142 return N; 143 } 144 145 template <class T, size_t N, class Storage> 146 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::reference 147 CircularBuffer<T, N, Storage>::front() 148 { 149 ASSERT(mFrontIndex < size()); 150 return mData[mFrontIndex]; 151 } 152 153 template <class T, size_t N, class Storage> 154 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_reference 155 CircularBuffer<T, N, Storage>::front() const 156 { 157 ASSERT(mFrontIndex < size()); 158 return mData[mFrontIndex]; 159 } 160 161 template <class T, size_t N, class Storage> 162 void CircularBuffer<T, N, Storage>::swap(CircularBuffer<T, N, Storage> &other) 163 { 164 std::swap(mData, other.mData); 165 std::swap(mFrontIndex, other.mFrontIndex); 166 } 167 168 template <class T, size_t N, class Storage> 169 void CircularBuffer<T, N, Storage>::next() 170 { 171 mFrontIndex = (mFrontIndex + 1) % size(); 172 } 173 } // namespace angle 174 175 #endif // COMMON_CIRCULARBUFFER_H_