generic_ring_buffer.h
Go to the documentation of this file.
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_


swri_math_util
Author(s): Marc Alban
autogenerated on Tue Oct 3 2017 03:19:18