artdaq_core  v1_07_01
 All Classes Namespaces Functions
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 <cassert>
18 //#include <cstddef> // ptrdiff_t
19 //#include <utility> // std::swap
20 //#include <memory> // unique_ptr
21 #include <vector>
22 
23 //#include "trace.h" // TRACE
24 #ifndef TRACE
25 # define TRACE( lvl, ... )
26 # define UNDEF_TRACE_AT_END
27 #endif
28 
29 #define USE_UNIQUE_PTR 0
30 #define QV_ALIGN 512
31 static inline void *QV_MEMALIGN(size_t boundary, size_t size) { void *retadr; posix_memalign(&retadr, boundary, size); return retadr; }
32 
33 #ifndef QUICKVEC_DO_TEMPLATE
34 # define QUICKVEC_DO_TEMPLATE 1
35 #endif
36 
37 #undef NOT_OLD_CXXSTD
38 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
39 # define NOT_OLD_CXXSTD 1
40 #endif
41 
42 #if QUICKVEC_DO_TEMPLATE == 0
43 # ifndef QUICKVEC_TT
44 # define QUICKVEC_TT unsigned long long
45 # endif
46 # define TT_ QUICKVEC_TT
47 # define QUICKVEC_TEMPLATE
48 # define QUICKVEC QuickVec
49 # define QUICKVEC_TN QuickVec
50 # define QUICKVEC_VERSION
51 #else
52 # define QUICKVEC_TEMPLATE template <typename TT_>
53 # define QUICKVEC QuickVec<TT_>
54 # define QUICKVEC_TN typename QuickVec<TT_>
55 // Class_Version() MUST be updated every time private member data change.
56 # define QUICKVEC_VERSION static short Class_Version() { return 5; } // proper version for templates
57 #endif
58 
59 QUICKVEC_TEMPLATE
60 struct QuickVec
61 {
62  typedef TT_* iterator;
63  typedef const TT_* const_iterator;
64  typedef TT_& reference;
65  typedef const TT_& const_reference;
66  typedef TT_ value_type;
67  typedef ptrdiff_t difference_type;
68  typedef size_t size_type;
69 
70  QuickVec(size_t sz);
71  QuickVec(size_t sz, TT_ val);
72 # if USE_UNIQUE_PTR == 0
73  virtual ~QuickVec() noexcept;
74 # define PTR_(xx) xx
75 # else
76 # define PTR_(xx) xx.get()
77 # endif
78  QuickVec(std::vector<TT_> & other)
79  //: size_(other.size()), data_(new TT_[other.capacity()]), capacity_(other.capacity())
80  : size_(other.size()), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity())
81  {
82  memcpy(PTR_(data_), (void*)&other[0], size_ * sizeof(TT_));
83  }
84  void clear() { size_ = 0; }
85 
86  QuickVec(const QuickVec & other) //= delete; // non construction-copyable
87  //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
88  : size_(other.size_), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity_)
89  {
90  TRACE(10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
91  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
92  memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
93  }
94  QUICKVEC & operator=(const QuickVec & other) //= delete; // non copyable
95  {
96  TRACE(10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
97  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
98  resize(other.size_);
99  memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
100  return *this;
101  }
102 # if NOT_OLD_CXXSTD
103  QuickVec(QuickVec && other) noexcept // construction-movable
104  : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
105  {
106  TRACE(10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
107  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
108 # if USE_UNIQUE_PTR == 0
109  other.data_ = nullptr;
110 # endif
111  }
112  QUICKVEC & operator=(QuickVec && other) noexcept // assign movable
113  {
114  TRACE(10, "QuickVec move assign this=%p data_=%p other.data_=%p"
115  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
116  size_ = other.size_;
117  //delete [] data_;
118  free(data_);
119  data_ = std::move(other.data_);
120  capacity_ = other.capacity_;
121 # if USE_UNIQUE_PTR == 0
122  other.data_ = nullptr;
123 # endif
124  return *this;
125  }
126 # endif
127 
128  TT_& operator[](int idx);
129  const TT_& operator[](int idx) const;
130  size_t size() const;
131  size_t capacity() const;
132  iterator begin();
133  const_iterator begin() const;
134  iterator end();
135  const_iterator end() const;
136  void reserve(size_t size);
137  void resize(size_t size);
138  void resize(size_t size, TT_ val);
139  iterator insert(const_iterator position, size_t nn, const TT_& val);
140  iterator insert(const_iterator position, const_iterator first
141  , const_iterator last);
142  iterator erase(const_iterator first, const_iterator last);
143  void swap(QuickVec& x) noexcept;
144  void push_back(const value_type& val);
145 
146  QUICKVEC_VERSION
147 
148 private:
149  // Root needs the size_ member first. It must be of type int.
150  // Root then needs the [size_] comment after data_.
151  // Note: NO SPACE between "//" and "[size_]"
152  unsigned size_;
153 # if USE_UNIQUE_PTR == 0
154  TT_ * data_; //[size_]
155 # else
156  std::unique_ptr<TT_[]> data_;
157 # endif
158  unsigned capacity_;
159 };
160 
161 QUICKVEC_TEMPLATE
162 inline QUICKVEC::QuickVec(size_t sz)
163 //: size_(sz), data_(new TT_[sz]), capacity_(sz)
164  : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
165 {
166  TRACE(15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_));
167 }
168 QUICKVEC_TEMPLATE
169 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
170 //: size_(sz), data_(new TT_[sz]), capacity_(sz)
171  : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
172 {
173  TRACE(15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_));
174  for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
175  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
176 }
177 
178 #if USE_UNIQUE_PTR == 0
179 QUICKVEC_TEMPLATE
180 inline QUICKVEC::~QuickVec() noexcept
181 {
182  TRACE(15, "QuickVec %p dtor start data_=%p size_=%d"
183  , (void*)this, (void*)PTR_(data_), size_);
184  //delete [] data_;
185  free(data_);
186  TRACE(15, "QuickVec %p dtor return", (void*)this);
187 }
188 #endif
189 
190 QUICKVEC_TEMPLATE
191 inline TT_& QUICKVEC::operator[](int idx)
192 {
193  assert(idx < (int)size_); return data_[idx];
194 }
195 
196 QUICKVEC_TEMPLATE
197 inline const TT_& QUICKVEC::operator[](int idx) const
198 {
199  assert(idx < (int)size_);
200  return data_[idx];
201 }
202 
203 QUICKVEC_TEMPLATE
204 inline size_t QUICKVEC::size() const { return size_; }
205 QUICKVEC_TEMPLATE
206 inline size_t QUICKVEC::capacity() const { return capacity_; }
207 
208 QUICKVEC_TEMPLATE
209 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
210 QUICKVEC_TEMPLATE
211 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
212 QUICKVEC_TEMPLATE
213 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_) + size_); }
214 QUICKVEC_TEMPLATE
215 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_) + size_); }
216 
217 QUICKVEC_TEMPLATE
218 inline void QUICKVEC::reserve(size_t size)
219 {
220  if (size > capacity_) // reallocation if true
221  {
222 # if USE_UNIQUE_PTR == 0
223  TT_ * old = data_;
224  //data_ = new TT_[size];
225  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
226  memcpy(data_, old, size_ * sizeof(TT_));
227  TRACE(13, "QUICKVEC::reserve this=%p old=%p data_=%p"
228  , (void*)this, (void*)old, (void*)data_);
229  //delete [] old;
230  free(old);
231 # else
232  std::unique_ptr<TT_[]> old = std::move(data_);
233  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
234  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
235  memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
236 # endif
237  capacity_ = size;
238  // bye to old(unique_ptr)
239  }
240 }
241 
242 QUICKVEC_TEMPLATE
243 inline void QUICKVEC::resize(size_t size)
244 {
245  if (size < size_) size_ = size; // decrease
246  else if (size <= capacity_) size_ = size;
247  else // increase/reallocate
248  {
249 # if USE_UNIQUE_PTR == 0
250  TT_ * old = data_;
251  //data_ = new TT_[size];
252  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
253  memcpy(data_, old, size_ * sizeof(TT_));
254  TRACE(13, "QUICKVEC::resize this=%p old=%p data_=%p"
255  , (void*)this, (void*)old, (void*)data_);
256  //delete [] old;
257  free(old);
258 # else
259  std::unique_ptr<TT_[]> old = std::move(data_);
260  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
261  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
262  memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
263 # endif
264  size_ = capacity_ = size;
265  // bye to old(unique_ptr)
266  }
267 }
268 QUICKVEC_TEMPLATE
269 inline void QUICKVEC::resize(size_type size, TT_ val)
270 {
271  size_type old_size = size;
272  resize(size);
273  if (size > old_size)
274  for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
275 }
276 
277 QUICKVEC_TEMPLATE
278 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
279  , size_t nn
280  , const TT_& val)
281 {
282  assert(position <= end()); // the current end
283  size_t offset = position - begin();
284  reserve(size_ + nn); // may reallocate and invalidate "position"
285 
286  iterator dst = end() + nn; // for shifting existing data after
287  iterator src = end(); // insertion point
288  size_t cnt = end() - (begin() + offset);
289  while (cnt--) *--dst = *--src;
290 
291  dst = begin() + offset;
292  size_ += nn;
293  while (nn--) *dst++ = val;
294  return begin() + offset;
295 }
296 QUICKVEC_TEMPLATE
297 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
298  , const_iterator first
299  , const_iterator last)
300 {
301  assert(position <= end()); // the current end
302  size_t nn = (last - first);
303  size_t offset = position - begin();
304  reserve(size_ + nn); // may reallocate and invalidate "position"
305 
306  iterator dst = end() + nn; // for shifting existing data after
307  iterator src = end(); // insertion point
308  size_t cnt = end() - (begin() + offset);
309  while (cnt--) *--dst = *--src;
310 
311  dst = begin() + offset;
312  size_ += nn;
313  while (nn--) *dst++ = *first++;
314  return begin() + offset;
315 }
316 
317 QUICKVEC_TEMPLATE
318 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
319  , const_iterator last)
320 {
321  assert(last <= end()); // the current end
322  size_t nn = (last - first);
323  size_t offset = first - begin();
324 
325  iterator dst = begin() + offset; // for shifting existing data from last
326  iterator src = dst + nn; // to first
327  size_t cnt = end() - src;
328  while (cnt--) *dst++ = *src++;
329 
330  size_ -= nn;
331  return begin() + offset;
332 }
333 
334 QUICKVEC_TEMPLATE
335 inline void QUICKVEC::swap(QuickVec& x) noexcept
336 {
337  TRACE(12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
338  , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_));
339  std::swap(data_, x.data_);
340  std::swap(size_, x.size_);
341  std::swap(capacity_, x.capacity_);
342  TRACE(12, "QUICKVEC::swap return data_=%p x.data_=%p"
343  , (void*)PTR_(data_), (void*)PTR_(x.data_));
344 }
345 
346 QUICKVEC_TEMPLATE
347 inline void QUICKVEC::push_back(const value_type& val)
348 {
349  if (size_ == capacity_)
350  {
351  reserve(size_ + size_ / 10 + 1);
352  }
353  *end() = val;
354  ++size_;
355 }
356 
357 #ifdef UNDEF_TRACE_AT_END
358 # undef TRACE
359 #endif
360 #endif /* QuickVec_hh */