GemaCoreLib
The GeMA Core library
gmDualVector.h
Go to the documentation of this file.
1 /************************************************************************
2 **
3 ** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4 ** All rights reserved.
5 **
6 ** This file is part of the "GeMA" software. It's use should respect
7 ** the terms in the license agreement that can be found together
8 ** with this source code.
9 ** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10 ** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11 ** A PARTICULAR PURPOSE.
12 **
13 ************************************************************************/
14 
23 #ifndef _GEMA_DUAL_VECTOR_H_
24 #define _GEMA_DUAL_VECTOR_H_
25 
26 #include "gmPODVector.h"
27 
41 template <class T> class GmDualVector
42 {
43 public:
44  static_assert(!QTypeInfo<T>::isComplex, "Not a POD type");
45 
47  typedef T DataType;
48 
50  GmDualVector() { _fixedData = NULL; _fixedSize = 0; }
51 
53  GmDualVector(size_t nvalues) { _fixedData = NULL; _fixedSize = 0; if(!addValues(nvalues)) throw(std::bad_alloc()); }
54 
56  ~GmDualVector() { free(_fixedData); } // Plain C deallocation - see addValues()
57 
59  size_t size() const { return _fixedSize + _growData.size(); }
60 
67  const T* iptr(size_t index) const
68  {
69  assert(index < size());
70  if(index < _fixedSize) //[[likely]]
71  return _fixedData + index;
72  else //[[unlikely]]
73  return _growData.data() + (index - _fixedSize);
74  }
75 
77  T* iptr(size_t index)
78  {
79  assert(index < size());
80  if(index < _fixedSize) //[[likely]]
81  return _fixedData + index;
82  else //[[unlikely]]
83  return _growData.data() + (index - _fixedSize);
84  }
85 
87  const T& operator[](size_t index) const { return *iptr(index); }
88 
90  T& operator[](size_t index) { return *iptr(index); }
91 
99  bool addValues(size_t numAddedValues, bool tight = false)
100  {
101  S_TRACE();
102  if(numAddedValues == 0)
103  return true;
104 
105  if(size() > std::numeric_limits<size_t>::max() - numAddedValues)
106  {
107  gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error adding %1 values. Vector size would surpass the maximum possible capacity.").arg(numAddedValues));
108  return false;
109  }
110 
111  // If the fixed part is empty, lets use it to store the requested size
112  if(!_fixedData || (tight && !_growData.size()))
113  {
114  assert(_growData.size() == 0);
115  // We use realloc for the allocation to, hopefully, grow the vector without moving when tight is true
116  // We can do that since T is a POD type
117  T* newPtr = (T*)realloc(_fixedData, (_fixedSize + numAddedValues) * sizeof(T));
118  if(!newPtr)
119  {
120  if(!_fixedData)
121  gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error allocating a new vector with %1 entries of %2 bytes.")
122  .arg(_fixedSize + numAddedValues).arg(sizeof(T)));
123  else
124  gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error resizing a vector with %1 entries of %2 bytes to a vector with %3 entries.")
125  .arg(_fixedSize).arg(sizeof(T)).arg(_fixedSize + numAddedValues));
126  return false;
127  }
128  _fixedData = newPtr;
129  _fixedSize += numAddedValues;
130  return true;
131  }
132 
133  // Fixed part already exists. Lets use the grow part of the vector
134  if(tight)
135  return _growData.resize(_growData.size() + numAddedValues, GmPODVectorTightGrow);
136  else
137  return _growData.resize(_growData.size() + numAddedValues);
138  }
139 
141  void restoreSize(size_t oldNumValues)
142  {
143  S_TRACE();
144  assert(oldNumValues <= size());
145 
146  if(oldNumValues > 0)
147  {
148  assert(oldNumValues >= _fixedSize);
149  _growData.resize(oldNumValues - _fixedSize);
150  }
151  else
152  clear();
153  }
154 
156  void clear()
157  {
158  S_TRACE();
159  free(_fixedData);
160  _fixedData = NULL;
161  _fixedSize = 0;
162  _growData.clear();
163  }
164 
170  size_t usedMemory() const { return (_fixedSize + _growData.capacity()) * sizeof(T); }
171 
173  int numDumpBuffers() const { return 1 + (_growData.size() > 0); }
174 
176  char* dumpBuffer(int i) const { assert(i >= 0 && i < numDumpBuffers()); return (char*)(i ? _growData.data() : _fixedData); }
177 
179  size_t dumpBufferSize(int i) const { assert(i >= 0 && i < numDumpBuffers()); return (i ? _growData.size() : _fixedSize) * sizeof(T); }
180 
181 protected:
183  size_t _fixedSize;
184 
186 
187 private:
188  Q_DISABLE_COPY(GmDualVector);
189 };
190 
191 
192 
196 template <class T> class GmDualVectorR : public GmDualVector<T>
197 {
198 public:
200  GmDualVectorR() { _size = 0; }
201 
203  GmDualVectorR(size_t nvalues) : GmDualVector(nvalues) { _size = nvalues; }
204 
207 
209  size_t size() const
210  {
211  assert(_size >= _fixedSize ? (_size == _fixedSize + _growData.size()) : (_growData.size() == 0));
212  return _size;
213  }
214 
219  bool addValues(size_t numAddedValues, bool tight = false)
220  {
221  S_TRACE();
222 
223  if(_size > std::numeric_limits<size_t>::max() - numAddedValues)
224  {
225  gmWarnMsg(GmPanicLogger(), QObject::tr("Dual vector: Error adding %1 values. Vector size would surpass the maximum possible capacity.").arg(numAddedValues));
226  return false;
227  }
228 
229  size_t nadd = numAddedValues;
230  if(_size < _fixedSize) // There are available entries in the fixed part
231  {
232  assert(_growData.size() == 0);
233  if(numAddedValues > _fixedSize - _size) // Carefull with negative values using size_t
234  nadd = numAddedValues - (_fixedSize - _size);
235  else
236  nadd = 0;
237  }
238 
239  if(!GmDualVector<T>::addValues(nadd, tight))
240  return false;
241  _size += numAddedValues;
242  return true;
243  }
244 
246  void restoreSize(size_t oldNumValues)
247  {
248  S_TRACE();
249  GmDualVector<T>::restoreSize(qMax(oldNumValues, _fixedSize));
250  _size = oldNumValues;
251  }
252 
264  void removeValues(size_t index, size_t numValues)
265  {
266  S_TRACE();
267  assert(index + numValues <= _size);
268 
269  if(index >= _fixedSize) // All the removed data belongs to the grow part
270  {
271  _growData.remove(index - _fixedSize, numValues);
272  _size -= numValues;
273  }
274  else
275  {
276  // At least one of the removed entries is in the fixed part
277  size_t fr = index + numValues; // The first index in the remaining part of the vector that should be moved to the left
278  size_t nr = _size - fr; // The size of the remaining part of the vector that should be moved to the left
279 
280  // Move left all the remaining entries after the removed window
281  for(size_t i = 0; i < nr; i++)
282  *iptr(index+i) = *iptr(fr+i);
283 
284  // Adjust the sizes
285  _size -= numValues;
286  if(_size > _fixedSize) // Carefull with negative results using size_t
288  else
289  _growData.clear();
290  }
291  }
292 
294  void clear()
295  {
296  S_TRACE();
298  _size = 0;
299  }
300 
301 private:
302  Q_DISABLE_COPY(GmDualVectorR);
303 
304  size_t _size;
305 };
306 
307 
308 
309 
310 #endif
GmDualVector(size_t nvalues)
The constructor initializing the "fixed" part size. The vector contents is NOT initialized.
Definition: gmDualVector.h:53
size_t size() const
Returns the vector size.
Definition: gmDualVector.h:209
const GmLogCategory & GmPanicLogger()
Returns the global "panic" logger, usually used to report memory allocation fails deep inside class s...
Definition: gmLog.cpp:700
T DataType
The stored data type.
Definition: gmDualVector.h:44
GmDualVectorR(size_t nvalues)
The constructor initializing the "fixed" part size. The vector contents is NOT initialized.
Definition: gmDualVector.h:203
int numDumpBuffers() const
Returns the number of internal buffers used by this implementation.
Definition: gmDualVector.h:173
#define S_TRACE()
Macro for run time stack tracking at release build.
Definition: gmTrace.h:44
T & operator[](size_t index)
Non-const overload for the standard indexing operator.
Definition: gmDualVector.h:90
size_t _fixedSize
The number of entries in _fixedData.
Definition: gmDualVector.h:183
QString tr(const char *sourceText, const char *disambiguation, int n)
GmPODVector< T > _growData
The variable part.
Definition: gmDualVector.h:185
Implementation of the GmPODVector template class.
void clear()
Clears all stored data returning the object to a default constructed state.
Definition: gmDualVector.h:294
const T * iptr(size_t index) const
Returns a pointer to the index data inside the vector. By the very nature of this class,...
Definition: gmDualVector.h:67
GmDualVector()
Default constructor.
Definition: gmDualVector.h:50
size_t size() const
Returns the vector size.
Definition: gmDualVector.h:59
bool addValues(size_t numAddedValues, bool tight=false)
Adds numAddedValues to the set, without any initialization. Returns true on success,...
Definition: gmDualVector.h:219
~GmDualVector()
Destructor.
Definition: gmDualVector.h:56
void restoreSize(size_t oldNumValues)
Restores the size of the set to the previous size before the last call to addValues().
Definition: gmDualVector.h:246
size_t dumpBufferSize(int i) const
Returns the size in bytes of the i'th internal buffer returned by dumpBuffer(i)
Definition: gmDualVector.h:179
size_t _size
The total number of entries in the vector. Can be less than _fixedSize if entries where removed from ...
Definition: gmDualVector.h:304
void removeValues(size_t index, size_t numValues)
Removes numValues from the set, starting from (and including) index.
Definition: gmDualVector.h:264
bool resize(ControlSize newSize, GmPODGrowT grow=Grow)
Resizes the vector to the given size using the speciefied grow policy.
Definition: gmPODVector.h:159
~GmDualVectorR()
Destructor.
Definition: gmDualVector.h:206
T * iptr(size_t index)
Non-const overload for iptr()
Definition: gmDualVector.h:77
A vector tailored for storing mesh related data for the common scenario where elements are added to t...
Definition: gmDualVector.h:41
A class very simmilar to GmDualVector with support for removing values. Removing values should be use...
Definition: gmDualVector.h:196
size_t usedMemory() const
Returns an estimative of the memory used by the data set in bytes.
Definition: gmDualVector.h:170
void remove(ControlSize index, ControlSize numValues)
Removes numValues entries from the vector starting at index.
Definition: gmPODVector.h:139
T * _fixedData
The fixed part of the dual vector with _fixedSize entries.
Definition: gmDualVector.h:182
GmDualVectorR()
Default constructor.
Definition: gmDualVector.h:200
ControlSize capacity() const
Returns the vector allocated capacity.
Definition: gmPODVector.h:106
char * dumpBuffer(int i) const
Returns the i'th internal buffer, i from 0 to numDumpBuffers()-1.
Definition: gmDualVector.h:176
const T * data() const
Returns a pointer to the data inside the vector.
Definition: gmPODVector.h:109
ControlSize size() const
Returns the vector size.
Definition: gmPODVector.h:103
void clear()
Clears all stored data returning the object to a default constructed state.
Definition: gmDualVector.h:156
size_t GmPODVectorTightGrow(size_t s, size_t a)
Vector growing to exactly the needed size.
Definition: gmPODVector.h:72
void clear()
Clears the vector deallocating used memory.
Definition: gmPODVector.h:229
bool addValues(size_t numAddedValues, bool tight=false)
Adds numAddedValues to the set, without any initialization. Returns true on success,...
Definition: gmDualVector.h:99
void restoreSize(size_t oldNumValues)
Restores the size of the set to the previous size before the last call to addValues().
Definition: gmDualVector.h:141
const T & operator[](size_t index) const
Standard indexing operator.
Definition: gmDualVector.h:87