xref: /aosp_15_r20/frameworks/native/include/input/RingBuffer.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2023 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 #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <algorithm>
20*38e8c45fSAndroid Build Coastguard Worker #include <compare>
21*38e8c45fSAndroid Build Coastguard Worker #include <cstddef>
22*38e8c45fSAndroid Build Coastguard Worker #include <iterator>
23*38e8c45fSAndroid Build Coastguard Worker #include <memory>
24*38e8c45fSAndroid Build Coastguard Worker #include <type_traits>
25*38e8c45fSAndroid Build Coastguard Worker #include <utility>
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker namespace android {
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker // A fixed-size ring buffer of elements.
32*38e8c45fSAndroid Build Coastguard Worker //
33*38e8c45fSAndroid Build Coastguard Worker // Elements can only be removed from the front/back or added to the front/back, but with O(1)
34*38e8c45fSAndroid Build Coastguard Worker // performance. Elements from the opposing side are evicted when new elements are pushed onto a full
35*38e8c45fSAndroid Build Coastguard Worker // buffer.
36*38e8c45fSAndroid Build Coastguard Worker template <typename T>
37*38e8c45fSAndroid Build Coastguard Worker class RingBuffer {
38*38e8c45fSAndroid Build Coastguard Worker public:
39*38e8c45fSAndroid Build Coastguard Worker     using value_type = T;
40*38e8c45fSAndroid Build Coastguard Worker     using size_type = size_t;
41*38e8c45fSAndroid Build Coastguard Worker     using difference_type = ptrdiff_t;
42*38e8c45fSAndroid Build Coastguard Worker     using reference = value_type&;
43*38e8c45fSAndroid Build Coastguard Worker     using const_reference = const value_type&;
44*38e8c45fSAndroid Build Coastguard Worker     using pointer = value_type*;
45*38e8c45fSAndroid Build Coastguard Worker     using const_pointer = const value_type*;
46*38e8c45fSAndroid Build Coastguard Worker 
47*38e8c45fSAndroid Build Coastguard Worker     template <typename U>
48*38e8c45fSAndroid Build Coastguard Worker     class Iterator;
49*38e8c45fSAndroid Build Coastguard Worker     using iterator = Iterator<T>;
50*38e8c45fSAndroid Build Coastguard Worker     using const_iterator = Iterator<const T>;
51*38e8c45fSAndroid Build Coastguard Worker 
52*38e8c45fSAndroid Build Coastguard Worker     // Creates an empty ring buffer that can hold some capacity.
RingBuffer(size_type capacity)53*38e8c45fSAndroid Build Coastguard Worker     explicit RingBuffer(size_type capacity)
54*38e8c45fSAndroid Build Coastguard Worker           : mBuffer(std::allocator<value_type>().allocate(capacity)), mCapacity(capacity) {}
55*38e8c45fSAndroid Build Coastguard Worker 
56*38e8c45fSAndroid Build Coastguard Worker     // Creates a full ring buffer holding a fixed number of elements initialised to some value.
RingBuffer(size_type count,const_reference value)57*38e8c45fSAndroid Build Coastguard Worker     explicit RingBuffer(size_type count, const_reference value) : RingBuffer(count) {
58*38e8c45fSAndroid Build Coastguard Worker         while (count) {
59*38e8c45fSAndroid Build Coastguard Worker             pushBack(value);
60*38e8c45fSAndroid Build Coastguard Worker             --count;
61*38e8c45fSAndroid Build Coastguard Worker         }
62*38e8c45fSAndroid Build Coastguard Worker     }
63*38e8c45fSAndroid Build Coastguard Worker 
RingBuffer(const RingBuffer & other)64*38e8c45fSAndroid Build Coastguard Worker     RingBuffer(const RingBuffer& other) : RingBuffer(other.capacity()) {
65*38e8c45fSAndroid Build Coastguard Worker         for (const auto& element : other) {
66*38e8c45fSAndroid Build Coastguard Worker             pushBack(element);
67*38e8c45fSAndroid Build Coastguard Worker         }
68*38e8c45fSAndroid Build Coastguard Worker     }
69*38e8c45fSAndroid Build Coastguard Worker 
RingBuffer(RingBuffer && other)70*38e8c45fSAndroid Build Coastguard Worker     RingBuffer(RingBuffer&& other) noexcept { *this = std::move(other); }
71*38e8c45fSAndroid Build Coastguard Worker 
~RingBuffer()72*38e8c45fSAndroid Build Coastguard Worker     ~RingBuffer() {
73*38e8c45fSAndroid Build Coastguard Worker         if (mBuffer) {
74*38e8c45fSAndroid Build Coastguard Worker             clear();
75*38e8c45fSAndroid Build Coastguard Worker             std::allocator<value_type>().deallocate(mBuffer, mCapacity);
76*38e8c45fSAndroid Build Coastguard Worker         }
77*38e8c45fSAndroid Build Coastguard Worker     }
78*38e8c45fSAndroid Build Coastguard Worker 
79*38e8c45fSAndroid Build Coastguard Worker     RingBuffer& operator=(const RingBuffer& other) { return *this = RingBuffer(other); }
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker     RingBuffer& operator=(RingBuffer&& other) noexcept {
82*38e8c45fSAndroid Build Coastguard Worker         if (this == &other) {
83*38e8c45fSAndroid Build Coastguard Worker             return *this;
84*38e8c45fSAndroid Build Coastguard Worker         }
85*38e8c45fSAndroid Build Coastguard Worker         if (mBuffer) {
86*38e8c45fSAndroid Build Coastguard Worker             clear();
87*38e8c45fSAndroid Build Coastguard Worker             std::allocator<value_type>().deallocate(mBuffer, mCapacity);
88*38e8c45fSAndroid Build Coastguard Worker         }
89*38e8c45fSAndroid Build Coastguard Worker         mBuffer = std::move(other.mBuffer);
90*38e8c45fSAndroid Build Coastguard Worker         mCapacity = other.mCapacity;
91*38e8c45fSAndroid Build Coastguard Worker         mBegin = other.mBegin;
92*38e8c45fSAndroid Build Coastguard Worker         mSize = other.mSize;
93*38e8c45fSAndroid Build Coastguard Worker         other.mBuffer = nullptr;
94*38e8c45fSAndroid Build Coastguard Worker         other.mCapacity = 0;
95*38e8c45fSAndroid Build Coastguard Worker         other.mBegin = 0;
96*38e8c45fSAndroid Build Coastguard Worker         other.mSize = 0;
97*38e8c45fSAndroid Build Coastguard Worker         return *this;
98*38e8c45fSAndroid Build Coastguard Worker     }
99*38e8c45fSAndroid Build Coastguard Worker 
begin()100*38e8c45fSAndroid Build Coastguard Worker     iterator begin() { return {*this, 0}; }
begin()101*38e8c45fSAndroid Build Coastguard Worker     const_iterator begin() const { return {*this, 0}; }
end()102*38e8c45fSAndroid Build Coastguard Worker     iterator end() { return {*this, mSize}; }
end()103*38e8c45fSAndroid Build Coastguard Worker     const_iterator end() const { return {*this, mSize}; }
104*38e8c45fSAndroid Build Coastguard Worker 
front()105*38e8c45fSAndroid Build Coastguard Worker     reference front() { return mBuffer[mBegin]; }
front()106*38e8c45fSAndroid Build Coastguard Worker     const_reference front() const { return mBuffer[mBegin]; }
back()107*38e8c45fSAndroid Build Coastguard Worker     reference back() { return mBuffer[bufferIndex(mSize - 1)]; }
back()108*38e8c45fSAndroid Build Coastguard Worker     const_reference back() const { return mBuffer[bufferIndex(mSize - 1)]; }
109*38e8c45fSAndroid Build Coastguard Worker 
110*38e8c45fSAndroid Build Coastguard Worker     reference operator[](size_type i) { return mBuffer[bufferIndex(i)]; }
111*38e8c45fSAndroid Build Coastguard Worker     const_reference operator[](size_type i) const { return mBuffer[bufferIndex(i)]; }
112*38e8c45fSAndroid Build Coastguard Worker 
113*38e8c45fSAndroid Build Coastguard Worker     // Removes all elements from the buffer.
clear()114*38e8c45fSAndroid Build Coastguard Worker     void clear() {
115*38e8c45fSAndroid Build Coastguard Worker         std::destroy(begin(), end());
116*38e8c45fSAndroid Build Coastguard Worker         mSize = 0;
117*38e8c45fSAndroid Build Coastguard Worker     }
118*38e8c45fSAndroid Build Coastguard Worker 
119*38e8c45fSAndroid Build Coastguard Worker     // Removes and returns the first element from the buffer.
popFront()120*38e8c45fSAndroid Build Coastguard Worker     value_type popFront() {
121*38e8c45fSAndroid Build Coastguard Worker         value_type element = mBuffer[mBegin];
122*38e8c45fSAndroid Build Coastguard Worker         std::destroy_at(std::addressof(mBuffer[mBegin]));
123*38e8c45fSAndroid Build Coastguard Worker         mBegin = next(mBegin);
124*38e8c45fSAndroid Build Coastguard Worker         --mSize;
125*38e8c45fSAndroid Build Coastguard Worker         return element;
126*38e8c45fSAndroid Build Coastguard Worker     }
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     // Removes and returns the last element from the buffer.
popBack()129*38e8c45fSAndroid Build Coastguard Worker     value_type popBack() {
130*38e8c45fSAndroid Build Coastguard Worker         size_type backIndex = bufferIndex(mSize - 1);
131*38e8c45fSAndroid Build Coastguard Worker         value_type element = mBuffer[backIndex];
132*38e8c45fSAndroid Build Coastguard Worker         std::destroy_at(std::addressof(mBuffer[backIndex]));
133*38e8c45fSAndroid Build Coastguard Worker         --mSize;
134*38e8c45fSAndroid Build Coastguard Worker         return element;
135*38e8c45fSAndroid Build Coastguard Worker     }
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     // Adds an element to the front of the buffer.
pushFront(const value_type & element)138*38e8c45fSAndroid Build Coastguard Worker     void pushFront(const value_type& element) { pushFront(value_type(element)); }
pushFront(value_type && element)139*38e8c45fSAndroid Build Coastguard Worker     void pushFront(value_type&& element) {
140*38e8c45fSAndroid Build Coastguard Worker         mBegin = previous(mBegin);
141*38e8c45fSAndroid Build Coastguard Worker         if (size() == capacity()) {
142*38e8c45fSAndroid Build Coastguard Worker             mBuffer[mBegin] = std::forward<value_type>(element);
143*38e8c45fSAndroid Build Coastguard Worker         } else {
144*38e8c45fSAndroid Build Coastguard Worker             // The space at mBuffer[mBegin] is uninitialised.
145*38e8c45fSAndroid Build Coastguard Worker             // TODO: Use std::construct_at when it becomes available.
146*38e8c45fSAndroid Build Coastguard Worker             new (std::addressof(mBuffer[mBegin])) value_type(std::forward<value_type>(element));
147*38e8c45fSAndroid Build Coastguard Worker             ++mSize;
148*38e8c45fSAndroid Build Coastguard Worker         }
149*38e8c45fSAndroid Build Coastguard Worker     }
150*38e8c45fSAndroid Build Coastguard Worker 
151*38e8c45fSAndroid Build Coastguard Worker     // Adds an element to the back of the buffer.
pushBack(const value_type & element)152*38e8c45fSAndroid Build Coastguard Worker     void pushBack(const value_type& element) { pushBack(value_type(element)); }
pushBack(value_type && element)153*38e8c45fSAndroid Build Coastguard Worker     void pushBack(value_type&& element) {
154*38e8c45fSAndroid Build Coastguard Worker         if (size() == capacity()) {
155*38e8c45fSAndroid Build Coastguard Worker             mBuffer[mBegin] = std::forward<value_type>(element);
156*38e8c45fSAndroid Build Coastguard Worker             mBegin = next(mBegin);
157*38e8c45fSAndroid Build Coastguard Worker         } else {
158*38e8c45fSAndroid Build Coastguard Worker             // The space at mBuffer[...] is uninitialised.
159*38e8c45fSAndroid Build Coastguard Worker             // TODO: Use std::construct_at when it becomes available.
160*38e8c45fSAndroid Build Coastguard Worker             new (std::addressof(mBuffer[bufferIndex(mSize)]))
161*38e8c45fSAndroid Build Coastguard Worker                     value_type(std::forward<value_type>(element));
162*38e8c45fSAndroid Build Coastguard Worker             ++mSize;
163*38e8c45fSAndroid Build Coastguard Worker         }
164*38e8c45fSAndroid Build Coastguard Worker     }
165*38e8c45fSAndroid Build Coastguard Worker 
empty()166*38e8c45fSAndroid Build Coastguard Worker     bool empty() const { return mSize == 0; }
capacity()167*38e8c45fSAndroid Build Coastguard Worker     size_type capacity() const { return mCapacity; }
size()168*38e8c45fSAndroid Build Coastguard Worker     size_type size() const { return mSize; }
169*38e8c45fSAndroid Build Coastguard Worker 
swap(RingBuffer & other)170*38e8c45fSAndroid Build Coastguard Worker     void swap(RingBuffer& other) noexcept {
171*38e8c45fSAndroid Build Coastguard Worker         using std::swap;
172*38e8c45fSAndroid Build Coastguard Worker         swap(mBuffer, other.mBuffer);
173*38e8c45fSAndroid Build Coastguard Worker         swap(mCapacity, other.mCapacity);
174*38e8c45fSAndroid Build Coastguard Worker         swap(mBegin, other.mBegin);
175*38e8c45fSAndroid Build Coastguard Worker         swap(mSize, other.mSize);
176*38e8c45fSAndroid Build Coastguard Worker     }
177*38e8c45fSAndroid Build Coastguard Worker 
swap(RingBuffer & lhs,RingBuffer & rhs)178*38e8c45fSAndroid Build Coastguard Worker     friend void swap(RingBuffer& lhs, RingBuffer& rhs) noexcept { lhs.swap(rhs); }
179*38e8c45fSAndroid Build Coastguard Worker 
180*38e8c45fSAndroid Build Coastguard Worker     template <typename U>
181*38e8c45fSAndroid Build Coastguard Worker     class Iterator {
182*38e8c45fSAndroid Build Coastguard Worker     private:
183*38e8c45fSAndroid Build Coastguard Worker         using ContainerType = std::conditional_t<std::is_const_v<U>, const RingBuffer, RingBuffer>;
184*38e8c45fSAndroid Build Coastguard Worker 
185*38e8c45fSAndroid Build Coastguard Worker     public:
186*38e8c45fSAndroid Build Coastguard Worker         using iterator_category = std::random_access_iterator_tag;
187*38e8c45fSAndroid Build Coastguard Worker         using size_type = ContainerType::size_type;
188*38e8c45fSAndroid Build Coastguard Worker         using difference_type = ContainerType::difference_type;
189*38e8c45fSAndroid Build Coastguard Worker         using value_type = std::remove_cv_t<U>;
190*38e8c45fSAndroid Build Coastguard Worker         using pointer = U*;
191*38e8c45fSAndroid Build Coastguard Worker         using reference = U&;
192*38e8c45fSAndroid Build Coastguard Worker 
Iterator(ContainerType & container,size_type index)193*38e8c45fSAndroid Build Coastguard Worker         Iterator(ContainerType& container, size_type index)
194*38e8c45fSAndroid Build Coastguard Worker               : mContainer(container), mIndex(index) {}
195*38e8c45fSAndroid Build Coastguard Worker 
196*38e8c45fSAndroid Build Coastguard Worker         Iterator(const Iterator&) = default;
197*38e8c45fSAndroid Build Coastguard Worker         Iterator& operator=(const Iterator&) = default;
198*38e8c45fSAndroid Build Coastguard Worker 
199*38e8c45fSAndroid Build Coastguard Worker         Iterator& operator++() {
200*38e8c45fSAndroid Build Coastguard Worker             ++mIndex;
201*38e8c45fSAndroid Build Coastguard Worker             return *this;
202*38e8c45fSAndroid Build Coastguard Worker         }
203*38e8c45fSAndroid Build Coastguard Worker 
204*38e8c45fSAndroid Build Coastguard Worker         Iterator operator++(int) {
205*38e8c45fSAndroid Build Coastguard Worker             Iterator iterator(*this);
206*38e8c45fSAndroid Build Coastguard Worker             ++(*this);
207*38e8c45fSAndroid Build Coastguard Worker             return iterator;
208*38e8c45fSAndroid Build Coastguard Worker         }
209*38e8c45fSAndroid Build Coastguard Worker 
210*38e8c45fSAndroid Build Coastguard Worker         Iterator& operator--() {
211*38e8c45fSAndroid Build Coastguard Worker             --mIndex;
212*38e8c45fSAndroid Build Coastguard Worker             return *this;
213*38e8c45fSAndroid Build Coastguard Worker         }
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker         Iterator operator--(int) {
216*38e8c45fSAndroid Build Coastguard Worker             Iterator iterator(*this);
217*38e8c45fSAndroid Build Coastguard Worker             --(*this);
218*38e8c45fSAndroid Build Coastguard Worker             return iterator;
219*38e8c45fSAndroid Build Coastguard Worker         }
220*38e8c45fSAndroid Build Coastguard Worker 
221*38e8c45fSAndroid Build Coastguard Worker         Iterator& operator+=(difference_type n) {
222*38e8c45fSAndroid Build Coastguard Worker             mIndex += n;
223*38e8c45fSAndroid Build Coastguard Worker             return *this;
224*38e8c45fSAndroid Build Coastguard Worker         }
225*38e8c45fSAndroid Build Coastguard Worker 
226*38e8c45fSAndroid Build Coastguard Worker         Iterator operator+(difference_type n) {
227*38e8c45fSAndroid Build Coastguard Worker             Iterator iterator(*this);
228*38e8c45fSAndroid Build Coastguard Worker             return iterator += n;
229*38e8c45fSAndroid Build Coastguard Worker         }
230*38e8c45fSAndroid Build Coastguard Worker 
231*38e8c45fSAndroid Build Coastguard Worker         Iterator& operator-=(difference_type n) { return *this += -n; }
232*38e8c45fSAndroid Build Coastguard Worker 
233*38e8c45fSAndroid Build Coastguard Worker         Iterator operator-(difference_type n) {
234*38e8c45fSAndroid Build Coastguard Worker             Iterator iterator(*this);
235*38e8c45fSAndroid Build Coastguard Worker             return iterator -= n;
236*38e8c45fSAndroid Build Coastguard Worker         }
237*38e8c45fSAndroid Build Coastguard Worker 
238*38e8c45fSAndroid Build Coastguard Worker         difference_type operator-(const Iterator& other) { return mIndex - other.mIndex; }
239*38e8c45fSAndroid Build Coastguard Worker 
240*38e8c45fSAndroid Build Coastguard Worker         bool operator==(const Iterator& rhs) const { return mIndex == rhs.mIndex; }
241*38e8c45fSAndroid Build Coastguard Worker 
242*38e8c45fSAndroid Build Coastguard Worker         bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
243*38e8c45fSAndroid Build Coastguard Worker 
244*38e8c45fSAndroid Build Coastguard Worker         friend auto operator<=>(const Iterator& lhs, const Iterator& rhs) {
245*38e8c45fSAndroid Build Coastguard Worker             return lhs.mIndex <=> rhs.mIndex;
246*38e8c45fSAndroid Build Coastguard Worker         }
247*38e8c45fSAndroid Build Coastguard Worker 
248*38e8c45fSAndroid Build Coastguard Worker         reference operator[](difference_type n) { return *(*this + n); }
249*38e8c45fSAndroid Build Coastguard Worker 
250*38e8c45fSAndroid Build Coastguard Worker         reference operator*() const { return mContainer[mIndex]; }
251*38e8c45fSAndroid Build Coastguard Worker         pointer operator->() const { return std::addressof(mContainer[mIndex]); }
252*38e8c45fSAndroid Build Coastguard Worker 
253*38e8c45fSAndroid Build Coastguard Worker     private:
254*38e8c45fSAndroid Build Coastguard Worker         ContainerType& mContainer;
255*38e8c45fSAndroid Build Coastguard Worker         size_type mIndex = 0;
256*38e8c45fSAndroid Build Coastguard Worker     };
257*38e8c45fSAndroid Build Coastguard Worker 
258*38e8c45fSAndroid Build Coastguard Worker private:
259*38e8c45fSAndroid Build Coastguard Worker     // Returns the index of the next element in mBuffer.
next(size_type index)260*38e8c45fSAndroid Build Coastguard Worker     size_type next(size_type index) const {
261*38e8c45fSAndroid Build Coastguard Worker         if (index == capacity() - 1) {
262*38e8c45fSAndroid Build Coastguard Worker             return 0;
263*38e8c45fSAndroid Build Coastguard Worker         } else {
264*38e8c45fSAndroid Build Coastguard Worker             return index + 1;
265*38e8c45fSAndroid Build Coastguard Worker         }
266*38e8c45fSAndroid Build Coastguard Worker     }
267*38e8c45fSAndroid Build Coastguard Worker 
268*38e8c45fSAndroid Build Coastguard Worker     // Returns the index of the previous element in mBuffer.
previous(size_type index)269*38e8c45fSAndroid Build Coastguard Worker     size_type previous(size_type index) const {
270*38e8c45fSAndroid Build Coastguard Worker         if (index == 0) {
271*38e8c45fSAndroid Build Coastguard Worker             return capacity() - 1;
272*38e8c45fSAndroid Build Coastguard Worker         } else {
273*38e8c45fSAndroid Build Coastguard Worker             return index - 1;
274*38e8c45fSAndroid Build Coastguard Worker         }
275*38e8c45fSAndroid Build Coastguard Worker     }
276*38e8c45fSAndroid Build Coastguard Worker 
277*38e8c45fSAndroid Build Coastguard Worker     // Converts the index of an element in [0, size()] to its corresponding index in mBuffer.
bufferIndex(size_type elementIndex)278*38e8c45fSAndroid Build Coastguard Worker     size_type bufferIndex(size_type elementIndex) const {
279*38e8c45fSAndroid Build Coastguard Worker         if (elementIndex > size()) {
280*38e8c45fSAndroid Build Coastguard Worker             abort();
281*38e8c45fSAndroid Build Coastguard Worker         }
282*38e8c45fSAndroid Build Coastguard Worker         size_type index = mBegin + elementIndex;
283*38e8c45fSAndroid Build Coastguard Worker         if (index >= capacity()) {
284*38e8c45fSAndroid Build Coastguard Worker             index -= capacity();
285*38e8c45fSAndroid Build Coastguard Worker         }
286*38e8c45fSAndroid Build Coastguard Worker         if (index >= capacity()) {
287*38e8c45fSAndroid Build Coastguard Worker             abort();
288*38e8c45fSAndroid Build Coastguard Worker         }
289*38e8c45fSAndroid Build Coastguard Worker         return index;
290*38e8c45fSAndroid Build Coastguard Worker     }
291*38e8c45fSAndroid Build Coastguard Worker 
292*38e8c45fSAndroid Build Coastguard Worker     pointer mBuffer = nullptr;
293*38e8c45fSAndroid Build Coastguard Worker     size_type mCapacity = 0; // Total capacity of mBuffer.
294*38e8c45fSAndroid Build Coastguard Worker     size_type mBegin = 0;    // Index of the first initialised element in mBuffer.
295*38e8c45fSAndroid Build Coastguard Worker     size_type mSize = 0;     // Total number of initialised elements.
296*38e8c45fSAndroid Build Coastguard Worker };
297*38e8c45fSAndroid Build Coastguard Worker 
298*38e8c45fSAndroid Build Coastguard Worker } // namespace android
299