00001 // ***************************************************************************** 00002 // 00003 // Copyright (c) 2014, Southwest Research Institute® (SwRI®) 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 are met: 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above copyright 00011 // notice, this list of conditions and the following disclaimer in the 00012 // documentation and/or other materials provided with the distribution. 00013 // * Neither the name of Southwest Research Institute® (SwRI®) nor the 00014 // names of its contributors may be used to endorse or promote products 00015 // derived from this software without specific prior written permission. 00016 // 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 // 00028 // ***************************************************************************** 00029 00030 #ifndef MATH_UTIL_GENERIC_RING_BUFFER_H_ 00031 #define MATH_UTIL_GENERIC_RING_BUFFER_H_ 00032 #ifndef NULL 00033 #define NULL 0 00034 #endif 00035 #define GEN_RING_BUFF_DEFAULT_NUM_ELEMENTS 16 00036 00037 #include <cassert> 00038 #include <algorithm> 00039 00040 namespace swri_math_util 00041 { 00042 template <class T> 00043 class GenRingBuffer 00044 { 00045 public: 00046 // Default constructor 00047 GenRingBuffer() 00048 { 00049 NumElements = 0; 00050 this->alloc_mem(GEN_RING_BUFF_DEFAULT_NUM_ELEMENTS); 00051 this->init_array(); 00052 } 00053 00054 explicit GenRingBuffer(int NumElements2Alloc) 00055 { 00056 NumElements = 0; 00057 this->alloc_mem(NumElements2Alloc); 00058 this->init_array(); 00059 } 00060 00061 GenRingBuffer(const GenRingBuffer<T>& src) 00062 { 00063 this->alloc_mem(src.MaxNumElements); 00064 this->init_array(); 00065 this->copyRB(src); 00066 } 00067 00068 // Copy Assignment 00069 GenRingBuffer<T>& operator=(const GenRingBuffer<T>& src) 00070 { 00071 this->copyRB(src); 00072 return *this; 00073 } 00074 00075 virtual ~GenRingBuffer() 00076 { 00077 delete [] HEAD; 00078 } 00079 00080 void ResizeBuffer(int newSize) 00081 { 00082 this->realloc_mem(newSize); 00083 } 00084 00085 int size() const 00086 { 00087 return NumElements; 00088 } 00089 00090 int MaxSize() const 00091 { 00092 return MaxNumElements; 00093 } 00094 00095 virtual T* operator[](int i) 00096 { 00097 return this->get(i); 00098 } 00099 00100 virtual T* get(int i = 0) const 00101 { 00102 if (i >= NumElements) return NULL; 00103 int j = ((consumePtr-HEAD)+i)%MaxNumElements; 00104 return (&HEAD[j].Data); 00105 } 00106 00107 T* getRaw(int i) const 00108 { 00109 if (i >= MaxNumElements) 00110 { 00111 return NULL; 00112 } 00113 return (&HEAD[i].Data); 00114 } 00115 00116 T* getLoad() const 00117 { 00118 return &loadPtr->Data; 00119 } 00120 00121 // getTail searches backward from index i 00122 T* getTail(int i = 0) const 00123 { 00124 if (i >= NumElements) return NULL; 00125 int j = ((loadPtr-1-HEAD)-i); 00126 if (j < 0) 00127 { 00128 j += MaxNumElements; 00129 } 00130 return (&HEAD[j].Data); 00131 } 00132 00133 void load(const T &newElem) 00134 { 00135 this->push(newElem); 00136 } 00137 00138 void load1(T newElem) 00139 { 00140 this->push(newElem); 00141 } 00142 00143 T* pop() 00144 { 00145 T* temp; 00146 if (this->size() == 0) 00147 { 00148 return 0; 00149 } 00150 else 00151 { 00152 temp = this->get(); 00153 this->incConsumePtr(); 00154 NumElements--; 00155 } 00156 return temp; 00157 } 00158 00159 bool indexValid(int i) 00160 { 00161 return (i >= 0 && i <this->NumElements); 00162 } 00163 00164 void clear() 00165 { 00166 while (this->pop()); 00167 } 00168 00169 protected: 00170 void realloc_mem(int NumElements2Alloc) 00171 { 00172 temp = new ctr[std::max(2, NumElements2Alloc)]; 00173 this->copy_elems(temp, NumElements2Alloc); 00174 delete [] HEAD; 00175 HEAD = temp; 00176 TAIL = HEAD+NumElements2Alloc; 00177 loadPtr = HEAD; 00178 consumePtr = HEAD; 00179 MaxNumElements = NumElements2Alloc; 00180 if (MaxNumElements < NumElements) 00181 { 00182 NumElements = MaxNumElements; 00183 } 00184 this->init_array(); 00185 } 00186 00187 private: 00188 struct ctr 00189 { 00190 T Data; 00191 ctr *next; 00192 ctr *prev; 00193 }; 00194 ctr *temp; 00195 ctr *HEAD; 00196 ctr *TAIL; 00197 ctr *loadPtr; 00198 ctr *consumePtr; 00199 00200 int NumElements; 00201 int MaxNumElements; 00202 00203 00204 bool copy_elems(ctr* dest, int MaxNum2Copy) 00205 { 00206 bool success; 00207 int Num2Copy = std::min(NumElements, MaxNum2Copy); 00208 if (Num2Copy !=NumElements) 00209 { 00210 success = false; 00211 } 00212 else 00213 { 00214 success = true; 00215 } 00216 for (int i = 0; i < Num2Copy; i++) 00217 { 00218 dest[i].Data = *(this->get(i)); 00219 } 00220 return success; 00221 } 00222 00223 void push(const T &newElem) 00224 { 00225 assert(NumElements <= MaxNumElements); 00226 loadPtr->Data = newElem; 00227 if (NumElements >= MaxNumElements) 00228 { 00229 this->incLoadPtr(); 00230 this->incConsumePtr(); 00231 } 00232 else 00233 { 00234 this->incLoadPtr(); 00235 NumElements++; 00236 } 00237 } 00238 00239 void incLoadPtr() 00240 { 00241 loadPtr = loadPtr->next; 00242 } 00243 00244 void incConsumePtr() 00245 { 00246 consumePtr = consumePtr->next; 00247 } 00248 00249 ctr* alloc_mem(int NumElems) 00250 { 00251 HEAD = new ctr[std::max(NumElems, 2)]; 00252 TAIL = HEAD+NumElems; 00253 loadPtr = HEAD; 00254 consumePtr = HEAD; 00255 MaxNumElements = NumElems; 00256 return HEAD; 00257 } 00258 00259 void init_array() 00260 { 00261 int j, k; 00262 for (int i = 0; i < MaxNumElements; i++) 00263 { 00264 j = (i+1)%MaxNumElements; 00265 k = (i-1)%MaxNumElements; 00266 HEAD[i].next = &HEAD[j]; 00267 HEAD[i].prev = &HEAD[k]; 00268 } 00269 } 00270 00271 void copyRB(GenRingBuffer<T>& src) 00272 { 00273 this->clear(); 00274 if (src.MaxNumElements != this->MaxNumElements) 00275 { 00276 this->realloc_mem(src.MaxNumElements); 00277 } 00278 00279 // Initialize the new buffer's number of elements to zero. The for loop 00280 // below will take care of incrementing NumElements to the correct value. 00281 this->NumElements = 0; 00282 // This was the previously-used line of code, which resulted in the 00283 // copied-to buffer incorrectly having a NumElements greater than the 00284 // copy-from buffer by 1: 00285 // this->NumElements = src.NumElements; 00286 for (int i = 0; i < src.NumElements; ++i) 00287 { 00288 this->load(*(src[i])); 00289 } 00290 } 00291 }; 00292 } 00293 00294 #endif // MATH_UTIL_GENERIC_RING_BUFFER_H_