artdaq_core  v3_05_03
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"
125  , (void*)this, (void*)data_, (void*)&other[0], size_, other.size());
126  memcpy( data_, (void*)&other[0], size_ * sizeof(TT_));
127  }
128 
132  void clear() { size_ = 0; }
133 
134  //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
139  QuickVec(const QuickVec& other) //= delete; // non construction-copyable
140  : size_(other.size_)
141  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
142  , capacity_(other.capacity_)
143  {
144  TRACEN("QuickVec",10, "QuickVec copy ctor b4 memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
145  , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
146  memcpy( data_, other.data_, size_ * sizeof(TT_));
147  }
148 
154  QUICKVEC& operator=(const QuickVec& other) //= delete; // non copyable
155  {
156  TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
157  , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
158  resize(other.size_);
159  memcpy( data_, other.data_, size_ * sizeof(TT_));
160  return *this;
161  }
162 # if NOT_OLD_CXXSTD
163 
167  QuickVec(QuickVec&& other) noexcept // construction-movable
168  : size_(other.size_)
169  , data_(std::move(other.data_))
170  , capacity_(other.capacity_)
171  {
172  TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
173  , (void*)this, (void*)data_, (void*)other.data_ );
174  other.data_ = nullptr;
175  }
176 
182  QUICKVEC& operator=(QuickVec&& other) noexcept // assign movable
183  {
184  TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
185  , (void*)this, (void*)data_, (void*)other.data_ );
186  size_ = other.size_;
187  //delete [] data_;
188  free(data_);
189  data_ = std::move(other.data_);
190  capacity_ = other.capacity_;
191  other.data_ = nullptr;
192  return *this;
193  }
194 # endif
195 
201  TT_& operator[](int idx);
202 
208  const TT_& operator[](int idx) const;
209 
214  size_t size() const;
215 
224  size_t capacity() const;
225 
230  iterator begin();
231 
236  const_iterator begin() const;
237 
242  iterator end();
243 
248  const_iterator end() const;
249 
257  void reserve(size_t size);
258 
267  void resize(size_t size);
268 
279  void resizeWithCushion(size_t size, double growthFactor = 1.3);
280 
286  void resize(size_t size, TT_ val);
287 
299  iterator insert(const_iterator position, size_t nn, const TT_& val);
300 
313  , const_iterator last);
314 
326 
331  void swap(QuickVec& other) noexcept;
332 
337  void push_back(const value_type& val);
338 
339  QUICKVEC_VERSION
340 
341 private:
342  // Root needs the size_ member first. It must be of type int.
343  // Root then needs the [size_] comment after data_.
344  // Note: NO SPACE between "//" and "[size_]"
345  unsigned size_;
346  TT_* data_; //[size_]
347  unsigned capacity_;
348 };
349 
350 QUICKVEC_TEMPLATE
351 inline QUICKVEC::QuickVec(size_t sz)
352  : size_(sz)
353  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
354  , capacity_(sz)
355 {
356  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
357 }
358 
359 QUICKVEC_TEMPLATE
360 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
361  : size_(sz)
362  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
363  , capacity_(sz)
364 {
365  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
366  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
367  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
368 }
369 
370 QUICKVEC_TEMPLATE
371 inline QUICKVEC::~QuickVec() noexcept
372 {
373  TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
374  , (void*)this, (void*)data_, size_);
375  free(data_);
376  TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
377 }
378 
379 QUICKVEC_TEMPLATE
380 inline TT_& QUICKVEC::operator[](int idx)
381 {
382  assert(idx < (int)size_);
383  return data_[idx];
384 }
385 
386 QUICKVEC_TEMPLATE
387 inline const TT_& QUICKVEC::operator[](int idx) const
388 {
389  assert(idx < (int)size_);
390  return data_[idx];
391 }
392 
393 QUICKVEC_TEMPLATE
394 inline size_t QUICKVEC::size() const { return size_; }
395 
396 QUICKVEC_TEMPLATE
397 inline size_t QUICKVEC::capacity() const { return capacity_; }
398 
399 QUICKVEC_TEMPLATE
400 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
401 
402 QUICKVEC_TEMPLATE
403 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
404 
405 QUICKVEC_TEMPLATE
406 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
407 
408 QUICKVEC_TEMPLATE
409 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
410 
411 QUICKVEC_TEMPLATE
412 inline void QUICKVEC::reserve(size_t size)
413 {
414  if (size > capacity_) // reallocation if true
415  {
416  TT_* old = data_;
417  //data_ = new TT_[size];
418  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
419  memcpy(data_, old, size_ * sizeof(TT_));
420  TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p capacity=%d"
421  , (void*)this, (void*)old, (void*)data_, (int)size);
422  free(old);
423  capacity_ = size;
424  }
425 }
426 
427 QUICKVEC_TEMPLATE
428 inline void QUICKVEC::resize(size_t size)
429 {
430  if (size < size_) size_ = size; // decrease
431  else if (size <= capacity_) size_ = size;
432  else // increase/reallocate
433  {
434  TT_* old = data_;
435  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
436  memcpy(data_, old, size_ * sizeof(TT_));
437  TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p size=%d"
438  , (void*)this, (void*)old, (void*)data_, (int)size);
439  free(old);
440  size_ = capacity_ = size;
441  }
442 }
443 
444 QUICKVEC_TEMPLATE
445 inline void QUICKVEC::resizeWithCushion(size_t size, double growthFactor)
446 {
447  if (size > capacity_)
448  {
449  size_t new_size = std::round(capacity_ * growthFactor);
450  if (new_size < size) {new_size = size;}
451  if (new_size < 512) {new_size = 512;}
452  else if (new_size < 2048) {new_size = 2048;}
453  else if (new_size < 4096) {new_size = 4096;}
454  else if (new_size < 8192) {new_size = 8192;}
455  reserve(new_size);
456  }
457  resize(size);
458 }
459 
460 QUICKVEC_TEMPLATE
461 inline void QUICKVEC::resize(size_type size, TT_ val)
462 {
463  size_type old_size = size;
464  resize(size);
465  if (size > old_size) {
466  TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
467  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
468  }
469 }
470 
471 QUICKVEC_TEMPLATE
472 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
473  , size_t nn
474  , const TT_& val)
475 {
476  assert(position <= end()); // the current end
477  size_t offset = position - begin();
478  reserve(size_ + nn); // may reallocate and invalidate "position"
479 
480  iterator dst = end() + nn; // for shifting existing data after
481  iterator src = end(); // insertion point
482  size_t cnt = end() - (begin() + offset);
483  while (cnt--) *--dst = *--src;
484 
485  dst = begin() + offset;
486  size_ += nn;
487  while (nn--) *dst++ = val;
488  return begin() + offset;
489 }
490 
491 QUICKVEC_TEMPLATE
492 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
493  , const_iterator first
494  , const_iterator last)
495 {
496  assert(position <= end()); // the current end
497  size_t nn = (last - first);
498  size_t offset = position - begin();
499  reserve(size_ + nn); // may reallocate and invalidate "position"
500 
501  iterator dst = end() + nn; // for shifting existing data after
502  iterator src = end(); // insertion point
503  size_t cnt = end() - (begin() + offset);
504  while (cnt--) *--dst = *--src;
505 
506  dst = begin() + offset;
507  size_ += nn;
508  while (nn--) *dst++ = *first++;
509  return begin() + offset;
510 }
511 
512 QUICKVEC_TEMPLATE
513 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
514  , const_iterator last)
515 {
516  assert(last <= end()); // the current end
517  size_t nn = (last - first);
518  size_t offset = first - begin();
519 
520  iterator dst = begin() + offset; // for shifting existing data from last
521  iterator src = dst + nn; // to first
522  size_t cnt = end() - src;
523  while (cnt--) *dst++ = *src++;
524 
525  size_ -= nn;
526  return begin() + offset;
527 }
528 
529 QUICKVEC_TEMPLATE
530 inline void QUICKVEC::swap(QuickVec& x) noexcept
531 {
532  TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
533  , (void*)this, (void*)data_, (void*)x.data_ );
534  std::swap(data_, x.data_);
535  std::swap(size_, x.size_);
536  std::swap(capacity_, x.capacity_);
537  TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
538  , (void*)data_, (void*)x.data_ );
539 }
540 
541 QUICKVEC_TEMPLATE
542 inline void QUICKVEC::push_back(const value_type& val)
543 {
544  if (size_ == capacity_)
545  {
546  reserve(size_ + size_ / 10 + 1);
547  }
548  *end() = val;
549  ++size_;
550 }
551 
552 } // namespace
553 
554 #ifdef UNDEF_TRACE_AT_END
555 # undef TRACEN
556 # undef UNDEF_TRACE_AT_END
557 #endif
558 #endif /* QuickVec_hh */
iterator erase(const_iterator first, const_iterator last)
Erases elements in given range from the QuickVec.
Definition: QuickVec.hh:513
iterator end()
Gets an iterator to the end of the QuickVec.
Definition: QuickVec.hh:406
void clear()
Sets the size to 0. QuickVec does not reinitialize memory, so no further action will be taken...
Definition: QuickVec.hh:132
void reserve(size_t size)
Allocates memory for the QuickVec so that its capacity is at least size.
Definition: QuickVec.hh:412
void resize(size_t size)
Resizes the QuickVec.
Definition: QuickVec.hh:428
TT_ & operator[](int idx)
Returns a reference to a given element.
Definition: QuickVec.hh:380
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:394
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:397
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:530
void resizeWithCushion(size_t size, double growthFactor=1.3)
Resizes the QuickVec and requests additional capacity.
Definition: QuickVec.hh:445
iterator insert(const_iterator position, size_t nn, const TT_ &val)
Inserts an element into the QuickVec.
Definition: QuickVec.hh:472
void push_back(const value_type &val)
Adds a value to the QuickVec, resizing if necessary (adds 10% capacity)
Definition: QuickVec.hh:542
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:351
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:400
QuickVec< TT_ > & operator=(const QuickVec &other)
Copy assignment operator.
Definition: QuickVec.hh:154
virtual ~QuickVec() noexcept
Destructor calls free on data.
Definition: QuickVec.hh:371
TT_ & reference
reference is reference-to-member tpye
Definition: QuickVec.hh:91
QuickVec(const QuickVec &other)
Copy Constructor.
Definition: QuickVec.hh:139