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