$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_05_08a
$projectbrief
|
$projectbrief
|
$searchbox |
00001 // This file (QuickVec.hh) was created by Ron Rechenmacher <ron@fnal.gov> on 00002 // Sep 3, 2014. "TERMS AND CONDITIONS" governing this file are in the README 00003 // or COPYING file. If you do not have such a file, one can be obtained by 00004 // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000. 00005 // $RCSfile: QuickVec.hh,v $ 00006 // rev="$Revision: 1.8 $$Date: 2014/09/05 19:21:11 $"; 00007 #ifndef QuickVec_hh 00008 #define QuickVec_hh 00009 00010 //extern "C" { 00011 //#include <stdint.h> 00012 //} 00013 00014 #include <string.h> // memcpy 00015 //#include <strings.h> // bzero 00016 //#include <stdlib.h> // posix_memalign 00017 #include <cstddef> // ptrdiff_t 00018 //#include <utility> // std::swap 00019 //#include <memory> // unique_ptr 00021 #include <cassert> 00022 #include <cmath> 00023 #include <vector> 00026 //#include "trace.h" // TRACE 00027 #ifndef TRACEN 00028 #define TRACEN(nam, lvl, ...) 00029 #define UNDEF_TRACE_AT_END 00030 #endif 00031 00032 #define QV_ALIGN 512 00033 00040 static inline void* QV_MEMALIGN(size_t boundary, size_t size) 00041 { 00042 void* retadr; 00043 posix_memalign(&retadr, boundary, size); 00044 return retadr; 00045 } 00046 00047 #ifndef QUICKVEC_DO_TEMPLATE 00048 #define QUICKVEC_DO_TEMPLATE 1 00049 #endif 00050 00051 #undef NOT_OLD_CXXSTD 00052 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__) 00053 #define NOT_OLD_CXXSTD 1 00054 #endif 00055 00056 #if QUICKVEC_DO_TEMPLATE == 0 00057 #ifndef QUICKVEC_TT 00058 #define QUICKVEC_TT unsigned long long 00059 #endif 00060 #define TT_ QUICKVEC_TT 00061 #define QUICKVEC_TEMPLATE 00062 #define QUICKVEC QuickVec 00063 #define QUICKVEC_TN QuickVec 00064 #define QUICKVEC_VERSION 00065 #else 00066 #define QUICKVEC_TEMPLATE template<typename TT_> 00067 #define QUICKVEC QuickVec<TT_> 00068 #define QUICKVEC_TN typename QuickVec<TT_> 00069 #define QUICKVEC_VERSION \ 00070 \ 00076 static short Class_Version() { return 5; } // proper version for templates 00077 #endif 00078 00079 namespace artdaq { 00080 00086 QUICKVEC_TEMPLATE 00087 struct QuickVec 00088 { 00089 typedef TT_* iterator; 00090 typedef const TT_* const_iterator; 00091 typedef TT_& reference; 00092 typedef const TT_& const_reference; 00093 typedef TT_ value_type; 00094 typedef ptrdiff_t difference_type; 00095 typedef size_t size_type; 00096 00101 QuickVec(size_t sz); 00102 00108 QuickVec(size_t sz, TT_ val); 00109 00113 virtual ~QuickVec() noexcept; 00114 00119 QuickVec(std::vector<TT_>& other) 00120 : size_(other.size()) 00121 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))) 00122 , capacity_(other.capacity()) 00123 { 00124 TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d", (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 //: size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_) 00138 QuickVec(const QuickVec& other) //= delete; // non construction-copyable 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", (void*)this, (void*)data_, (void*)other.data_, size_, other.size_); 00144 memcpy(data_, other.data_, size_ * sizeof(TT_)); 00145 } 00146 00152 QUICKVEC& operator=(const QuickVec& other) //= delete; // non copyable 00153 { 00154 TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d", (void*)this, (void*)data_, (void*)other.data_, size_, other.size_); 00155 resize(other.size_); 00156 memcpy(data_, other.data_, size_ * sizeof(TT_)); 00157 return *this; 00158 } 00159 #if NOT_OLD_CXXSTD 00160 00164 QuickVec(QuickVec&& other) noexcept // construction-movable 00165 : size_(other.size_) 00166 , data_(std::move(other.data_)) 00167 , capacity_(other.capacity_) 00168 { 00169 TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p", (void*)this, (void*)data_, (void*)other.data_); 00170 other.data_ = nullptr; 00171 } 00172 00178 QUICKVEC& operator=(QuickVec&& other) noexcept // assign movable 00179 { 00180 TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p", (void*)this, (void*)data_, (void*)other.data_); 00181 size_ = other.size_; 00182 //delete [] data_; 00183 free(data_); 00184 data_ = std::move(other.data_); 00185 capacity_ = other.capacity_; 00186 other.data_ = nullptr; 00187 return *this; 00188 } 00189 #endif 00190 00196 TT_& operator[](int idx); 00197 00203 const TT_& operator[](int idx) const; 00204 00209 size_t size() const; 00210 00219 size_t capacity() const; 00220 00225 iterator begin(); 00226 00231 const_iterator begin() const; 00232 00237 iterator end(); 00238 00243 const_iterator end() const; 00244 00252 void reserve(size_t size); 00253 00262 void resize(size_t size); 00263 00274 void resizeWithCushion(size_t size, double growthFactor = 1.3); 00275 00281 void resize(size_t size, TT_ val); 00282 00294 iterator insert(const_iterator position, size_t nn, const TT_& val); 00295 00307 iterator insert(const_iterator position, const_iterator first, const_iterator last); 00308 00319 iterator erase(const_iterator first, const_iterator last); 00320 00325 void swap(QuickVec& other) noexcept; 00326 00331 void push_back(const value_type& val); 00332 00333 QUICKVEC_VERSION 00334 00335 private: 00336 // Root needs the size_ member first. It must be of type int. 00337 // Root then needs the [size_] comment after data_. 00338 // Note: NO SPACE between "//" and "[size_]" 00339 unsigned size_; 00340 TT_* data_; //[size_] 00341 unsigned capacity_; 00342 }; 00343 00344 QUICKVEC_TEMPLATE 00345 inline QUICKVEC::QuickVec(size_t sz) 00346 : size_(sz) 00347 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))) 00348 , capacity_(sz) 00349 { 00350 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_); 00351 } 00352 00353 QUICKVEC_TEMPLATE 00354 inline QUICKVEC::QuickVec(size_t sz, TT_ val) 00355 : size_(sz) 00356 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))) 00357 , capacity_(sz) 00358 { 00359 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_); 00360 for (iterator ii = begin(); ii != end(); ++ii) *ii = val; 00361 //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) ); 00362 } 00363 00364 QUICKVEC_TEMPLATE 00365 inline QUICKVEC::~QuickVec() noexcept 00366 { 00367 TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d", (void*)this, (void*)data_, size_); 00368 free(data_); 00369 TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this); 00370 } 00371 00372 QUICKVEC_TEMPLATE 00373 inline TT_& QUICKVEC::operator[](int idx) 00374 { 00375 assert(idx < (int)size_); 00376 return data_[idx]; 00377 } 00378 00379 QUICKVEC_TEMPLATE 00380 inline const TT_& QUICKVEC::operator[](int idx) const 00381 { 00382 assert(idx < (int)size_); 00383 return data_[idx]; 00384 } 00385 00386 QUICKVEC_TEMPLATE 00387 inline size_t QUICKVEC::size() const { return size_; } 00388 00389 QUICKVEC_TEMPLATE 00390 inline size_t QUICKVEC::capacity() const { return capacity_; } 00391 00392 QUICKVEC_TEMPLATE 00393 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); } 00394 00395 QUICKVEC_TEMPLATE 00396 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); } 00397 00398 QUICKVEC_TEMPLATE 00399 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_ + size_); } 00400 00401 QUICKVEC_TEMPLATE 00402 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_ + size_); } 00403 00404 QUICKVEC_TEMPLATE 00405 inline void QUICKVEC::reserve(size_t size) 00406 { 00407 if (size > capacity_) // reallocation if true 00408 { 00409 TT_* old = data_; 00410 //data_ = new TT_[size]; 00411 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)); 00412 memcpy(data_, old, size_ * sizeof(TT_)); 00413 TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p capacity=%d", (void*)this, (void*)old, (void*)data_, (int)size); 00414 free(old); 00415 capacity_ = size; 00416 } 00417 } 00418 00419 QUICKVEC_TEMPLATE 00420 inline void QUICKVEC::resize(size_t size) 00421 { 00422 if (size < size_) 00423 size_ = size; // decrease 00424 else if (size <= capacity_) 00425 size_ = size; 00426 else // increase/reallocate 00427 { 00428 TT_* old = data_; 00429 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)); 00430 memcpy(data_, old, size_ * sizeof(TT_)); 00431 TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p size=%d", (void*)this, (void*)old, (void*)data_, (int)size); 00432 free(old); 00433 size_ = capacity_ = size; 00434 } 00435 } 00436 00437 QUICKVEC_TEMPLATE 00438 inline void QUICKVEC::resizeWithCushion(size_t size, double growthFactor) 00439 { 00440 if (size > capacity_) 00441 { 00442 size_t new_size = std::round(capacity_ * growthFactor); 00443 if (new_size < size) { new_size = size; } 00444 if (new_size < 512) { new_size = 512; } 00445 else if (new_size < 2048) 00446 { 00447 new_size = 2048; 00448 } 00449 else if (new_size < 4096) 00450 { 00451 new_size = 4096; 00452 } 00453 else if (new_size < 8192) 00454 { 00455 new_size = 8192; 00456 } 00457 reserve(new_size); 00458 } 00459 resize(size); 00460 } 00461 00462 QUICKVEC_TEMPLATE 00463 inline void QUICKVEC::resize(size_type size, TT_ val) 00464 { 00465 size_type old_size = size; 00466 resize(size); 00467 if (size > old_size) 00468 { 00469 TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size - old_size); 00470 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val; 00471 } 00472 } 00473 00474 QUICKVEC_TEMPLATE 00475 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position, size_t nn, const TT_& val) 00476 { 00477 assert(position <= end()); // the current end 00478 size_t offset = position - begin(); 00479 reserve(size_ + nn); // may reallocate and invalidate "position" 00480 00481 iterator dst = end() + nn; // for shifting existing data after 00482 iterator src = end(); // insertion point 00483 size_t cnt = end() - (begin() + offset); 00484 while (cnt--) *--dst = *--src; 00485 00486 dst = begin() + offset; 00487 size_ += nn; 00488 while (nn--) *dst++ = val; 00489 return begin() + offset; 00490 } 00491 00492 QUICKVEC_TEMPLATE 00493 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position, const_iterator first, const_iterator last) 00494 { 00495 assert(position <= end()); // the current end 00496 size_t nn = (last - first); 00497 size_t offset = position - begin(); 00498 reserve(size_ + nn); // may reallocate and invalidate "position" 00499 00500 iterator dst = end() + nn; // for shifting existing data after 00501 iterator src = end(); // insertion point 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, const_iterator last) 00513 { 00514 assert(last <= end()); // the current end 00515 size_t nn = (last - first); 00516 size_t offset = first - begin(); 00517 00518 iterator dst = begin() + offset; // for shifting existing data from last 00519 iterator src = dst + nn; // to first 00520 size_t cnt = end() - src; 00521 while (cnt--) *dst++ = *src++; 00522 00523 size_ -= nn; 00524 return begin() + offset; 00525 } 00526 00527 QUICKVEC_TEMPLATE 00528 inline void QUICKVEC::swap(QuickVec& x) noexcept 00529 { 00530 TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p", (void*)this, (void*)data_, (void*)x.data_); 00531 std::swap(data_, x.data_); 00532 std::swap(size_, x.size_); 00533 std::swap(capacity_, x.capacity_); 00534 TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p", (void*)data_, (void*)x.data_); 00535 } 00536 00537 QUICKVEC_TEMPLATE 00538 inline void QUICKVEC::push_back(const value_type& val) 00539 { 00540 if (size_ == capacity_) 00541 { 00542 reserve(size_ + size_ / 10 + 1); 00543 } 00544 *end() = val; 00545 ++size_; 00546 } 00547 00548 } // namespace artdaq 00549 00550 #ifdef UNDEF_TRACE_AT_END 00551 #undef TRACEN 00552 #undef UNDEF_TRACE_AT_END 00553 #endif 00554 #endif /* QuickVec_hh */