NAMD
ResizeArrayRaw.h
Go to the documentation of this file.
1 
7 /*
8  Data storage class for ResizeArray and related container classes.
9  Copy and assignment copy raw pointers, use copy() to copy data.
10  Destructor does not delete data, call free first.
11 */
12 
13 
14 #ifndef RESIZEARRAYRAW_H
15 #define RESIZEARRAYRAW_H
16 
17 #include <new>
18 #include <string.h>
19 #include "common.h"
20 
21 // CmiMemcpy is not available in NVCC
22 #if !(defined(__NVCC__) || defined(NAMD_NVCC) || defined(__HIPCC__))
23 
24 #define ResizeArrayGrowthFactor 1.5
25 #define ResizeArrayMinSize 8
26 
27 // Need this juju to use templated friend below
28 template <class Type> class ResizeArray;
29 template <class Type> class SortableResizeArray;
30 template <class Type> class SortedArray;
31 template <class Type> class UniqueSortedArray;
32 template <class Type> class ResizeArrayIter;
33 
34 // Class assumes that one can bit move objects
35 // around on array. This will be true
36 // as long as object has no pointers to itself.
37 template <class Elem> class ResizeArrayRaw {
38 
39  private:
40  Elem *array;
41  unsigned char *varray;
42 
43  // Use of int (int32) is safe for counting elements.
44  int arraySize;
45  int allocSize;
46 
47  // No constructor run on new elements
48  // arraySize is not adjusted, only allocSize
49  void resizeRaw(int size) {
50  if (size <= allocSize) return;
51 
52  // Note that ResizeArrayGrowthFactor is type double so the
53  // multiplication below is also done in double.
54  // Assuming int32, the conversion from double overflows at
55  // allocSize = 1431655765
56  // Conditional remains safe if overflow causes RHS < 0.
57  if (size < (int)(allocSize*ResizeArrayGrowthFactor)) {
58  size = (int)(allocSize*ResizeArrayGrowthFactor);
59  }
60  // The next conditional will test true either for very small or
61  // unallocated arrays or if the above conditional causes overflow.
62  if ( (size-allocSize) < ResizeArrayMinSize) {
63  // Overflow occurs here only when allocSize is within
64  // ResizeArrayMinSize of 2^31.
65  size = allocSize+ResizeArrayMinSize;
66  }
67 
68  // Align everything to 64-byte boundaries (if possible).
69  // Use of sizeof below promotes expression to type size_t.
70  unsigned char *tmpv = new unsigned char[size*sizeof(Elem)+63];
71  //Elem *tmpa = (Elem *)((((long)tmpv)+63L)&(-64L));
72  // Someday we might need this alternate form.
73  //
74  // The following pointer manipulation is dangerous. We should use
75  // reinterpret_cast<uintptr_t> or equivalent to convert tmpv+63
76  // to an unsigned integer type before doing bitwise and operation.
77  //
78  // The 63 value (64-byte alignment) aligns for AVX-512 registers.
79  // Would be better to use a macro or maybe even a template parameter
80  // instead of hard-coding the alignment. With a template parameter,
81  // we could override the alignment where optimization warrants or
82  // target builds towards a particular alignment, e.g., AVX needs
83  // only 32-byte alignment.
84  Elem *tmpa = (Elem *)(tmpv+63 - (((long)(tmpv+63))&(63L)));
85  if (arraySize) memcpy((void *)tmpa, (void *)array, sizeof(Elem)*arraySize);
86 
87  if (allocSize) delete[] varray;
88  varray = tmpv;
89  array = tmpa;
90  allocSize = size;
91  }
92 
93  friend class ResizeArray<Elem>;
94  friend class SortableResizeArray<Elem>;
95  friend class SortedArray<Elem>;
96  friend class UniqueSortedArray<Elem>;
97  friend class ResizeArrayIter<Elem>;
98 
99  inline int size(void) const { return arraySize; }
100  inline Elem &operator[](int index) const { return array[index]; }
101 
102  // DMK - MIC Support - Allow us to see the buffer's size, not just how much of it is used
103  #if NAMD_MIC != 0
104  inline int bufSize(void) const { return allocSize; }
105  #endif
106 
107  // Default constructor
108  ResizeArrayRaw(void) :
109  array((Elem *)0), varray((unsigned char *)0), arraySize(0), allocSize(0) { }
110 
111  // Encap a pre-existing array
112  ResizeArrayRaw( Elem * * const array, int arraySize, int allocSize) {
113  if (allocSize < arraySize) allocSize = arraySize;
114  this->allocSize = allocSize;
115  this->arraySize = arraySize;
116  varray = (unsigned char *)*array;
117  this->array = (Elem *)*array;
118  *array = 0;
119  }
120 
121  // copy data
122  void copy(const ResizeArrayRaw<Elem> &rar ) {
123 
124  // Clean up this array
125  resize(0);
126  resizeRaw(rar.size());
127 
128  memcpy((void*)array, (void*)rar.array, sizeof(Elem)*rar.size());
129  arraySize = rar.size();
130  }
131 
132  // Properly constructs default object on new elements
133  // Properly destructs on removed elements
134  // arraySize is properly updated
135  void resize(int size) {
136  int i;
137 
138  if (size < arraySize) {
139  for (i=size; i<arraySize; i++) {
140  array[i].~Elem();
141  }
142  } else if (size > arraySize) {
143  resizeRaw(size);
144  for (i=arraySize; i<size; i++) {
145  new ((void *)&array[i]) Elem;
146  }
147  }
148  arraySize = size;
149  }
150 
151  // needed for ResizeArray destructor
152  void free(void) {
153  for (int i=0; i < arraySize; i++) {
154  array[i].~Elem();
155  }
156  delete[] varray;
157  }
158 
159  // resize to 0 and free storage
160  void clear(void) {
161  free();
162  array = 0;
163  varray = 0;
164  arraySize = 0;
165  allocSize = 0;
166  }
167 
168  inline void del(int index, int number) {
169  if (number) {
170  // Destruct objects to be deleted
171  for (int i=index; i < index+number; i++) {
172  array[i].~Elem();
173  }
174 
175  // Shift down
176  memmove((void *)(array+index),
177  (void *)(array+index+number),
178  (arraySize-number-index)*sizeof(Elem));
179 
180  // fixup size of array
181  arraySize -= number;
182  }
183  }
184 
185 
186  // Insert element in array
187  // If index is over the end of array, default
188  // constructor should be run over blank elements to pad.
189  inline void ins(const Elem &e, int index) {
190  // Size array depending if index is in current array or reaches beyond.
191  if (index < arraySize) {
192  resizeRaw(arraySize+1);
193  // Shift up
194  memmove((void *)(array+index+1),
195  (void *)(array+index),
196  (arraySize-index)*sizeof(Elem));
197  } else {
198  resizeRaw(index+1);
199  }
200 
201  // Write in new element via assignment - allows any refcounting
202  // etc. to take place correctly!
203  new((void *)&array[index]) Elem;
204  array[index] = e;
205 
206  // Take care of fill and setting correct arraySize
207  if (index > arraySize) {
208  for (Elem *tmp = array+arraySize; tmp < array+index; tmp++) {
209  new ((void *)tmp) Elem;
210  }
211  arraySize = index+1;
212  } else {
213  arraySize++;
214  }
215  }
216 
217  inline int find(const Elem &e) const {
218  for (int i=0; i<arraySize; i++) {
219  if (array[i] == e) return i;
220  }
221  return -1;
222  }
223 }; // end template definition
224 
225 #endif // NVCC guard
226 #endif // RESIZEARRAYRAW_H
#define ResizeArrayMinSize
#define ResizeArrayGrowthFactor