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 < size(); 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     inline int del(int index, int number) {
00162       int i;
00163   
00164       // Fix up number to delete if deletes off end of array
00165       if (index >= arraySize)
00166         number=0; // for inline sake, don't have multiple returns
00167       else if (index+number-1 > arraySize) {
00168         number = index-arraySize+1;
00169       }
00170   
00171       // Destruct objects to be deleted
00172       for (i=index; i < index+number; i++) {
00173         array[i].~Elem();
00174       }
00175   
00176       // Shift down
00177       memmove((void *)(array+index),
00178          (void *)(array+index+number),
00179          (arraySize-number-index)*sizeof(Elem));
00180       
00181       // fixup size of array
00182       arraySize -= number;
00183       return(number);
00184     }
00185   
00186     
00187     // Insert element in array
00188     // If index is over the end of array, default
00189     // constructor should be run over blank elements to pad.
00190     inline void ins(const Elem &e, int index) {
00191       // Size array depending if index is in current array or reaches beyond.
00192       if (index < arraySize) {
00193         resizeRaw(arraySize+1);
00194         // Shift up
00195         memmove((void *)(array+index+1),
00196           (void *)(array+index),
00197           (arraySize-index)*sizeof(Elem));
00198       } else {
00199         resizeRaw(index+1);
00200       }
00201       
00202       // Write in new element via assignment - allows any refcounting
00203       // etc. to take place correctly!
00204       new((void *)&array[index]) Elem;
00205       array[index] = e;
00206     
00207       // Take care of fill and setting correct arraySize 
00208       if (index > arraySize) {
00209         for (Elem *tmp = array+arraySize; tmp < array+index; tmp++) {
00210           new ((void *)tmp) Elem;
00211         }
00212         arraySize = index+1;
00213       } else
00214         arraySize++;
00215     }
00216 
00217     inline int find(const Elem &e) {
00218       for (int i=0; i<arraySize; i++)
00219         if (array[i] == e) return i;
00220       return -1;
00221     }
00222 };      // end template definition
00223 
00224 #endif

Generated on Sun Sep 7 04:07:42 2008 for NAMD by  doxygen 1.3.9.1