RingBuffer.h
Go to the documentation of this file.00001 /******************************************************************************* 00002 * 00003 * Copyright (c) 2010 Philipp Werner <philipp.werner@st.ovgu.de> 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * * Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * * Neither the name of the copyright holders nor the names of 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00024 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00025 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00026 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00027 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * 00036 * $Id$ 00037 * 00038 ******************************************************************************/ 00039 00040 #ifndef __RINGBUFFER_H_E7CCEE63FC08A7__ 00041 #define __RINGBUFFER_H_E7CCEE63FC08A7__ 00042 00043 00044 #include "debug.h" 00045 #include "config/type_traits/SmallestUnsignedTypeSelector.h" 00046 #include "config/type_traits/ExpandedRangeTypeSelector.h" 00047 00048 00049 namespace object { 00050 00057 template <class T, unsigned int N> 00058 class RingBuffer { 00059 public: 00060 00062 typedef typename SmallestUnsignedTypeSelector<N>::type SizeT; 00063 00064 protected: 00065 00067 typedef typename ExpandedRangeTypeSelector<SizeT>::type DoubleSizeT; 00068 00070 T buffer[N]; 00071 00073 SizeT first; 00074 00076 SizeT count; 00077 00078 00085 SizeT get_idx(SizeT num) const { 00086 FAMOUSO_ASSERT(num < N); 00087 // Avoid overflow of SizeT 00088 DoubleSizeT idx = (DoubleSizeT)(first) + (DoubleSizeT)(num); 00089 // Handle overflow over element count (N) 00090 // Avoid modulo because it is expensive on AVR 00091 if (idx < N) 00092 return idx; 00093 else 00094 return idx - N; 00095 } 00096 00098 void increment_first() { 00099 // Avoid modulo because it is expensive on AVR 00100 if (first == N-1) 00101 first = 0; 00102 else 00103 first++; 00104 } 00105 00107 void decrement_first() { 00108 // Avoid modulo because it is expensive on AVR 00109 if (first == 0) 00110 first = N-1; 00111 else 00112 first--; 00113 } 00114 00116 SizeT get_last() const { 00117 FAMOUSO_ASSERT(!is_empty()); 00118 return get_idx(count - 1); 00119 } 00120 00122 SizeT get_behind_last() const { 00123 return get_idx(count); 00124 } 00125 00127 SizeT get_infront_first() const { 00128 return get_idx(N-1); 00129 } 00130 00131 public: 00133 RingBuffer() : 00134 first(0), count(0) { 00135 } 00136 00138 SizeT get_count() const { 00139 return count; 00140 } 00141 00143 bool is_empty() const { 00144 return count == 0; 00145 } 00146 00148 bool is_full() const { 00149 return count == N; 00150 } 00151 00156 T & front() { 00157 FAMOUSO_ASSERT(!is_empty()); 00158 return buffer[first]; 00159 } 00160 00165 const T & front() const { 00166 FAMOUSO_ASSERT(!is_empty()); 00167 return buffer[first]; 00168 } 00169 00174 T & back() { 00175 return buffer[get_last()]; 00176 } 00177 00182 const T & back() const { 00183 return buffer[get_last()]; 00184 } 00185 00191 T & operator[] (SizeT i) { 00192 return buffer[get_idx(i)]; 00193 } 00194 00200 const T & operator[] (SizeT i) const { 00201 return buffer[get_idx(i)]; 00202 } 00203 00209 void push_front(const T & obj) { 00210 FAMOUSO_ASSERT(!is_full()); 00211 buffer[get_infront_first()] = obj; 00212 decrement_first(); 00213 count++; 00214 } 00215 00221 void push_back(const T & obj) { 00222 FAMOUSO_ASSERT(!is_full()); 00223 buffer[get_behind_last()] = obj; 00224 count++; 00225 } 00226 00231 void pop_front() { 00232 FAMOUSO_ASSERT(!is_empty()); 00233 increment_first(); 00234 count--; 00235 } 00236 00241 void pop_back() { 00242 FAMOUSO_ASSERT(!is_empty()); 00243 count--; 00244 } 00245 }; 00246 00247 } // namespace object 00248 00249 00250 #endif // __RINGBUFFER_H_E7CCEE63FC08A7__ 00251