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