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