xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deRingBuffer.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _DERINGBUFFER_HPP
2 #define _DERINGBUFFER_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Ring buffer template.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.hpp"
27 
28 namespace de
29 {
30 
31 void RingBuffer_selfTest(void);
32 
33 /** Ring buffer template. */
34 template <typename T>
35 class RingBuffer
36 {
37 public:
38     RingBuffer(int size);
39     ~RingBuffer(void);
40 
41     void clear(void);
42     void resize(int newSize);
43 
getSize(void) const44     int getSize(void) const
45     {
46         return m_size;
47     }
getNumElements(void) const48     int getNumElements(void) const
49     {
50         return m_numElements;
51     }
getNumFree(void) const52     int getNumFree(void) const
53     {
54         return m_size - m_numElements;
55     }
56 
57     void pushFront(const T &elem);
58     void pushFront(const T *elemBuf, int count);
59 
60     void peekBack(T *elemBuf, int count) const;
61     T peekBack(int offset) const;
62 
63     T popBack(void);
popBack(T * elemBuf,int count)64     void popBack(T *elemBuf, int count)
65     {
66         peekBack(elemBuf, count);
67         popBack(count);
68     }
69     void popBack(int count);
70 
71 protected:
72     int m_numElements;
73     int m_front;
74     int m_back;
75 
76     T *m_buffer;
77     int m_size;
78 };
79 
80 // RingBuffer implementation.
81 
82 template <typename T>
RingBuffer(int size)83 RingBuffer<T>::RingBuffer(int size) : m_numElements(0)
84                                     , m_front(0)
85                                     , m_back(0)
86                                     , m_size(size)
87 {
88     DE_ASSERT(size > 0);
89     m_buffer = new T[m_size];
90 }
91 
92 template <typename T>
~RingBuffer()93 RingBuffer<T>::~RingBuffer()
94 {
95     delete[] m_buffer;
96 }
97 
98 template <typename T>
clear(void)99 void RingBuffer<T>::clear(void)
100 {
101     m_numElements = 0;
102     m_front       = 0;
103     m_back        = 0;
104 }
105 
106 template <typename T>
resize(int newSize)107 void RingBuffer<T>::resize(int newSize)
108 {
109     DE_ASSERT(newSize >= m_numElements);
110     T *buf = new T[newSize];
111 
112     try
113     {
114         // Copy old elements.
115         for (int ndx = 0; ndx < m_numElements; ndx++)
116             buf[ndx] = m_buffer[(m_back + ndx) % m_size];
117 
118         // Reset pointers.
119         m_front = m_numElements;
120         m_back  = 0;
121         m_size  = newSize;
122 
123         DE_SWAP(T *, buf, m_buffer);
124         delete[] buf;
125     }
126     catch (...)
127     {
128         delete[] buf;
129         throw;
130     }
131 }
132 
133 template <typename T>
pushFront(const T & elem)134 inline void RingBuffer<T>::pushFront(const T &elem)
135 {
136     DE_ASSERT(getNumFree() > 0);
137     m_buffer[m_front] = elem;
138     m_front           = (m_front + 1) % m_size;
139     m_numElements += 1;
140 }
141 
142 template <typename T>
pushFront(const T * elemBuf,int count)143 void RingBuffer<T>::pushFront(const T *elemBuf, int count)
144 {
145     DE_ASSERT(de::inRange(count, 0, getNumFree()));
146     for (int i = 0; i < count; i++)
147         m_buffer[(m_front + i) % m_size] = elemBuf[i];
148     m_front = (m_front + count) % m_size;
149     m_numElements += count;
150 }
151 
152 template <typename T>
popBack()153 inline T RingBuffer<T>::popBack()
154 {
155     DE_ASSERT(getNumElements() > 0);
156     int ndx = m_back;
157     m_back  = (m_back + 1) % m_size;
158     m_numElements -= 1;
159     return m_buffer[ndx];
160 }
161 
162 template <typename T>
peekBack(int offset) const163 inline T RingBuffer<T>::peekBack(int offset) const
164 {
165     DE_ASSERT(de::inBounds(offset, 0, getNumElements()));
166     return m_buffer[(m_back + offset) % m_size];
167 }
168 
169 template <typename T>
peekBack(T * elemBuf,int count) const170 void RingBuffer<T>::peekBack(T *elemBuf, int count) const
171 {
172     DE_ASSERT(de::inRange(count, 0, getNumElements()));
173     for (int i = 0; i < count; i++)
174         elemBuf[i] = m_buffer[(m_back + i) % m_size];
175 }
176 
177 template <typename T>
popBack(int count)178 void RingBuffer<T>::popBack(int count)
179 {
180     DE_ASSERT(de::inRange(count, 0, getNumElements()));
181     m_back = (m_back + count) % m_size;
182     m_numElements -= count;
183 }
184 
185 } // namespace de
186 
187 #endif // _DERINGBUFFER_HPP
188