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