artdaq_core  v3_01_05
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 TRACE
27 # define TRACE( lvl, ... )
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 
274  void resize(size_t size, TT_ val);
275 
287  iterator insert(const_iterator position, size_t nn, const TT_& val);
288 
301  , const_iterator last);
302 
314 
319  void swap(QuickVec& other) noexcept;
320 
325  void push_back(const value_type& val);
326 
327  QUICKVEC_VERSION
328 
329 private:
330  // Root needs the size_ member first. It must be of type int.
331  // Root then needs the [size_] comment after data_.
332  // Note: NO SPACE between "//" and "[size_]"
333  unsigned size_;
334  TT_* data_; //[size_]
335  unsigned capacity_;
336 };
337 
338 QUICKVEC_TEMPLATE
339 inline QUICKVEC::QuickVec(size_t sz)
340  : size_(sz)
341  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
342  , capacity_(sz)
343 {
344  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
345 }
346 
347 QUICKVEC_TEMPLATE
348 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
349  : size_(sz)
350  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
351  , capacity_(sz)
352 {
353  TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
354  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
355  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
356 }
357 
358 QUICKVEC_TEMPLATE
359 inline QUICKVEC::~QuickVec() noexcept
360 {
361  TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
362  , (void*)this, (void*)data_, size_);
363  free(data_);
364  TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
365 }
366 
367 QUICKVEC_TEMPLATE
368 inline TT_& QUICKVEC::operator[](int idx)
369 {
370  assert(idx < (int)size_);
371  return data_[idx];
372 }
373 
374 QUICKVEC_TEMPLATE
375 inline const TT_& QUICKVEC::operator[](int idx) const
376 {
377  assert(idx < (int)size_);
378  return data_[idx];
379 }
380 
381 QUICKVEC_TEMPLATE
382 inline size_t QUICKVEC::size() const { return size_; }
383 
384 QUICKVEC_TEMPLATE
385 inline size_t QUICKVEC::capacity() const { return capacity_; }
386 
387 QUICKVEC_TEMPLATE
388 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
389 
390 QUICKVEC_TEMPLATE
391 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
392 
393 QUICKVEC_TEMPLATE
394 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
395 
396 QUICKVEC_TEMPLATE
397 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
398 
399 QUICKVEC_TEMPLATE
400 inline void QUICKVEC::reserve(size_t size)
401 {
402  if (size > capacity_) // reallocation if true
403  {
404  TT_* old = data_;
405  //data_ = new TT_[size];
406  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
407  memcpy(data_, old, size_ * sizeof(TT_));
408  TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p"
409  , (void*)this, (void*)old, (void*)data_);
410  free(old);
411  capacity_ = size;
412  }
413 }
414 
415 QUICKVEC_TEMPLATE
416 inline void QUICKVEC::resize(size_t size)
417 {
418  if (size < size_) size_ = size; // decrease
419  else if (size <= capacity_) size_ = size;
420  else // increase/reallocate
421  {
422  TT_* old = data_;
423  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
424  memcpy(data_, old, size_ * sizeof(TT_));
425  TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p"
426  , (void*)this, (void*)old, (void*)data_);
427  free(old);
428  size_ = capacity_ = size;
429  }
430 }
431 
432 QUICKVEC_TEMPLATE
433 inline void QUICKVEC::resize(size_type size, TT_ val)
434 {
435  size_type old_size = size;
436  resize(size);
437  if (size > old_size) {
438  TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
439  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
440  }
441 }
442 
443 QUICKVEC_TEMPLATE
444 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
445  , size_t nn
446  , const TT_& val)
447 {
448  assert(position <= end()); // the current end
449  size_t offset = position - begin();
450  reserve(size_ + nn); // may reallocate and invalidate "position"
451 
452  iterator dst = end() + nn; // for shifting existing data after
453  iterator src = end(); // insertion point
454  size_t cnt = end() - (begin() + offset);
455  while (cnt--) *--dst = *--src;
456 
457  dst = begin() + offset;
458  size_ += nn;
459  while (nn--) *dst++ = val;
460  return begin() + offset;
461 }
462 
463 QUICKVEC_TEMPLATE
464 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
465  , const_iterator first
466  , const_iterator last)
467 {
468  assert(position <= end()); // the current end
469  size_t nn = (last - first);
470  size_t offset = position - begin();
471  reserve(size_ + nn); // may reallocate and invalidate "position"
472 
473  iterator dst = end() + nn; // for shifting existing data after
474  iterator src = end(); // insertion point
475  size_t cnt = end() - (begin() + offset);
476  while (cnt--) *--dst = *--src;
477 
478  dst = begin() + offset;
479  size_ += nn;
480  while (nn--) *dst++ = *first++;
481  return begin() + offset;
482 }
483 
484 QUICKVEC_TEMPLATE
485 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
486  , const_iterator last)
487 {
488  assert(last <= end()); // the current end
489  size_t nn = (last - first);
490  size_t offset = first - begin();
491 
492  iterator dst = begin() + offset; // for shifting existing data from last
493  iterator src = dst + nn; // to first
494  size_t cnt = end() - src;
495  while (cnt--) *dst++ = *src++;
496 
497  size_ -= nn;
498  return begin() + offset;
499 }
500 
501 QUICKVEC_TEMPLATE
502 inline void QUICKVEC::swap(QuickVec& x) noexcept
503 {
504  TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
505  , (void*)this, (void*)data_, (void*)x.data_ );
506  std::swap(data_, x.data_);
507  std::swap(size_, x.size_);
508  std::swap(capacity_, x.capacity_);
509  TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
510  , (void*)data_, (void*)x.data_ );
511 }
512 
513 QUICKVEC_TEMPLATE
514 inline void QUICKVEC::push_back(const value_type& val)
515 {
516  if (size_ == capacity_)
517  {
518  reserve(size_ + size_ / 10 + 1);
519  }
520  *end() = val;
521  ++size_;
522 }
523 
524 } // namespace
525 
526 #ifdef UNDEF_TRACE_AT_END
527 # undef TRACE
528 # undef TRACEN
529 #endif
530 #endif /* QuickVec_hh */
iterator erase(const_iterator first, const_iterator last)
Erases elements in given range from the QuickVec.
Definition: QuickVec.hh:485
iterator end()
Gets an iterator to the end of the QuickVec.
Definition: QuickVec.hh:394
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:400
void resize(size_t size)
Resizes the QuickVec.
Definition: QuickVec.hh:416
TT_ & operator[](int idx)
Returns a reference to a given element.
Definition: QuickVec.hh:368
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:382
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:385
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:502
iterator insert(const_iterator position, size_t nn, const TT_ &val)
Inserts an element into the QuickVec.
Definition: QuickVec.hh:444
void push_back(const value_type &val)
Adds a value to the QuickVec, resizing if necessary (adds 10% capacity)
Definition: QuickVec.hh:514
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:339
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:388
QuickVec< TT_ > & operator=(const QuickVec &other)
Copy assignment operator.
Definition: QuickVec.hh:154
virtual ~QuickVec() noexcept
Destructor calls free on data.
Definition: QuickVec.hh:359
TT_ & reference
reference is reference-to-member tpye
Definition: QuickVec.hh:91
QuickVec(const QuickVec &other)
Copy Constructor.
Definition: QuickVec.hh:139