artdaq_core  v3_05_10
QuickVec.hh
1 // This file (QuickVec.hh) was created by Ron Rechenmacher <ron@fnal.gov> on
2 // Sep 3, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3 // or COPYING file. If you do not have such a file, one can be obtained by
4 // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5 // $RCSfile: QuickVec.hh,v $
6 // rev="$Revision: 1.8 $$Date: 2014/09/05 19:21:11 $";
7 #ifndef QuickVec_hh
8 #define QuickVec_hh
9 
10 //extern "C" {
11 //#include <stdint.h>
12 //}
13 
14 #include <string.h> // memcpy
15 //#include <strings.h> // bzero
16 //#include <stdlib.h> // posix_memalign
17 #include <cstddef> // ptrdiff_t
18 //#include <utility> // std::swap
19 //#include <memory> // unique_ptr
21 #include <cassert>
22 #include <cmath>
23 #include <vector>
26 //#include "trace.h" // TRACE
27 #ifndef TRACEN
28 #define TRACEN(nam, lvl, ...)
29 #define UNDEF_TRACE_AT_END
30 #endif
31 
32 #define QV_ALIGN 512
33 
40 static inline void* QV_MEMALIGN(size_t boundary, size_t size)
41 {
42  void* retadr;
43  posix_memalign(&retadr, boundary, size);
44  return retadr;
45 }
46 
47 #ifndef QUICKVEC_DO_TEMPLATE
48 #define QUICKVEC_DO_TEMPLATE 1
49 #endif
50 
51 #undef NOT_OLD_CXXSTD
52 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
53 #define NOT_OLD_CXXSTD 1
54 #endif
55 
56 #if QUICKVEC_DO_TEMPLATE == 0
57 #ifndef QUICKVEC_TT
58 #define QUICKVEC_TT unsigned long long
59 #endif
60 #define TT_ QUICKVEC_TT
61 #define QUICKVEC_TEMPLATE
62 #define QUICKVEC QuickVec
63 #define QUICKVEC_TN QuickVec
64 #define QUICKVEC_VERSION
65 #else
66 #define QUICKVEC_TEMPLATE template<typename TT_>
67 #define QUICKVEC QuickVec<TT_>
68 #define QUICKVEC_TN typename QuickVec<TT_>
69 #define QUICKVEC_VERSION \
70  \
76  static short Class_Version() { return 5; } // proper version for templates
77 #endif
78 
79 namespace artdaq {
80 
86 QUICKVEC_TEMPLATE
87 struct QuickVec
88 {
89  typedef TT_* iterator;
90  typedef const TT_* const_iterator;
91  typedef TT_& reference;
92  typedef const TT_& const_reference;
93  typedef TT_ value_type;
94  typedef ptrdiff_t difference_type;
95  typedef size_t size_type;
96 
101  QuickVec(size_t sz);
102 
108  QuickVec(size_t sz, TT_ val);
109 
113  virtual ~QuickVec() noexcept;
114 
119  QuickVec(std::vector<TT_>& other)
120  : size_(other.size())
121  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
122  , capacity_(other.capacity())
123  {
124  TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d", (void*)this, (void*)data_, (void*)&other[0], size_, other.size());
125  memcpy(data_, (void*)&other[0], size_ * sizeof(TT_));
126  }
127 
131  void clear() { size_ = 0; }
132 
133  //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
138  QuickVec(const QuickVec& other) //= delete; // non construction-copyable
139  : size_(other.size_)
140  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
141  , capacity_(other.capacity_)
142  {
143  TRACEN("QuickVec", 10, "QuickVec copy ctor b4 memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d", (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
144  memcpy(data_, other.data_, size_ * sizeof(TT_));
145  }
146 
152  QUICKVEC& operator=(const QuickVec& other) //= delete; // non copyable
153  {
154  TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d", (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
155  resize(other.size_);
156  memcpy(data_, other.data_, size_ * sizeof(TT_));
157  return *this;
158  }
159 #if NOT_OLD_CXXSTD
160 
164  QuickVec(QuickVec&& other) noexcept // construction-movable
165  : size_(other.size_)
166  , data_(std::move(other.data_))
167  , capacity_(other.capacity_)
168  {
169  TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p", (void*)this, (void*)data_, (void*)other.data_);
170  other.data_ = nullptr;
171  }
172 
178  QUICKVEC& operator=(QuickVec&& other) noexcept // assign movable
179  {
180  TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p", (void*)this, (void*)data_, (void*)other.data_);
181  size_ = other.size_;
182  //delete [] data_;
183  free(data_);
184  data_ = std::move(other.data_);
185  capacity_ = other.capacity_;
186  other.data_ = nullptr;
187  return *this;
188  }
189 #endif
190 
196  TT_& operator[](int idx);
197 
203  const TT_& operator[](int idx) const;
204 
209  size_t size() const;
210 
219  size_t capacity() const;
220 
225  iterator begin();
226 
231  const_iterator begin() const;
232 
237  iterator end();
238 
243  const_iterator end() const;
244 
252  void reserve(size_t size);
253 
262  void resize(size_t size);
263 
274  void resizeWithCushion(size_t size, double growthFactor = 1.3);
275 
281  void resize(size_t size, TT_ val);
282 
294  iterator insert(const_iterator position, size_t nn, const TT_& val);
295 
308 
320 
325  void swap(QuickVec& other) noexcept;
326 
331  void push_back(const value_type& val);
332 
333  QUICKVEC_VERSION
334 
335 private:
336  // Root needs the size_ member first. It must be of type int.
337  // Root then needs the [size_] comment after data_.
338  // Note: NO SPACE between "//" and "[size_]"
339  unsigned size_;
340  TT_* data_; //[size_]
341  unsigned capacity_;
342 };
343 
344 QUICKVEC_TEMPLATE
345 inline QUICKVEC::QuickVec(size_t sz)
346  : size_(sz)
347  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
348  , capacity_(sz)
349 {
350  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_);
351 }
352 
353 QUICKVEC_TEMPLATE
354 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
355  : size_(sz)
356  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
357  , capacity_(sz)
358 {
359  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_);
360  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
361  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
362 }
363 
364 QUICKVEC_TEMPLATE
365 inline QUICKVEC::~QuickVec() noexcept
366 {
367  TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d", (void*)this, (void*)data_, size_);
368  free(data_);
369  TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
370 }
371 
372 QUICKVEC_TEMPLATE
373 inline TT_& QUICKVEC::operator[](int idx)
374 {
375  assert(idx < (int)size_);
376  return data_[idx];
377 }
378 
379 QUICKVEC_TEMPLATE
380 inline const TT_& QUICKVEC::operator[](int idx) const
381 {
382  assert(idx < (int)size_);
383  return data_[idx];
384 }
385 
386 QUICKVEC_TEMPLATE
387 inline size_t QUICKVEC::size() const { return size_; }
388 
389 QUICKVEC_TEMPLATE
390 inline size_t QUICKVEC::capacity() const { return capacity_; }
391 
392 QUICKVEC_TEMPLATE
393 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
394 
395 QUICKVEC_TEMPLATE
396 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
397 
398 QUICKVEC_TEMPLATE
399 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_ + size_); }
400 
401 QUICKVEC_TEMPLATE
402 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_ + size_); }
403 
404 QUICKVEC_TEMPLATE
405 inline void QUICKVEC::reserve(size_t size)
406 {
407  if (size > capacity_) // reallocation if true
408  {
409  TT_* old = data_;
410  //data_ = new TT_[size];
411  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
412  memcpy(data_, old, size_ * sizeof(TT_));
413  TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p capacity=%d", (void*)this, (void*)old, (void*)data_, (int)size);
414  free(old);
415  capacity_ = size;
416  }
417 }
418 
419 QUICKVEC_TEMPLATE
420 inline void QUICKVEC::resize(size_t size)
421 {
422  if (size < size_)
423  size_ = size; // decrease
424  else if (size <= capacity_)
425  size_ = size;
426  else // increase/reallocate
427  {
428  TT_* old = data_;
429  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
430  memcpy(data_, old, size_ * sizeof(TT_));
431  TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p size=%d", (void*)this, (void*)old, (void*)data_, (int)size);
432  free(old);
433  size_ = capacity_ = size;
434  }
435 }
436 
437 QUICKVEC_TEMPLATE
438 inline void QUICKVEC::resizeWithCushion(size_t size, double growthFactor)
439 {
440  if (size > capacity_)
441  {
442  size_t new_size = std::round(capacity_ * growthFactor);
443  if (new_size < size) { new_size = size; }
444  if (new_size < 512) { new_size = 512; }
445  else if (new_size < 2048)
446  {
447  new_size = 2048;
448  }
449  else if (new_size < 4096)
450  {
451  new_size = 4096;
452  }
453  else if (new_size < 8192)
454  {
455  new_size = 8192;
456  }
457  reserve(new_size);
458  }
459  resize(size);
460 }
461 
462 QUICKVEC_TEMPLATE
463 inline void QUICKVEC::resize(size_type size, TT_ val)
464 {
465  size_type old_size = size;
466  resize(size);
467  if (size > old_size)
468  {
469  TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size - old_size);
470  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
471  }
472 }
473 
474 QUICKVEC_TEMPLATE
475 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position, size_t nn, const TT_& val)
476 {
477  assert(position <= end()); // the current end
478  size_t offset = position - begin();
479  reserve(size_ + nn); // may reallocate and invalidate "position"
480 
481  iterator dst = end() + nn; // for shifting existing data after
482  iterator src = end(); // insertion point
483  size_t cnt = end() - (begin() + offset);
484  while (cnt--) *--dst = *--src;
485 
486  dst = begin() + offset;
487  size_ += nn;
488  while (nn--) *dst++ = val;
489  return begin() + offset;
490 }
491 
492 QUICKVEC_TEMPLATE
493 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position, const_iterator first, const_iterator last)
494 {
495  assert(position <= end()); // the current end
496  size_t nn = (last - first);
497  size_t offset = position - begin();
498  reserve(size_ + nn); // may reallocate and invalidate "position"
499 
500  iterator dst = end() + nn; // for shifting existing data after
501  iterator src = end(); // insertion point
502  size_t cnt = end() - (begin() + offset);
503  while (cnt--) *--dst = *--src;
504 
505  dst = begin() + offset;
506  size_ += nn;
507  while (nn--) *dst++ = *first++;
508  return begin() + offset;
509 }
510 
511 QUICKVEC_TEMPLATE
512 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first, const_iterator last)
513 {
514  assert(last <= end()); // the current end
515  size_t nn = (last - first);
516  size_t offset = first - begin();
517 
518  iterator dst = begin() + offset; // for shifting existing data from last
519  iterator src = dst + nn; // to first
520  size_t cnt = end() - src;
521  while (cnt--) *dst++ = *src++;
522 
523  size_ -= nn;
524  return begin() + offset;
525 }
526 
527 QUICKVEC_TEMPLATE
528 inline void QUICKVEC::swap(QuickVec& x) noexcept
529 {
530  TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p", (void*)this, (void*)data_, (void*)x.data_);
531  std::swap(data_, x.data_);
532  std::swap(size_, x.size_);
533  std::swap(capacity_, x.capacity_);
534  TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p", (void*)data_, (void*)x.data_);
535 }
536 
537 QUICKVEC_TEMPLATE
538 inline void QUICKVEC::push_back(const value_type& val)
539 {
540  if (size_ == capacity_)
541  {
542  reserve(size_ + size_ / 10 + 1);
543  }
544  *end() = val;
545  ++size_;
546 }
547 
548 } // namespace artdaq
549 
550 #ifdef UNDEF_TRACE_AT_END
551 #undef TRACEN
552 #undef UNDEF_TRACE_AT_END
553 #endif
554 #endif /* QuickVec_hh */
iterator erase(const_iterator first, const_iterator last)
Erases elements in given range from the QuickVec.
Definition: QuickVec.hh:512
iterator end()
Gets an iterator to the end of the QuickVec.
Definition: QuickVec.hh:399
void clear()
Sets the size to 0. QuickVec does not reinitialize memory, so no further action will be taken...
Definition: QuickVec.hh:131
void reserve(size_t size)
Allocates memory for the QuickVec so that its capacity is at least size.
Definition: QuickVec.hh:405
void resize(size_t size)
Resizes the QuickVec.
Definition: QuickVec.hh:420
TT_ & operator[](int idx)
Returns a reference to a given element.
Definition: QuickVec.hh:373
size_t size_type
size_type is size_t
Definition: QuickVec.hh:95
TT_ value_type
value_type is member type
Definition: QuickVec.hh:93
size_t size() const
Accesses the current size of the QuickVec.
Definition: QuickVec.hh:387
TT_ * iterator
Iterator is pointer-to-member type.
Definition: QuickVec.hh:89
ptrdiff_t difference_type
difference_type is ptrdiff_t
Definition: QuickVec.hh:94
size_t capacity() const
Accesses the current capacity of the QuickVec.
Definition: QuickVec.hh:390
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:528
void resizeWithCushion(size_t size, double growthFactor=1.3)
Resizes the QuickVec and requests additional capacity.
Definition: QuickVec.hh:438
iterator insert(const_iterator position, size_t nn, const TT_ &val)
Inserts an element into the QuickVec.
Definition: QuickVec.hh:475
void push_back(const value_type &val)
Adds a value to the QuickVec, resizing if necessary (adds 10% capacity)
Definition: QuickVec.hh:538
A QuickVec behaves like a std::vector, but does no initialization of its data, making it faster at th...
Definition: QuickVec.hh:87
QuickVec(size_t sz)
Allocates a QuickVec object, doing no initialization of allocated memory.
Definition: QuickVec.hh:345
const TT_ * const_iterator
const_iterator is const-pointer-to-member type
Definition: QuickVec.hh:90
const TT_ & const_reference
const_reference is const-reference-to-member type
Definition: QuickVec.hh:92
iterator begin()
Gets an iterator to the beginning of the QuickVec.
Definition: QuickVec.hh:393
QuickVec< TT_ > & operator=(const QuickVec &other)
Copy assignment operator.
Definition: QuickVec.hh:152
virtual ~QuickVec() noexcept
Destructor calls free on data.
Definition: QuickVec.hh:365
TT_ & reference
reference is reference-to-member tpye
Definition: QuickVec.hh:91
QuickVec(const QuickVec &other)
Copy Constructor.
Definition: QuickVec.hh:138