Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ResizeArrayRaw.h

Go to the documentation of this file.
00001 
00007 /*
00008    ResizeArrayRaw template
00009    Object Requirements: new
00010                         Elem(Elem &)
00011                         ~Elem()
00012                         Elem & operator= (Elem &)
00013 */
00014 
00015 
00016 #ifndef RESIZEARRAYRAW_H
00017 #define RESIZEARRAYRAW_H
00018 
00019 #include <new>
00020 #include <string.h>
00021 #include "common.h"
00022 
00023 #define GrowthFactor 1.5
00024 #define MinSize 8
00025 
00026 // Need this juju to use templated friend below
00027 template <class Type> class ResizeArray;
00028 template <class Type> class SortableResizeArray;
00029 template <class Type> class ResizeArrayIter;
00030 
00031 // Class assumes that one can bit move objects
00032 // around on array.  This will be true
00033 // as long as object has no pointers to itself.
00034 template <class Elem> class ResizeArrayRaw {
00035 
00036   private:
00037     Elem *array;
00038     unsigned char *varray;
00039 
00040     int arraySize;
00041     int allocSize;
00042 
00043     int refCount;
00044 
00045     float growthFactor;
00046     int minSize;
00047 
00048     // No constructor run on new elements
00049     // arraySize is not adjusted, only allocSize
00050     void resizeRaw(int size) {
00051       if (size <= allocSize) return;
00052   
00053       if (size < (int)(allocSize*growthFactor)) 
00054         size = (int)(allocSize*growthFactor);
00055       if ( (size-allocSize) < minSize) 
00056         size = allocSize+minSize;
00057 
00058       // align everything to 32-byte boundaries (if possible)
00059       unsigned char *tmpv = new unsigned char[size*sizeof(Elem)+31];
00060       //Elem *tmpa = (Elem *)((((long)tmpv)+31L)&(-32L));
00061       // Someday we might need this alternate form.
00062       Elem *tmpa = (Elem *)(tmpv+31 - (((long)(tmpv+31))&(31L)));
00063       CmiMemcpy((void *)tmpa, (void *)array, sizeof(Elem)*arraySize);
00064   
00065       if (allocSize) delete[] varray;
00066       varray = tmpv;
00067       array = tmpa;
00068       allocSize = size;
00069     }
00070 
00071     // Empty function for now.
00072     // eventually, this should get smaller storage and free
00073     // void reduce(void) {}; 
00074 
00075   public:
00076     friend class ResizeArray<Elem>;
00077     friend class SortableResizeArray<Elem>;
00078     friend class ResizeArrayIter<Elem>;
00079 
00080     inline int size(void) const { return arraySize; }
00081     inline Elem &operator[](int index) const { return array[index]; }
00082 
00083     // Default constructor 
00084     ResizeArrayRaw(void) : 
00085       array((Elem *)0), varray((unsigned char *)0), arraySize(0), allocSize(0) { 
00086       growthFactor = GrowthFactor;
00087       minSize = MinSize;
00088     }
00089 
00090     // Copy constructor - true copy on construction.
00091     ResizeArrayRaw(const ResizeArrayRaw<Elem> &rar ) : 
00092       array((Elem *)0), varray((unsigned char *)0), arraySize(0), allocSize(0) {
00093       growthFactor = rar.growthFactor;
00094       minSize = rar.minSize;
00095       // We want rar.size() slots, but no constructor run on the elements
00096       resizeRaw(rar.size());
00097       CmiMemcpy((void*)array, (void*)rar.array, sizeof(Elem)*rar.size());
00098       arraySize = rar.size();
00099     }
00100   
00101     // Encap a pre-existing array
00102     ResizeArrayRaw( Elem * * const array, int arraySize, int allocSize) {
00103       if (allocSize < arraySize) allocSize = arraySize;
00104       this->allocSize = allocSize;
00105       this->arraySize = arraySize;
00106       varray = (unsigned char *)*array;
00107       this->array = (Elem *)*array;
00108       *array = 0;
00109       growthFactor = GrowthFactor;
00110       minSize = MinSize;
00111     }
00112   
00113     ~ResizeArrayRaw(void) {
00114       for (int i=0; i < arraySize; i++) {
00115         array[i].~Elem();
00116       }
00117       delete[] varray;
00118     }
00119   
00120     // minSize = minimum growth size - (also initial size of array)
00121     // growthFactor = mulplicative factor by which to grow array.
00122     void setResizeParams(int min, float growth) {
00123       minSize = min;
00124       growthFactor = growth;
00125     }
00126   
00127   
00128     // True copy made on assignment.
00129     ResizeArrayRaw<Elem> & operator=(const ResizeArrayRaw<Elem> &rar ) {
00130       growthFactor = rar.growthFactor;
00131       minSize = rar.minSize;
00132   
00133       // Clean up this array
00134       resize(0);
00135       resizeRaw(rar.size());
00136   
00137       CmiMemcpy((void*)array, (void*)rar.array, sizeof(Elem)*rar.size());
00138       arraySize = rar.size();
00139       return *this;
00140     }
00141   
00142     // Properly constructs default object on new elements
00143     // Properly destructs on removed elements
00144     // arraySize is properly updated
00145     void resize(int size) {
00146       int i;
00147   
00148       if (size < arraySize) {
00149         for (i=size; i<arraySize; i++) {
00150           array[i].~Elem();
00151         }
00152       } else if (size > arraySize) {
00153         resizeRaw(size);
00154         for (i=arraySize; i<size; i++) {
00155           new ((void *)&array[i]) Elem;
00156         }
00157       }
00158       arraySize = size;
00159     }
00160   
00161     // resize to 0 and free storage
00162     void clear(void) {
00163       for (int i=0; i<arraySize; i++) {
00164         array[i].~Elem();
00165       }
00166       delete [] varray;
00167       array = 0;
00168       varray = 0;
00169       arraySize = 0;
00170       allocSize = 0;
00171     }
00172 
00173     inline int del(int index, int number) {
00174       int i;
00175   
00176       // Fix up number to delete if deletes off end of array
00177       if (index >= arraySize)
00178         number=0; // for inline sake, don't have multiple returns
00179       else if (index+number-1 > arraySize) {
00180         number = index-arraySize+1;
00181       }
00182   
00183       // Destruct objects to be deleted
00184       for (i=index; i < index+number; i++) {
00185         array[i].~Elem();
00186       }
00187   
00188       // Shift down
00189       memmove((void *)(array+index),
00190          (void *)(array+index+number),
00191          (arraySize-number-index)*sizeof(Elem));
00192       
00193       // fixup size of array
00194       arraySize -= number;
00195       return(number);
00196     }
00197   
00198     
00199     // Insert element in array
00200     // If index is over the end of array, default
00201     // constructor should be run over blank elements to pad.
00202     inline void ins(const Elem &e, int index) {
00203       // Size array depending if index is in current array or reaches beyond.
00204       if (index < arraySize) {
00205         resizeRaw(arraySize+1);
00206         // Shift up
00207         memmove((void *)(array+index+1),
00208           (void *)(array+index),
00209           (arraySize-index)*sizeof(Elem));
00210       } else {
00211         resizeRaw(index+1);
00212       }
00213       
00214       // Write in new element via assignment - allows any refcounting
00215       // etc. to take place correctly!
00216       new((void *)&array[index]) Elem;
00217       array[index] = e;
00218     
00219       // Take care of fill and setting correct arraySize 
00220       if (index > arraySize) {
00221         for (Elem *tmp = array+arraySize; tmp < array+index; tmp++) {
00222           new ((void *)tmp) Elem;
00223         }
00224         arraySize = index+1;
00225       } else
00226         arraySize++;
00227     }
00228 
00229     inline int find(const Elem &e) {
00230       for (int i=0; i<arraySize; i++)
00231         if (array[i] == e) return i;
00232       return -1;
00233     }
00234 };      // end template definition
00235 
00236 #endif

Generated on Fri May 25 04:07:17 2012 for NAMD by  doxygen 1.3.9.1