artdaq_core  v1_07_08
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
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 USE_UNIQUE_PTR 0
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 # if USE_UNIQUE_PTR == 0
110 
113  virtual ~QuickVec() noexcept;
114 
115 # define PTR_(xx) xx
116 # else
117 # define PTR_(xx) xx.get()
118 # endif
119  //: size_(other.size()), data_(new TT_[other.capacity()]), capacity_(other.capacity())
124  QuickVec(std::vector<TT_>& other)
125  : size_(other.size())
126  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
127  , capacity_(other.capacity())
128  {
129  memcpy(PTR_(data_), (void*)&other[0], size_ * sizeof(TT_));
130  }
131 
135  void clear() { size_ = 0; }
136 
137  //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
142  QuickVec(const QuickVec& other) //= delete; // non construction-copyable
143  : size_(other.size_)
144  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
145  , capacity_(other.capacity_)
146  {
147  TRACE(10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
148  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
149  memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
150  }
151 
157  QUICKVEC& operator=(const QuickVec& other) //= delete; // non copyable
158  {
159  TRACE(10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
160  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
161  resize(other.size_);
162  memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
163  return *this;
164  }
165 # if NOT_OLD_CXXSTD
166 
170  QuickVec(QuickVec&& other) noexcept // construction-movable
171  : size_(other.size_)
172  , data_(std::move(other.data_))
173  , capacity_(other.capacity_)
174  {
175  TRACE(10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
176  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
177 # if USE_UNIQUE_PTR == 0
178  other.data_ = nullptr;
179 # endif
180  }
181 
187  QUICKVEC& operator=(QuickVec&& other) noexcept // assign movable
188  {
189  TRACE(10, "QuickVec move assign this=%p data_=%p other.data_=%p"
190  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
191  size_ = other.size_;
192  //delete [] data_;
193  free(data_);
194  data_ = std::move(other.data_);
195  capacity_ = other.capacity_;
196 # if USE_UNIQUE_PTR == 0
197  other.data_ = nullptr;
198 # endif
199  return *this;
200  }
201 # endif
202 
208  TT_& operator[](int idx);
209 
215  const TT_& operator[](int idx) const;
216 
221  size_t size() const;
222 
231  size_t capacity() const;
232 
237  iterator begin();
238 
243  const_iterator begin() const;
244 
249  iterator end();
250 
255  const_iterator end() const;
256 
264  void reserve(size_t size);
265 
274  void resize(size_t size);
275 
281  void resize(size_t size, TT_ val);
282 
294  iterator insert(const_iterator position, size_t nn, const TT_& val);
295 
308  , const_iterator last);
309 
321 
326  void swap(QuickVec& other) noexcept;
327 
332  void push_back(const value_type& val);
333 
334  QUICKVEC_VERSION
335 
336 private:
337  // Root needs the size_ member first. It must be of type int.
338  // Root then needs the [size_] comment after data_.
339  // Note: NO SPACE between "//" and "[size_]"
340  unsigned size_;
341 # if USE_UNIQUE_PTR == 0
342  TT_* data_; //[size_]
343 # else
344  std::unique_ptr<TT_[]> data_;
345 # endif
346  unsigned capacity_;
347 };
348 
349 QUICKVEC_TEMPLATE
350 inline QUICKVEC::QuickVec(size_t sz)
351 //: size_(sz), data_(new TT_[sz]), capacity_(sz)
352  : size_(sz)
353  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
354  , capacity_(sz)
355 {
356  TRACE(15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_));
357 }
358 
359 QUICKVEC_TEMPLATE
360 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
361 //: size_(sz), data_(new TT_[sz]), capacity_(sz)
362  : size_(sz)
363  , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
364  , capacity_(sz)
365 {
366  TRACE(15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_));
367  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
368  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
369 }
370 
371 #if USE_UNIQUE_PTR == 0
372 QUICKVEC_TEMPLATE
373 inline QUICKVEC::~QuickVec() noexcept
374 {
375  TRACE(15, "QuickVec %p dtor start data_=%p size_=%d"
376  , (void*)this, (void*)PTR_(data_), size_);
377  //delete [] data_;
378  free(data_);
379  TRACE(15, "QuickVec %p dtor return", (void*)this);
380 }
381 #endif
382 
383 QUICKVEC_TEMPLATE
384 inline TT_& QUICKVEC::operator[](int idx)
385 {
386  assert(idx < (int)size_);
387  return data_[idx];
388 }
389 
390 QUICKVEC_TEMPLATE
391 inline const TT_& QUICKVEC::operator[](int idx) const
392 {
393  assert(idx < (int)size_);
394  return data_[idx];
395 }
396 
397 QUICKVEC_TEMPLATE
398 inline size_t QUICKVEC::size() const { return size_; }
399 
400 QUICKVEC_TEMPLATE
401 inline size_t QUICKVEC::capacity() const { return capacity_; }
402 
403 QUICKVEC_TEMPLATE
404 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
405 
406 QUICKVEC_TEMPLATE
407 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
408 
409 QUICKVEC_TEMPLATE
410 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_) + size_); }
411 
412 QUICKVEC_TEMPLATE
413 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_) + size_); }
414 
415 QUICKVEC_TEMPLATE
416 inline void QUICKVEC::reserve(size_t size)
417 {
418  if (size > capacity_) // reallocation if true
419  {
420 # if USE_UNIQUE_PTR == 0
421  TT_* old = data_;
422  //data_ = new TT_[size];
423  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
424  memcpy(data_, old, size_ * sizeof(TT_));
425  TRACE(13, "QUICKVEC::reserve this=%p old=%p data_=%p"
426  , (void*)this, (void*)old, (void*)data_);
427  //delete [] old;
428  free(old);
429 # else
430  std::unique_ptr<TT_[]> old = std::move(data_);
431  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
432  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
433  memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
434 # endif
435  capacity_ = size;
436  // bye to old(unique_ptr)
437  }
438 }
439 
440 QUICKVEC_TEMPLATE
441 inline void QUICKVEC::resize(size_t size)
442 {
443  if (size < size_) size_ = size; // decrease
444  else if (size <= capacity_) size_ = size;
445  else // increase/reallocate
446  {
447 # if USE_UNIQUE_PTR == 0
448  TT_* old = data_;
449  //data_ = new TT_[size];
450  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
451  memcpy(data_, old, size_ * sizeof(TT_));
452  TRACE(13, "QUICKVEC::resize this=%p old=%p data_=%p"
453  , (void*)this, (void*)old, (void*)data_);
454  //delete [] old;
455  free(old);
456 # else
457  std::unique_ptr<TT_[]> old = std::move(data_);
458  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
459  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
460  memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
461 # endif
462  size_ = capacity_ = size;
463  // bye to old(unique_ptr)
464  }
465 }
466 
467 QUICKVEC_TEMPLATE
468 inline void QUICKVEC::resize(size_type size, TT_ val)
469 {
470  size_type old_size = size;
471  resize(size);
472  if (size > old_size)
473  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
474 }
475 
476 QUICKVEC_TEMPLATE
477 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
478  , size_t nn
479  , const TT_& val)
480 {
481  assert(position <= end()); // the current end
482  size_t offset = position - begin();
483  reserve(size_ + nn); // may reallocate and invalidate "position"
484 
485  iterator dst = end() + nn; // for shifting existing data after
486  iterator src = end(); // insertion point
487  size_t cnt = end() - (begin() + offset);
488  while (cnt--) *--dst = *--src;
489 
490  dst = begin() + offset;
491  size_ += nn;
492  while (nn--) *dst++ = val;
493  return begin() + offset;
494 }
495 
496 QUICKVEC_TEMPLATE
497 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
498  , const_iterator first
499  , const_iterator last)
500 {
501  assert(position <= end()); // the current end
502  size_t nn = (last - first);
503  size_t offset = position - begin();
504  reserve(size_ + nn); // may reallocate and invalidate "position"
505 
506  iterator dst = end() + nn; // for shifting existing data after
507  iterator src = end(); // insertion point
508  size_t cnt = end() - (begin() + offset);
509  while (cnt--) *--dst = *--src;
510 
511  dst = begin() + offset;
512  size_ += nn;
513  while (nn--) *dst++ = *first++;
514  return begin() + offset;
515 }
516 
517 QUICKVEC_TEMPLATE
518 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
519  , const_iterator last)
520 {
521  assert(last <= end()); // the current end
522  size_t nn = (last - first);
523  size_t offset = first - begin();
524 
525  iterator dst = begin() + offset; // for shifting existing data from last
526  iterator src = dst + nn; // to first
527  size_t cnt = end() - src;
528  while (cnt--) *dst++ = *src++;
529 
530  size_ -= nn;
531  return begin() + offset;
532 }
533 
534 QUICKVEC_TEMPLATE
535 inline void QUICKVEC::swap(QuickVec& x) noexcept
536 {
537  TRACE(12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
538  , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_));
539  std::swap(data_, x.data_);
540  std::swap(size_, x.size_);
541  std::swap(capacity_, x.capacity_);
542  TRACE(12, "QUICKVEC::swap return data_=%p x.data_=%p"
543  , (void*)PTR_(data_), (void*)PTR_(x.data_));
544 }
545 
546 QUICKVEC_TEMPLATE
547 inline void QUICKVEC::push_back(const value_type& val)
548 {
549  if (size_ == capacity_)
550  {
551  reserve(size_ + size_ / 10 + 1);
552  }
553  *end() = val;
554  ++size_;
555 }
556 
557 } // namespace
558 
559 #ifdef UNDEF_TRACE_AT_END
560 # undef TRACE
561 #endif
562 #endif /* QuickVec_hh */
iterator erase(const_iterator first, const_iterator last)
Erases elements in given range from the QuickVec.
Definition: QuickVec.hh:518
iterator end()
Gets an iterator to the end of the QuickVec.
Definition: QuickVec.hh:410
void clear()
Sets the size to 0. QuickVec does not reinitialize memory, so no further action will be taken...
Definition: QuickVec.hh:135
void reserve(size_t size)
Allocates memory for the QuickVec so that its capacity is at least size.
Definition: QuickVec.hh:416
void resize(size_t size)
Resizes the QuickVec.
Definition: QuickVec.hh:441
TT_ & operator[](int idx)
Returns a reference to a given element.
Definition: QuickVec.hh:384
size_t size_type
size_type is size_t
Definition: QuickVec.hh:95
QuickVec(std::vector< TT_ > &other)
Copies the contents of a std::vector into a new QuickVec object.
Definition: QuickVec.hh:124
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:398
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:401
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:535
iterator insert(const_iterator position, size_t nn, const TT_ &val)
Inserts an element into the QuickVec.
Definition: QuickVec.hh:477
void push_back(const value_type &val)
Adds a value to the QuickVec, resizing if necessary (adds 10% capacity)
Definition: QuickVec.hh:547
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:350
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:404
QuickVec< TT_ > & operator=(const QuickVec &other)
Copy assignment operator.
Definition: QuickVec.hh:157
virtual ~QuickVec() noexcept
Destructor calls free on data. QuickVec compiled in non-unique_ptr mode.
Definition: QuickVec.hh:373
TT_ & reference
reference is reference-to-member tpye
Definition: QuickVec.hh:91
QuickVec(const QuickVec &other)
Copy Constructor.
Definition: QuickVec.hh:142