xref: /aosp_15_r20/frameworks/native/services/sensorservice/RingBuffer.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #ifndef ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
18*38e8c45fSAndroid Build Coastguard Worker #define ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <cutils/compiler.h>
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <iterator>
24*38e8c45fSAndroid Build Coastguard Worker #include <utility>
25*38e8c45fSAndroid Build Coastguard Worker #include <vector>
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker namespace android {
28*38e8c45fSAndroid Build Coastguard Worker namespace SensorServiceUtil {
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker /**
31*38e8c45fSAndroid Build Coastguard Worker  * A RingBuffer class that maintains an array of objects that can grow up to a certain size.
32*38e8c45fSAndroid Build Coastguard Worker  * Elements added to the RingBuffer are inserted in the logical front of the buffer, and
33*38e8c45fSAndroid Build Coastguard Worker  * invalidate all current iterators for that RingBuffer object.
34*38e8c45fSAndroid Build Coastguard Worker  */
35*38e8c45fSAndroid Build Coastguard Worker template <class T>
36*38e8c45fSAndroid Build Coastguard Worker class RingBuffer final {
37*38e8c45fSAndroid Build Coastguard Worker public:
38*38e8c45fSAndroid Build Coastguard Worker 
39*38e8c45fSAndroid Build Coastguard Worker     /**
40*38e8c45fSAndroid Build Coastguard Worker      * Construct a RingBuffer that can grow up to the given length.
41*38e8c45fSAndroid Build Coastguard Worker      */
42*38e8c45fSAndroid Build Coastguard Worker     explicit RingBuffer(size_t length);
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker     /**
45*38e8c45fSAndroid Build Coastguard Worker      * Forward iterator to this class.  Implements an std:forward_iterator.
46*38e8c45fSAndroid Build Coastguard Worker      */
47*38e8c45fSAndroid Build Coastguard Worker     class iterator : public std::iterator<std::forward_iterator_tag, T> {
48*38e8c45fSAndroid Build Coastguard Worker     public:
49*38e8c45fSAndroid Build Coastguard Worker         iterator(T* ptr, size_t size, size_t pos, size_t ctr);
50*38e8c45fSAndroid Build Coastguard Worker 
51*38e8c45fSAndroid Build Coastguard Worker         iterator& operator++();
52*38e8c45fSAndroid Build Coastguard Worker 
53*38e8c45fSAndroid Build Coastguard Worker         iterator operator++(int);
54*38e8c45fSAndroid Build Coastguard Worker 
55*38e8c45fSAndroid Build Coastguard Worker         bool operator==(const iterator& rhs);
56*38e8c45fSAndroid Build Coastguard Worker 
57*38e8c45fSAndroid Build Coastguard Worker         bool operator!=(const iterator& rhs);
58*38e8c45fSAndroid Build Coastguard Worker 
59*38e8c45fSAndroid Build Coastguard Worker         T& operator*();
60*38e8c45fSAndroid Build Coastguard Worker 
61*38e8c45fSAndroid Build Coastguard Worker         T* operator->();
62*38e8c45fSAndroid Build Coastguard Worker 
63*38e8c45fSAndroid Build Coastguard Worker     private:
64*38e8c45fSAndroid Build Coastguard Worker         T* mPtr;
65*38e8c45fSAndroid Build Coastguard Worker         size_t mSize;
66*38e8c45fSAndroid Build Coastguard Worker         size_t mPos;
67*38e8c45fSAndroid Build Coastguard Worker         size_t mCtr;
68*38e8c45fSAndroid Build Coastguard Worker     };
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker     /**
71*38e8c45fSAndroid Build Coastguard Worker      * Constant forward iterator to this class.  Implements an std:forward_iterator.
72*38e8c45fSAndroid Build Coastguard Worker      */
73*38e8c45fSAndroid Build Coastguard Worker     class const_iterator : public std::iterator<std::forward_iterator_tag, T> {
74*38e8c45fSAndroid Build Coastguard Worker     public:
75*38e8c45fSAndroid Build Coastguard Worker         const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr);
76*38e8c45fSAndroid Build Coastguard Worker 
77*38e8c45fSAndroid Build Coastguard Worker         const_iterator& operator++();
78*38e8c45fSAndroid Build Coastguard Worker 
79*38e8c45fSAndroid Build Coastguard Worker         const_iterator operator++(int);
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker         bool operator==(const const_iterator& rhs);
82*38e8c45fSAndroid Build Coastguard Worker 
83*38e8c45fSAndroid Build Coastguard Worker         bool operator!=(const const_iterator& rhs);
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker         const T& operator*();
86*38e8c45fSAndroid Build Coastguard Worker 
87*38e8c45fSAndroid Build Coastguard Worker         const T* operator->();
88*38e8c45fSAndroid Build Coastguard Worker 
89*38e8c45fSAndroid Build Coastguard Worker     private:
90*38e8c45fSAndroid Build Coastguard Worker         const T* mPtr;
91*38e8c45fSAndroid Build Coastguard Worker         size_t mSize;
92*38e8c45fSAndroid Build Coastguard Worker         size_t mPos;
93*38e8c45fSAndroid Build Coastguard Worker         size_t mCtr;
94*38e8c45fSAndroid Build Coastguard Worker     };
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker     /**
97*38e8c45fSAndroid Build Coastguard Worker      * Adds item to the front of this RingBuffer.  If the RingBuffer is at its maximum length,
98*38e8c45fSAndroid Build Coastguard Worker      * this will result in the last element being replaced (this is done using the element's
99*38e8c45fSAndroid Build Coastguard Worker      * assignment operator).
100*38e8c45fSAndroid Build Coastguard Worker      *
101*38e8c45fSAndroid Build Coastguard Worker      * All current iterators are invalidated.
102*38e8c45fSAndroid Build Coastguard Worker      */
103*38e8c45fSAndroid Build Coastguard Worker     void add(const T& item);
104*38e8c45fSAndroid Build Coastguard Worker 
105*38e8c45fSAndroid Build Coastguard Worker     /**
106*38e8c45fSAndroid Build Coastguard Worker      * Moves item to the front of this RingBuffer.  Following a call to this, item should no
107*38e8c45fSAndroid Build Coastguard Worker      * longer be used.  If the RingBuffer is at its maximum length, this will result in the
108*38e8c45fSAndroid Build Coastguard Worker      * last element being replaced (this is done using the element's assignment operator).
109*38e8c45fSAndroid Build Coastguard Worker      *
110*38e8c45fSAndroid Build Coastguard Worker      * All current iterators are invalidated.
111*38e8c45fSAndroid Build Coastguard Worker      */
112*38e8c45fSAndroid Build Coastguard Worker     void add(T&& item);
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker     /**
115*38e8c45fSAndroid Build Coastguard Worker      * Construct item in-place in the front of this RingBuffer using the given arguments.  If
116*38e8c45fSAndroid Build Coastguard Worker      * the RingBuffer is at its maximum length, this will result in the last element being
117*38e8c45fSAndroid Build Coastguard Worker      * replaced (this is done using the element's assignment operator).
118*38e8c45fSAndroid Build Coastguard Worker      *
119*38e8c45fSAndroid Build Coastguard Worker      * All current iterators are invalidated.
120*38e8c45fSAndroid Build Coastguard Worker      */
121*38e8c45fSAndroid Build Coastguard Worker     template <class... Args>
122*38e8c45fSAndroid Build Coastguard Worker     void emplace(Args&&... args);
123*38e8c45fSAndroid Build Coastguard Worker 
124*38e8c45fSAndroid Build Coastguard Worker     /**
125*38e8c45fSAndroid Build Coastguard Worker      * Get an iterator to the front of this RingBuffer.
126*38e8c45fSAndroid Build Coastguard Worker      */
127*38e8c45fSAndroid Build Coastguard Worker     iterator begin();
128*38e8c45fSAndroid Build Coastguard Worker 
129*38e8c45fSAndroid Build Coastguard Worker     /**
130*38e8c45fSAndroid Build Coastguard Worker      * Get an iterator to the end of this RingBuffer.
131*38e8c45fSAndroid Build Coastguard Worker      */
132*38e8c45fSAndroid Build Coastguard Worker     iterator end();
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker     /**
135*38e8c45fSAndroid Build Coastguard Worker      * Get a const_iterator to the front of this RingBuffer.
136*38e8c45fSAndroid Build Coastguard Worker      */
137*38e8c45fSAndroid Build Coastguard Worker     const_iterator begin() const;
138*38e8c45fSAndroid Build Coastguard Worker 
139*38e8c45fSAndroid Build Coastguard Worker     /**
140*38e8c45fSAndroid Build Coastguard Worker      * Get a const_iterator to the end of this RingBuffer.
141*38e8c45fSAndroid Build Coastguard Worker      */
142*38e8c45fSAndroid Build Coastguard Worker     const_iterator end() const;
143*38e8c45fSAndroid Build Coastguard Worker 
144*38e8c45fSAndroid Build Coastguard Worker     /**
145*38e8c45fSAndroid Build Coastguard Worker      * Return a reference to the element at a given index.  If the index is out of range for
146*38e8c45fSAndroid Build Coastguard Worker      * this ringbuffer, [0, size), the behavior for this is undefined.
147*38e8c45fSAndroid Build Coastguard Worker      */
148*38e8c45fSAndroid Build Coastguard Worker     T& operator[](size_t index);
149*38e8c45fSAndroid Build Coastguard Worker 
150*38e8c45fSAndroid Build Coastguard Worker     /**
151*38e8c45fSAndroid Build Coastguard Worker      * Return a const reference to the element at a given index.  If the index is out of range
152*38e8c45fSAndroid Build Coastguard Worker      * for this ringbuffer, [0, size), the behavior for this is undefined.
153*38e8c45fSAndroid Build Coastguard Worker      */
154*38e8c45fSAndroid Build Coastguard Worker     const T& operator[](size_t index) const;
155*38e8c45fSAndroid Build Coastguard Worker 
156*38e8c45fSAndroid Build Coastguard Worker     /**
157*38e8c45fSAndroid Build Coastguard Worker      * Return the current size of this RingBuffer.
158*38e8c45fSAndroid Build Coastguard Worker      */
159*38e8c45fSAndroid Build Coastguard Worker     size_t size() const;
160*38e8c45fSAndroid Build Coastguard Worker 
161*38e8c45fSAndroid Build Coastguard Worker     /**
162*38e8c45fSAndroid Build Coastguard Worker      * Remove all elements from this RingBuffer and set the size to 0.
163*38e8c45fSAndroid Build Coastguard Worker      */
164*38e8c45fSAndroid Build Coastguard Worker     void clear();
165*38e8c45fSAndroid Build Coastguard Worker 
166*38e8c45fSAndroid Build Coastguard Worker private:
167*38e8c45fSAndroid Build Coastguard Worker     size_t mFrontIdx;
168*38e8c45fSAndroid Build Coastguard Worker     size_t mMaxBufferSize;
169*38e8c45fSAndroid Build Coastguard Worker     std::vector<T> mBuffer;
170*38e8c45fSAndroid Build Coastguard Worker }; // class RingBuffer
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker 
173*38e8c45fSAndroid Build Coastguard Worker template <class T>
RingBuffer(size_t length)174*38e8c45fSAndroid Build Coastguard Worker RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {}
175*38e8c45fSAndroid Build Coastguard Worker 
176*38e8c45fSAndroid Build Coastguard Worker template <class T>
iterator(T * ptr,size_t size,size_t pos,size_t ctr)177*38e8c45fSAndroid Build Coastguard Worker RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) :
178*38e8c45fSAndroid Build Coastguard Worker         mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
179*38e8c45fSAndroid Build Coastguard Worker 
180*38e8c45fSAndroid Build Coastguard Worker template <class T>
181*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() {
182*38e8c45fSAndroid Build Coastguard Worker     ++mCtr;
183*38e8c45fSAndroid Build Coastguard Worker 
184*38e8c45fSAndroid Build Coastguard Worker     if (CC_UNLIKELY(mCtr == mSize)) {
185*38e8c45fSAndroid Build Coastguard Worker         mPos = mSize;
186*38e8c45fSAndroid Build Coastguard Worker         return *this;
187*38e8c45fSAndroid Build Coastguard Worker     }
188*38e8c45fSAndroid Build Coastguard Worker 
189*38e8c45fSAndroid Build Coastguard Worker     mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
190*38e8c45fSAndroid Build Coastguard Worker     return *this;
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker 
193*38e8c45fSAndroid Build Coastguard Worker template <class T>
194*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) {
195*38e8c45fSAndroid Build Coastguard Worker     iterator tmp{mPtr, mSize, mPos, mCtr};
196*38e8c45fSAndroid Build Coastguard Worker     ++(*this);
197*38e8c45fSAndroid Build Coastguard Worker     return tmp;
198*38e8c45fSAndroid Build Coastguard Worker }
199*38e8c45fSAndroid Build Coastguard Worker 
200*38e8c45fSAndroid Build Coastguard Worker template <class T>
201*38e8c45fSAndroid Build Coastguard Worker bool RingBuffer<T>::iterator::operator==(const iterator& rhs) {
202*38e8c45fSAndroid Build Coastguard Worker     return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
203*38e8c45fSAndroid Build Coastguard Worker }
204*38e8c45fSAndroid Build Coastguard Worker 
205*38e8c45fSAndroid Build Coastguard Worker template <class T>
206*38e8c45fSAndroid Build Coastguard Worker bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) {
207*38e8c45fSAndroid Build Coastguard Worker     return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker 
210*38e8c45fSAndroid Build Coastguard Worker template <class T>
211*38e8c45fSAndroid Build Coastguard Worker T& RingBuffer<T>::iterator::operator*() {
212*38e8c45fSAndroid Build Coastguard Worker     return *(mPtr + mPos);
213*38e8c45fSAndroid Build Coastguard Worker }
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker template <class T>
216*38e8c45fSAndroid Build Coastguard Worker T* RingBuffer<T>::iterator::operator->() {
217*38e8c45fSAndroid Build Coastguard Worker     return mPtr + mPos;
218*38e8c45fSAndroid Build Coastguard Worker }
219*38e8c45fSAndroid Build Coastguard Worker 
220*38e8c45fSAndroid Build Coastguard Worker template <class T>
const_iterator(const T * ptr,size_t size,size_t pos,size_t ctr)221*38e8c45fSAndroid Build Coastguard Worker RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) :
222*38e8c45fSAndroid Build Coastguard Worker         mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
223*38e8c45fSAndroid Build Coastguard Worker 
224*38e8c45fSAndroid Build Coastguard Worker template <class T>
225*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() {
226*38e8c45fSAndroid Build Coastguard Worker     ++mCtr;
227*38e8c45fSAndroid Build Coastguard Worker 
228*38e8c45fSAndroid Build Coastguard Worker     if (CC_UNLIKELY(mCtr == mSize)) {
229*38e8c45fSAndroid Build Coastguard Worker         mPos = mSize;
230*38e8c45fSAndroid Build Coastguard Worker         return *this;
231*38e8c45fSAndroid Build Coastguard Worker     }
232*38e8c45fSAndroid Build Coastguard Worker 
233*38e8c45fSAndroid Build Coastguard Worker     mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
234*38e8c45fSAndroid Build Coastguard Worker     return *this;
235*38e8c45fSAndroid Build Coastguard Worker }
236*38e8c45fSAndroid Build Coastguard Worker 
237*38e8c45fSAndroid Build Coastguard Worker template <class T>
238*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) {
239*38e8c45fSAndroid Build Coastguard Worker     const_iterator tmp{mPtr, mSize, mPos, mCtr};
240*38e8c45fSAndroid Build Coastguard Worker     ++(*this);
241*38e8c45fSAndroid Build Coastguard Worker     return tmp;
242*38e8c45fSAndroid Build Coastguard Worker }
243*38e8c45fSAndroid Build Coastguard Worker 
244*38e8c45fSAndroid Build Coastguard Worker template <class T>
245*38e8c45fSAndroid Build Coastguard Worker bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) {
246*38e8c45fSAndroid Build Coastguard Worker     return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
247*38e8c45fSAndroid Build Coastguard Worker }
248*38e8c45fSAndroid Build Coastguard Worker 
249*38e8c45fSAndroid Build Coastguard Worker template <class T>
250*38e8c45fSAndroid Build Coastguard Worker bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) {
251*38e8c45fSAndroid Build Coastguard Worker     return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
252*38e8c45fSAndroid Build Coastguard Worker }
253*38e8c45fSAndroid Build Coastguard Worker 
254*38e8c45fSAndroid Build Coastguard Worker template <class T>
255*38e8c45fSAndroid Build Coastguard Worker const T& RingBuffer<T>::const_iterator::operator*() {
256*38e8c45fSAndroid Build Coastguard Worker     return *(mPtr + mPos);
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker 
259*38e8c45fSAndroid Build Coastguard Worker template <class T>
260*38e8c45fSAndroid Build Coastguard Worker const T* RingBuffer<T>::const_iterator::operator->() {
261*38e8c45fSAndroid Build Coastguard Worker     return mPtr + mPos;
262*38e8c45fSAndroid Build Coastguard Worker }
263*38e8c45fSAndroid Build Coastguard Worker 
264*38e8c45fSAndroid Build Coastguard Worker template <class T>
add(const T & item)265*38e8c45fSAndroid Build Coastguard Worker void RingBuffer<T>::add(const T& item) {
266*38e8c45fSAndroid Build Coastguard Worker     if (mBuffer.size() < mMaxBufferSize) {
267*38e8c45fSAndroid Build Coastguard Worker         mBuffer.push_back(item);
268*38e8c45fSAndroid Build Coastguard Worker         mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
269*38e8c45fSAndroid Build Coastguard Worker         return;
270*38e8c45fSAndroid Build Coastguard Worker     }
271*38e8c45fSAndroid Build Coastguard Worker 
272*38e8c45fSAndroid Build Coastguard Worker     mBuffer[mFrontIdx] = item;
273*38e8c45fSAndroid Build Coastguard Worker     mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
274*38e8c45fSAndroid Build Coastguard Worker }
275*38e8c45fSAndroid Build Coastguard Worker 
276*38e8c45fSAndroid Build Coastguard Worker template <class T>
add(T && item)277*38e8c45fSAndroid Build Coastguard Worker void RingBuffer<T>::add(T&& item) {
278*38e8c45fSAndroid Build Coastguard Worker     if (mBuffer.size() != mMaxBufferSize) {
279*38e8c45fSAndroid Build Coastguard Worker         mBuffer.push_back(std::forward<T>(item));
280*38e8c45fSAndroid Build Coastguard Worker         mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
281*38e8c45fSAndroid Build Coastguard Worker         return;
282*38e8c45fSAndroid Build Coastguard Worker     }
283*38e8c45fSAndroid Build Coastguard Worker 
284*38e8c45fSAndroid Build Coastguard Worker     // Only works for types with move assignment operator
285*38e8c45fSAndroid Build Coastguard Worker     mBuffer[mFrontIdx] = std::forward<T>(item);
286*38e8c45fSAndroid Build Coastguard Worker     mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
287*38e8c45fSAndroid Build Coastguard Worker }
288*38e8c45fSAndroid Build Coastguard Worker 
289*38e8c45fSAndroid Build Coastguard Worker template <class T>
290*38e8c45fSAndroid Build Coastguard Worker template <class... Args>
emplace(Args &&...args)291*38e8c45fSAndroid Build Coastguard Worker void RingBuffer<T>::emplace(Args&&... args) {
292*38e8c45fSAndroid Build Coastguard Worker     if (mBuffer.size() != mMaxBufferSize) {
293*38e8c45fSAndroid Build Coastguard Worker         mBuffer.emplace_back(std::forward<Args>(args)...);
294*38e8c45fSAndroid Build Coastguard Worker         mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
295*38e8c45fSAndroid Build Coastguard Worker         return;
296*38e8c45fSAndroid Build Coastguard Worker     }
297*38e8c45fSAndroid Build Coastguard Worker 
298*38e8c45fSAndroid Build Coastguard Worker     // Only works for types with move assignment operator
299*38e8c45fSAndroid Build Coastguard Worker     mBuffer[mFrontIdx] = T(std::forward<Args>(args)...);
300*38e8c45fSAndroid Build Coastguard Worker     mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
301*38e8c45fSAndroid Build Coastguard Worker }
302*38e8c45fSAndroid Build Coastguard Worker 
303*38e8c45fSAndroid Build Coastguard Worker template <class T>
begin()304*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::iterator RingBuffer<T>::begin() {
305*38e8c45fSAndroid Build Coastguard Worker     size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
306*38e8c45fSAndroid Build Coastguard Worker     return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
307*38e8c45fSAndroid Build Coastguard Worker }
308*38e8c45fSAndroid Build Coastguard Worker 
309*38e8c45fSAndroid Build Coastguard Worker template <class T>
end()310*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::iterator RingBuffer<T>::end() {
311*38e8c45fSAndroid Build Coastguard Worker     size_t s = mBuffer.size();
312*38e8c45fSAndroid Build Coastguard Worker     return iterator(mBuffer.data(), s, s, s);
313*38e8c45fSAndroid Build Coastguard Worker }
314*38e8c45fSAndroid Build Coastguard Worker 
315*38e8c45fSAndroid Build Coastguard Worker template <class T>
begin()316*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const {
317*38e8c45fSAndroid Build Coastguard Worker     size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
318*38e8c45fSAndroid Build Coastguard Worker     return const_iterator(mBuffer.data(), mBuffer.size(),
319*38e8c45fSAndroid Build Coastguard Worker             (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
320*38e8c45fSAndroid Build Coastguard Worker }
321*38e8c45fSAndroid Build Coastguard Worker 
322*38e8c45fSAndroid Build Coastguard Worker template <class T>
end()323*38e8c45fSAndroid Build Coastguard Worker typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const {
324*38e8c45fSAndroid Build Coastguard Worker     size_t s = mBuffer.size();
325*38e8c45fSAndroid Build Coastguard Worker     return const_iterator(mBuffer.data(), s, s, s);
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker 
328*38e8c45fSAndroid Build Coastguard Worker template <class T>
329*38e8c45fSAndroid Build Coastguard Worker T& RingBuffer<T>::operator[](size_t index) {
330*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
331*38e8c45fSAndroid Build Coastguard Worker             index, mBuffer.size());
332*38e8c45fSAndroid Build Coastguard Worker     size_t pos = (index >= mFrontIdx) ?
333*38e8c45fSAndroid Build Coastguard Worker             mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
334*38e8c45fSAndroid Build Coastguard Worker     return mBuffer[pos];
335*38e8c45fSAndroid Build Coastguard Worker }
336*38e8c45fSAndroid Build Coastguard Worker 
337*38e8c45fSAndroid Build Coastguard Worker template <class T>
338*38e8c45fSAndroid Build Coastguard Worker const T& RingBuffer<T>::operator[](size_t index) const {
339*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
340*38e8c45fSAndroid Build Coastguard Worker             index, mBuffer.size());
341*38e8c45fSAndroid Build Coastguard Worker     size_t pos = (index >= mFrontIdx) ?
342*38e8c45fSAndroid Build Coastguard Worker             mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
343*38e8c45fSAndroid Build Coastguard Worker     return mBuffer[pos];
344*38e8c45fSAndroid Build Coastguard Worker }
345*38e8c45fSAndroid Build Coastguard Worker 
346*38e8c45fSAndroid Build Coastguard Worker template <class T>
size()347*38e8c45fSAndroid Build Coastguard Worker size_t RingBuffer<T>::size() const {
348*38e8c45fSAndroid Build Coastguard Worker     return mBuffer.size();
349*38e8c45fSAndroid Build Coastguard Worker }
350*38e8c45fSAndroid Build Coastguard Worker 
351*38e8c45fSAndroid Build Coastguard Worker template <class T>
clear()352*38e8c45fSAndroid Build Coastguard Worker void RingBuffer<T>::clear() {
353*38e8c45fSAndroid Build Coastguard Worker     mBuffer.clear();
354*38e8c45fSAndroid Build Coastguard Worker     mFrontIdx = 0;
355*38e8c45fSAndroid Build Coastguard Worker }
356*38e8c45fSAndroid Build Coastguard Worker 
357*38e8c45fSAndroid Build Coastguard Worker }  // namespace SensorServiceUtil
358*38e8c45fSAndroid Build Coastguard Worker }; // namespace android
359*38e8c45fSAndroid Build Coastguard Worker 
360*38e8c45fSAndroid Build Coastguard Worker #endif // ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
361*38e8c45fSAndroid Build Coastguard Worker 
362