artdaq_core  v1_07_00
 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  ~QuickVec();
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  { memcpy( PTR_(data_), (void*)&other[0], size_*sizeof(TT_) );
82  }
83  void clear() { size_=0; }
84 
85  QuickVec( const QuickVec & other ) //= delete; // non construction-copyable
86  //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
87  : size_(other.size_), data_((TT_*)QV_MEMALIGN(QV_ALIGN,other.capacity()*sizeof(TT_))), capacity_(other.capacity_)
88  { TRACE( 10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
89  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
90  memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
91  }
92  QUICKVEC & operator=( const QuickVec & other ) //= delete; // non copyable
93  { TRACE( 10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
94  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
95  resize( other.size_ );
96  memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
97  return *this;
98  }
99 # if NOT_OLD_CXXSTD
100  QuickVec( QuickVec && other ) // construction-movable
101  : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
102  { TRACE( 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
103  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
104 # if USE_UNIQUE_PTR == 0
105  other.data_ = nullptr;
106 # endif
107  }
108  QUICKVEC & operator=( QuickVec && other ) // assign movable
109  { TRACE( 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
110  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
111  size_ = other.size_;
112  //delete [] data_;
113  free( data_ );
114  data_ = std::move(other.data_);
115  capacity_ = other.capacity_;
116 # if USE_UNIQUE_PTR == 0
117  other.data_ = nullptr;
118 # endif
119  return *this;
120  }
121 # endif
122 
123  TT_& operator[](int idx);
124  const TT_& operator[](int idx) const;
125  size_t size() const;
126  size_t capacity() const;
127  iterator begin();
128  const_iterator begin() const;
129  iterator end();
130  const_iterator end() const;
131  void reserve( size_t size );
132  void resize( size_t size );
133  void resize( size_t size, TT_ val );
134  iterator insert( const_iterator position, size_t nn, const TT_& val );
135  iterator insert( const_iterator position, const_iterator first
136  , const_iterator last);
137  iterator erase( const_iterator first, const_iterator last );
138  void swap( QuickVec& x );
139  void push_back( const value_type& val );
140 
141  QUICKVEC_VERSION
142 
143 private:
144  // Root needs the size_ member first. It must be of type int.
145  // Root then needs the [size_] comment after data_.
146  // Note: NO SPACE between "//" and "[size_]"
147  unsigned size_;
148 # if USE_UNIQUE_PTR == 0
149  TT_ * data_; //[size_]
150 # else
151  std::unique_ptr<TT_[]> data_;
152 # endif
153  unsigned capacity_;
154 };
155 
156 QUICKVEC_TEMPLATE
157 inline QUICKVEC::QuickVec( size_t sz )
158  //: size_(sz), data_(new TT_[sz]), capacity_(sz)
159  : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN,sz*sizeof(TT_))), capacity_(sz)
160 { TRACE( 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_) );
161 }
162 QUICKVEC_TEMPLATE
163 inline QUICKVEC::QuickVec( size_t sz, TT_ val )
164  //: size_(sz), data_(new TT_[sz]), capacity_(sz)
165  : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN,sz*sizeof(TT_))), capacity_(sz)
166 { TRACE( 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_) );
167  for (iterator ii=begin(); ii!=end(); ++ii) *ii=val;
168  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
169 }
170 
171 #if USE_UNIQUE_PTR == 0
172 QUICKVEC_TEMPLATE
173 inline QUICKVEC::~QuickVec()
174 { TRACE( 15, "QuickVec %p dtor start data_=%p size_=%d"
175  , (void*)this, (void*)PTR_(data_), size_ );
176  //delete [] data_;
177  free( data_ );
178  TRACE( 15, "QuickVec %p dtor return", (void*)this );
179 }
180 #endif
181 
182 QUICKVEC_TEMPLATE
183 inline TT_& QUICKVEC::operator[](int idx)
184 { assert(idx<(int)size_); return data_[idx];
185 }
186 
187 QUICKVEC_TEMPLATE
188 inline const TT_& QUICKVEC::operator[](int idx) const
189 { assert(idx < (int)size_);
190  return data_[idx];
191 }
192 
193 QUICKVEC_TEMPLATE
194 inline size_t QUICKVEC::size() const { return size_; }
195 QUICKVEC_TEMPLATE
196 inline size_t QUICKVEC::capacity() const { return capacity_; }
197 
198 QUICKVEC_TEMPLATE
199 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
200 QUICKVEC_TEMPLATE
201 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
202 QUICKVEC_TEMPLATE
203 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_)+size_); }
204 QUICKVEC_TEMPLATE
205 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_)+size_); }
206 
207 QUICKVEC_TEMPLATE
208 inline void QUICKVEC::reserve( size_t size )
209 { if (size > capacity_) // reallocation if true
210  {
211 # if USE_UNIQUE_PTR == 0
212  TT_ * old=data_;
213  //data_ = new TT_[size];
214  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_));
215  memcpy( data_, old, size_*sizeof(TT_) );
216  TRACE( 13, "QUICKVEC::reserve this=%p old=%p data_=%p"
217  , (void*)this, (void*)old, (void*)data_ );
218  //delete [] old;
219  free( old );
220 # else
221  std::unique_ptr<TT_[]> old=std::move(data_);
222  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
223  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_)));
224  memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
225 # endif
226  capacity_ = size;
227  // bye to old(unique_ptr)
228  }
229 }
230 
231 QUICKVEC_TEMPLATE
232 inline void QUICKVEC::resize( size_t size )
233 { if (size < size_) size_ = size; // decrease
234  else if (size <= capacity_) size_ = size;
235  else // increase/reallocate
236  {
237 # if USE_UNIQUE_PTR == 0
238  TT_ * old=data_;
239  //data_ = new TT_[size];
240  data_ = (TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_));
241  memcpy( data_, old, size_*sizeof(TT_) );
242  TRACE( 13, "QUICKVEC::resize this=%p old=%p data_=%p"
243  , (void*)this, (void*)old, (void*)data_ );
244  //delete [] old;
245  free( old );
246 # else
247  std::unique_ptr<TT_[]> old=std::move(data_);
248  //data_ = std::unique_ptr<TT_[]>(new TT_[size]);
249  data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_)));
250  memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
251 # endif
252  size_ = capacity_ = size;
253  // bye to old(unique_ptr)
254  }
255 }
256 QUICKVEC_TEMPLATE
257 inline void QUICKVEC::resize( size_type size, TT_ val )
258 { size_type old_size=size;
259  resize( size );
260  if (size > old_size)
261  for (iterator ii=begin()+old_size; ii!=end(); ++ii) *ii=val;
262 }
263 
264 QUICKVEC_TEMPLATE
265 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
266  , size_t nn
267  , const TT_& val)
268 { assert(position<=end()); // the current end
269  size_t offset=position-begin();
270  reserve( size_+nn ); // may reallocate and invalidate "position"
271 
272  iterator dst=end()+nn; // for shifting existing data after
273  iterator src=end(); // insertion point
274  size_t cnt=end()-(begin()+offset);
275  while (cnt--) *--dst = *--src;
276 
277  dst=begin()+offset;
278  size_+=nn;
279  while (nn--) *dst++ = val;
280  return begin()+offset;
281 }
282 QUICKVEC_TEMPLATE
283 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
284  , const_iterator first
285  , const_iterator last)
286 { assert(position<=end()); // the current end
287  size_t nn=(last-first);
288  size_t offset=position-begin();
289  reserve( size_+nn ); // may reallocate and invalidate "position"
290 
291  iterator dst=end()+nn; // for shifting existing data after
292  iterator src=end(); // insertion point
293  size_t cnt=end()-(begin()+offset);
294  while (cnt--) *--dst = *--src;
295 
296  dst=begin()+offset;
297  size_+=nn;
298  while (nn--) *dst++ = *first++;
299  return begin()+offset;
300 }
301 
302 QUICKVEC_TEMPLATE
303 inline QUICKVEC_TN::iterator QUICKVEC::erase( const_iterator first
304  ,const_iterator last )
305 { assert(last<=end()); // the current end
306  size_t nn=(last-first);
307  size_t offset=first-begin();
308 
309  iterator dst=begin()+offset; // for shifting existing data from last
310  iterator src=dst+nn; // to first
311  size_t cnt=end()-src;
312  while (cnt--) *dst++ = *src++;
313 
314  size_-=nn;
315  return begin()+offset;
316 }
317 
318 QUICKVEC_TEMPLATE
319 inline void QUICKVEC::swap( QuickVec& x )
320 { TRACE( 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
321  , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_) );
322  std::swap( data_, x.data_ );
323  std::swap( size_, x.size_ );
324  std::swap( capacity_, x.capacity_ );
325  TRACE( 12, "QUICKVEC::swap return data_=%p x.data_=%p"
326  , (void*)PTR_(data_), (void*)PTR_(x.data_) );
327 }
328 
329 QUICKVEC_TEMPLATE
330 inline void QUICKVEC::push_back( const value_type& val )
331 { if (size_ == capacity_)
332  { reserve( size_ + size_/10 + 1 );
333  }
334  *end() = val;
335  ++size_;
336 }
337 
338 #ifdef UNDEF_TRACE_AT_END
339 # undef TRACE
340 #endif
341 #endif /* QuickVec_hh */