xref: /aosp_15_r20/external/angle/src/common/CircularBuffer.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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