artdaq_core  v3_05_00
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 <vector>
25 //#include "trace.h" // TRACE
26 #ifndef TRACEN
27 # define TRACEN( nam, lvl, ... )
28 # define UNDEF_TRACE_AT_END
29 #endif
30 
31 #define QV_ALIGN 512
32 
39 static inline void* QV_MEMALIGN(size_t boundary, size_t size)
40 {
41  void* retadr;
42  posix_memalign(&retadr, boundary, size);
43  return retadr;
44 }
45 
46 #ifndef QUICKVEC_DO_TEMPLATE
47 # define QUICKVEC_DO_TEMPLATE 1
48 #endif
49 
50 #undef NOT_OLD_CXXSTD
51 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
52 # define NOT_OLD_CXXSTD 1
53 #endif
54 
55 #if QUICKVEC_DO_TEMPLATE == 0
56 # ifndef QUICKVEC_TT
57 # define QUICKVEC_TT unsigned long long
58 # endif
59 # define TT_ QUICKVEC_TT
60 # define QUICKVEC_TEMPLATE
61 # define QUICKVEC QuickVec
62 # define QUICKVEC_TN QuickVec
63 # define QUICKVEC_VERSION
64 #else
65 # define QUICKVEC_TEMPLATE template <typename TT_>
66 # define QUICKVEC QuickVec<TT_>
67 # define QUICKVEC_TN typename QuickVec<TT_>
68 # define QUICKVEC_VERSION \
69  \
75 static short Class_Version() { return 5; } // proper version for templates
76 #endif
77 
78 namespace artdaq {
79 
85 QUICKVEC_TEMPLATE
86 struct QuickVec
87 {
88  typedef TT_* iterator;
89  typedef const TT_* const_iterator;
90  typedef TT_& reference;
91  typedef const TT_& const_reference;
92  typedef TT_ value_type;
93  typedef ptrdiff_t difference_type;
94  typedef size_t size_type;
95 
100  QuickVec(size_t sz);
101 
107  QuickVec(size_t sz, TT_ val);
108 
112  virtual ~QuickVec() noexcept;
113 
118  QuickVec(std::vector<TT_>& other)
119  : size_(other.size())
120  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
121  , capacity_(other.capacity())
122  {
123  TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d"
124  , (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"
144  , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
145  memcpy( data_, other.data_, size_ * sizeof(TT_));
146  }
147 
153  QUICKVEC& operator=(const QuickVec& other) //= delete; // non copyable
154  {
155  TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
156  , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
157  resize(other.size_);
158  memcpy( data_, other.data_, size_ * sizeof(TT_));
159  return *this;
160  }
161 # if NOT_OLD_CXXSTD
162 
166  QuickVec(QuickVec&& other) noexcept // construction-movable
167  : size_(other.size_)
168  , data_(std::move(other.data_))
169  , capacity_(other.capacity_)
170  {
171  TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
172  , (void*)this, (void*)data_, (void*)other.data_ );
173  other.data_ = nullptr;
174  }
175 
181  QUICKVEC& operator=(QuickVec&& other) noexcept // assign movable
182  {
183  TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
184  , (void*)this, (void*)data_, (void*)other.data_ );
185  size_ = other.size_;
186  //delete [] data_;
187  free(data_);
188  data_ = std::move(other.data_);
189  capacity_ = other.capacity_;
190  other.data_ = nullptr;
191  return *this;
192  }
193 # endif
194 
200  TT_& operator[](int idx);
201 
207  const TT_& operator[](int idx) const;
208 
213  size_t size() const;
214 
223  size_t capacity() const;
224 
229  iterator begin();
230 
235  const_iterator begin() const;
236 
241  iterator end();
242 
247  const_iterator end() const;
248 
256  void reserve(size_t size);
257 
266  void resize(size_t size);
267 
278  void resizeWithCushion(size_t size, double growthFactor = 1.3);
279 
285  void resize(size_t size, TT_ val);
286 
298  iterator insert(const_iterator position, size_t nn, const TT_& val);
299 
312  , const_iterator last);
313 
325 
330  void swap(QuickVec& other) noexcept;
331 
336  void push_back(const value_type& val);
337 
338  QUICKVEC_VERSION
339 
340 private:
341  // Root needs the size_ member first. It must be of type int.
342  // Root then needs the [size_] comment after data_.
343  // Note: NO SPACE between "//" and "[size_]"
344  unsigned size_;
345  TT_* data_; //[size_]
346  unsigned capacity_;
347 };
348 
349 QUICKVEC_TEMPLATE
350 inline QUICKVEC::QuickVec(size_t sz)
351  : size_(sz)
352  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
353  , capacity_(sz)
354 {
355  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
356 }
357 
358 QUICKVEC_TEMPLATE
359 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
360  : size_(sz)
361  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
362  , capacity_(sz)
363 {
364  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
365  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
366  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
367 }
368 
369 QUICKVEC_TEMPLATE
370 inline QUICKVEC::~QuickVec() noexcept
371 {
372  TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
373  , (void*)this, (void*)data_, size_);
374  free(data_);
375  TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
376 }
377 
378 QUICKVEC_TEMPLATE
379 inline TT_& QUICKVEC::operator[](int idx)
380 {
381  assert(idx < (int)size_);
382  return data_[idx];
383 }
384 
385 QUICKVEC_TEMPLATE
386 inline const TT_& QUICKVEC::operator[](int idx) const
387 {
388  assert(idx < (int)size_);
389  return data_[idx];
390 }
391 
392 QUICKVEC_TEMPLATE
393 inline size_t QUICKVEC::size() const { return size_; }
394 
395 QUICKVEC_TEMPLATE
396 inline size_t QUICKVEC::capacity() const { return capacity_; }
397 
398 QUICKVEC_TEMPLATE
399 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
400 
401 QUICKVEC_TEMPLATE
402 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
403 
404 QUICKVEC_TEMPLATE
405 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
406 
407 QUICKVEC_TEMPLATE
408 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
409 
410 QUICKVEC_TEMPLATE
411 inline void QUICKVEC::reserve(size_t size)
412 {
413  if (size > capacity_) // reallocation if true
414  {
415  TT_* old = data_;
416  //data_ = new TT_[size];
417  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
418  memcpy(data_, old, size_ * sizeof(TT_));
419  TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p capacity=%d"
420  , (void*)this, (void*)old, (void*)data_, (int)size);
421  free(old);
422  capacity_ = size;
423  }
424 }
425 
426 QUICKVEC_TEMPLATE
427 inline void QUICKVEC::resize(size_t size)
428 {
429  if (size < size_) size_ = size; // decrease
430  else if (size <= capacity_) size_ = size;
431  else // increase/reallocate
432  {
433  TT_* old = data_;
434  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
435  memcpy(data_, old, size_ * sizeof(TT_));
436  TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p size=%d"
437  , (void*)this, (void*)old, (void*)data_, (int)size);
438  free(old);
439  size_ = capacity_ = size;
440  }
441 }
442 
443 QUICKVEC_TEMPLATE
444 inline void QUICKVEC::resizeWithCushion(size_t size, double growthFactor)
445 {
446  if (size > capacity_)
447  {
448  size_t new_size = std::round(capacity_ * growthFactor);
449  if (new_size < size) {new_size = size;}
450  if (new_size < 512) {new_size = 512;}
451  else if (new_size < 2048) {new_size = 2048;}
452  else if (new_size < 4096) {new_size = 4096;}
453  else if (new_size < 8192) {new_size = 8192;}
454  reserve(new_size);
455  }
456  resize(size);
457 }
458 
459 QUICKVEC_TEMPLATE
460 inline void QUICKVEC::resize(size_type size, TT_ val)
461 {
462  size_type old_size = size;
463  resize(size);
464  if (size > old_size) {
465  TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
466  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
467  }
468 }
469 
470 QUICKVEC_TEMPLATE
471 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
472  , size_t nn
473  , const TT_& val)
474 {
475  assert(position <= end()); // the current end
476  size_t offset = position - begin();
477  reserve(size_ + nn); // may reallocate and invalidate "position"
478 
479  iterator dst = end() + nn; // for shifting existing data after
480  iterator src = end(); // insertion point
481  size_t cnt = end() - (begin() + offset);
482  while (cnt--) *--dst = *--src;
483 
484  dst = begin() + offset;
485  size_ += nn;
486  while (nn--) *dst++ = val;
487  return begin() + offset;
488 }
489 
490 QUICKVEC_TEMPLATE
491 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
492  , const_iterator first
493  , 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
513  , const_iterator last)
514 {
515  assert(last <= end()); // the current end
516  size_t nn = (last - first);
517  size_t offset = first - begin();
518 
519  iterator dst = begin() + offset; // for shifting existing data from last
520  iterator src = dst + nn; // to first
521  size_t cnt = end() - src;
522  while (cnt--) *dst++ = *src++;
523 
524  size_ -= nn;
525  return begin() + offset;
526 }
527 
528 QUICKVEC_TEMPLATE
529 inline void QUICKVEC::swap(QuickVec& x) noexcept
530 {
531  TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
532  , (void*)this, (void*)data_, (void*)x.data_ );
533  std::swap(data_, x.data_);
534  std::swap(size_, x.size_);
535  std::swap(capacity_, x.capacity_);
536  TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
537  , (void*)data_, (void*)x.data_ );
538 }
539 
540 QUICKVEC_TEMPLATE
541 inline void QUICKVEC::push_back(const value_type& val)
542 {
543  if (size_ == capacity_)
544  {
545  reserve(size_ + size_ / 10 + 1);
546  }
547  *end() = val;
548  ++size_;
549 }
550 
551 } // namespace
552 
553 #ifdef UNDEF_TRACE_AT_END
554 # undef TRACEN
555 # undef UNDEF_TRACE_AT_END
556 #endif
557 #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:405
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:411
void resize(size_t size)
Resizes the QuickVec.
Definition: QuickVec.hh:427
TT_ & operator[](int idx)
Returns a reference to a given element.
Definition: QuickVec.hh:379
size_t size_type
size_type is size_t
Definition: QuickVec.hh:94
TT_ value_type
value_type is member type
Definition: QuickVec.hh:92
size_t size() const
Accesses the current size of the QuickVec.
Definition: QuickVec.hh:393
TT_ * iterator
Iterator is pointer-to-member type.
Definition: QuickVec.hh:88
ptrdiff_t difference_type
difference_type is ptrdiff_t
Definition: QuickVec.hh:93
size_t capacity() const
Accesses the current capacity of the QuickVec.
Definition: QuickVec.hh:396
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:529
void resizeWithCushion(size_t size, double growthFactor=1.3)
Resizes the QuickVec and requests additional capacity.
Definition: QuickVec.hh:444
iterator insert(const_iterator position, size_t nn, const TT_ &val)
Inserts an element into the QuickVec.
Definition: QuickVec.hh:471
void push_back(const value_type &val)
Adds a value to the QuickVec, resizing if necessary (adds 10% capacity)
Definition: QuickVec.hh:541
A QuickVec behaves like a std::vector, but does no initialization of its data, making it faster at th...
Definition: QuickVec.hh:86
QuickVec(size_t sz)
Allocates a QuickVec object, doing no initialization of allocated memory.
Definition: QuickVec.hh:350
const TT_ * const_iterator
const_iterator is const-pointer-to-member type
Definition: QuickVec.hh:89
const TT_ & const_reference
const_reference is const-reference-to-member type
Definition: QuickVec.hh:91
iterator begin()
Gets an iterator to the beginning of the QuickVec.
Definition: QuickVec.hh:399
QuickVec< TT_ > & operator=(const QuickVec &other)
Copy assignment operator.
Definition: QuickVec.hh:153
virtual ~QuickVec() noexcept
Destructor calls free on data.
Definition: QuickVec.hh:370
TT_ & reference
reference is reference-to-member tpye
Definition: QuickVec.hh:90
QuickVec(const QuickVec &other)
Copy Constructor.
Definition: QuickVec.hh:138