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