00001
00002
00003
00004
00005
00006
00007 #ifndef QuickVec_hh
00008 #define QuickVec_hh
00009
00010
00011
00012
00013
00014 #include <string.h>
00015
00016
00017 #include <cstddef>
00018
00019
00021 #include <cassert>
00022 #include <vector>
00025
00026 #ifndef TRACEN
00027 # define TRACEN( nam, lvl, ... )
00028 # define UNDEF_TRACE_AT_END
00029 #endif
00030
00031 #define QV_ALIGN 512
00032
00039 static inline void* QV_MEMALIGN(size_t boundary, size_t size)
00040 {
00041 void* retadr;
00042 posix_memalign(&retadr, boundary, size);
00043 return retadr;
00044 }
00045
00046 #ifndef QUICKVEC_DO_TEMPLATE
00047 # define QUICKVEC_DO_TEMPLATE 1
00048 #endif
00049
00050 #undef NOT_OLD_CXXSTD
00051 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
00052 # define NOT_OLD_CXXSTD 1
00053 #endif
00054
00055 #if QUICKVEC_DO_TEMPLATE == 0
00056 # ifndef QUICKVEC_TT
00057 # define QUICKVEC_TT unsigned long long
00058 # endif
00059 # define TT_ QUICKVEC_TT
00060 # define QUICKVEC_TEMPLATE
00061 # define QUICKVEC QuickVec
00062 # define QUICKVEC_TN QuickVec
00063 # define QUICKVEC_VERSION
00064 #else
00065 # define QUICKVEC_TEMPLATE template <typename TT_>
00066 # define QUICKVEC QuickVec<TT_>
00067 # define QUICKVEC_TN typename QuickVec<TT_>
00068 # define QUICKVEC_VERSION \
00069 \
00075 static short Class_Version() { return 5; } // proper version for templates
00076 #endif
00077
00078 namespace artdaq {
00079
00085 QUICKVEC_TEMPLATE
00086 struct QuickVec
00087 {
00088 typedef TT_* iterator;
00089 typedef const TT_* const_iterator;
00090 typedef TT_& reference;
00091 typedef const TT_& const_reference;
00092 typedef TT_ value_type;
00093 typedef ptrdiff_t difference_type;
00094 typedef size_t size_type;
00095
00100 QuickVec(size_t sz);
00101
00107 QuickVec(size_t sz, TT_ val);
00108
00112 virtual ~QuickVec() noexcept;
00113
00118 QuickVec(std::vector<TT_>& other)
00119 : size_(other.size())
00120 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00121 , capacity_(other.capacity())
00122 {
00123 TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d"
00124 , (void*)this, (void*)data_, (void*)&other[0], size_, other.size());
00125 memcpy( data_, (void*)&other[0], size_ * sizeof(TT_));
00126 }
00127
00131 void clear() { size_ = 0; }
00132
00133
00138 QuickVec(const QuickVec& other)
00139 : size_(other.size_)
00140 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00141 , capacity_(other.capacity_)
00142 {
00143 TRACEN("QuickVec",10, "QuickVec copy ctor b4 memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00144 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00145 memcpy( data_, other.data_, size_ * sizeof(TT_));
00146 }
00147
00153 QUICKVEC& operator=(const QuickVec& other)
00154 {
00155 TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00156 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00157 resize(other.size_);
00158 memcpy( data_, other.data_, size_ * sizeof(TT_));
00159 return *this;
00160 }
00161 # if NOT_OLD_CXXSTD
00162
00166 QuickVec(QuickVec&& other) noexcept
00167 : size_(other.size_)
00168 , data_(std::move(other.data_))
00169 , capacity_(other.capacity_)
00170 {
00171 TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00172 , (void*)this, (void*)data_, (void*)other.data_ );
00173 other.data_ = nullptr;
00174 }
00175
00181 QUICKVEC& operator=(QuickVec&& other) noexcept
00182 {
00183 TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00184 , (void*)this, (void*)data_, (void*)other.data_ );
00185 size_ = other.size_;
00186
00187 free(data_);
00188 data_ = std::move(other.data_);
00189 capacity_ = other.capacity_;
00190 other.data_ = nullptr;
00191 return *this;
00192 }
00193 # endif
00194
00200 TT_& operator[](int idx);
00201
00207 const TT_& operator[](int idx) const;
00208
00213 size_t size() const;
00214
00223 size_t capacity() const;
00224
00229 iterator begin();
00230
00235 const_iterator begin() const;
00236
00241 iterator end();
00242
00247 const_iterator end() const;
00248
00256 void reserve(size_t size);
00257
00266 void resize(size_t size);
00267
00278 void resizeWithCushion(size_t size, double growthFactor = 1.3);
00279
00285 void resize(size_t size, TT_ val);
00286
00298 iterator insert(const_iterator position, size_t nn, const TT_& val);
00299
00311 iterator insert(const_iterator position, const_iterator first
00312 , const_iterator last);
00313
00324 iterator erase(const_iterator first, const_iterator last);
00325
00330 void swap(QuickVec& other) noexcept;
00331
00336 void push_back(const value_type& val);
00337
00338 QUICKVEC_VERSION
00339
00340 private:
00341
00342
00343
00344 unsigned size_;
00345 TT_* data_;
00346 unsigned capacity_;
00347 };
00348
00349 QUICKVEC_TEMPLATE
00350 inline QUICKVEC::QuickVec(size_t sz)
00351 : size_(sz)
00352 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00353 , capacity_(sz)
00354 {
00355 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
00356 }
00357
00358 QUICKVEC_TEMPLATE
00359 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00360 : size_(sz)
00361 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00362 , capacity_(sz)
00363 {
00364 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
00365 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00366
00367 }
00368
00369 QUICKVEC_TEMPLATE
00370 inline QUICKVEC::~QuickVec() noexcept
00371 {
00372 TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
00373 , (void*)this, (void*)data_, size_);
00374 free(data_);
00375 TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
00376 }
00377
00378 QUICKVEC_TEMPLATE
00379 inline TT_& QUICKVEC::operator[](int idx)
00380 {
00381 assert(idx < (int)size_);
00382 return data_[idx];
00383 }
00384
00385 QUICKVEC_TEMPLATE
00386 inline const TT_& QUICKVEC::operator[](int idx) const
00387 {
00388 assert(idx < (int)size_);
00389 return data_[idx];
00390 }
00391
00392 QUICKVEC_TEMPLATE
00393 inline size_t QUICKVEC::size() const { return size_; }
00394
00395 QUICKVEC_TEMPLATE
00396 inline size_t QUICKVEC::capacity() const { return capacity_; }
00397
00398 QUICKVEC_TEMPLATE
00399 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
00400
00401 QUICKVEC_TEMPLATE
00402 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
00403
00404 QUICKVEC_TEMPLATE
00405 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
00406
00407 QUICKVEC_TEMPLATE
00408 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
00409
00410 QUICKVEC_TEMPLATE
00411 inline void QUICKVEC::reserve(size_t size)
00412 {
00413 if (size > capacity_)
00414 {
00415 TT_* old = data_;
00416
00417 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00418 memcpy(data_, old, size_ * sizeof(TT_));
00419 TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p capacity=%d"
00420 , (void*)this, (void*)old, (void*)data_, (int)size);
00421 free(old);
00422 capacity_ = size;
00423 }
00424 }
00425
00426 QUICKVEC_TEMPLATE
00427 inline void QUICKVEC::resize(size_t size)
00428 {
00429 if (size < size_) size_ = size;
00430 else if (size <= capacity_) size_ = size;
00431 else
00432 {
00433 TT_* old = data_;
00434 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00435 memcpy(data_, old, size_ * sizeof(TT_));
00436 TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p size=%d"
00437 , (void*)this, (void*)old, (void*)data_, (int)size);
00438 free(old);
00439 size_ = capacity_ = size;
00440 }
00441 }
00442
00443 QUICKVEC_TEMPLATE
00444 inline void QUICKVEC::resizeWithCushion(size_t size, double growthFactor)
00445 {
00446 if (size > capacity_)
00447 {
00448 size_t new_size = std::round(capacity_ * growthFactor);
00449 if (new_size < size) {new_size = size;}
00450 if (new_size < 512) {new_size = 512;}
00451 else if (new_size < 2048) {new_size = 2048;}
00452 else if (new_size < 4096) {new_size = 4096;}
00453 else if (new_size < 8192) {new_size = 8192;}
00454 reserve(new_size);
00455 }
00456 resize(size);
00457 }
00458
00459 QUICKVEC_TEMPLATE
00460 inline void QUICKVEC::resize(size_type size, TT_ val)
00461 {
00462 size_type old_size = size;
00463 resize(size);
00464 if (size > old_size) {
00465 TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
00466 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00467 }
00468 }
00469
00470 QUICKVEC_TEMPLATE
00471 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00472 , size_t nn
00473 , const TT_& val)
00474 {
00475 assert(position <= end());
00476 size_t offset = position - begin();
00477 reserve(size_ + nn);
00478
00479 iterator dst = end() + nn;
00480 iterator src = end();
00481 size_t cnt = end() - (begin() + offset);
00482 while (cnt--) *--dst = *--src;
00483
00484 dst = begin() + offset;
00485 size_ += nn;
00486 while (nn--) *dst++ = val;
00487 return begin() + offset;
00488 }
00489
00490 QUICKVEC_TEMPLATE
00491 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00492 , const_iterator first
00493 , const_iterator last)
00494 {
00495 assert(position <= end());
00496 size_t nn = (last - first);
00497 size_t offset = position - begin();
00498 reserve(size_ + nn);
00499
00500 iterator dst = end() + nn;
00501 iterator src = end();
00502 size_t cnt = end() - (begin() + offset);
00503 while (cnt--) *--dst = *--src;
00504
00505 dst = begin() + offset;
00506 size_ += nn;
00507 while (nn--) *dst++ = *first++;
00508 return begin() + offset;
00509 }
00510
00511 QUICKVEC_TEMPLATE
00512 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00513 , const_iterator last)
00514 {
00515 assert(last <= end());
00516 size_t nn = (last - first);
00517 size_t offset = first - begin();
00518
00519 iterator dst = begin() + offset;
00520 iterator src = dst + nn;
00521 size_t cnt = end() - src;
00522 while (cnt--) *dst++ = *src++;
00523
00524 size_ -= nn;
00525 return begin() + offset;
00526 }
00527
00528 QUICKVEC_TEMPLATE
00529 inline void QUICKVEC::swap(QuickVec& x) noexcept
00530 {
00531 TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00532 , (void*)this, (void*)data_, (void*)x.data_ );
00533 std::swap(data_, x.data_);
00534 std::swap(size_, x.size_);
00535 std::swap(capacity_, x.capacity_);
00536 TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
00537 , (void*)data_, (void*)x.data_ );
00538 }
00539
00540 QUICKVEC_TEMPLATE
00541 inline void QUICKVEC::push_back(const value_type& val)
00542 {
00543 if (size_ == capacity_)
00544 {
00545 reserve(size_ + size_ / 10 + 1);
00546 }
00547 *end() = val;
00548 ++size_;
00549 }
00550
00551 }
00552
00553 #ifdef UNDEF_TRACE_AT_END
00554 # undef TRACEN
00555 # undef UNDEF_TRACE_AT_END
00556 #endif
00557 #endif