$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_04_20a
$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 <vector> 00025 //#include "trace.h" // TRACE 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 //: 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" 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) //= delete; // non copyable 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 // construction-movable 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 // assign movable 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 //delete [] data_; 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 // Root needs the size_ member first. It must be of type int. 00342 // Root then needs the [size_] comment after data_. 00343 // Note: NO SPACE between "//" and "[size_]" 00344 unsigned size_; 00345 TT_* data_; //[size_] 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 //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) ); 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_) // reallocation if true 00414 { 00415 TT_* old = data_; 00416 //data_ = new TT_[size]; 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; // decrease 00430 else if (size <= capacity_) size_ = size; 00431 else // increase/reallocate 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()); // the current end 00476 size_t offset = position - begin(); 00477 reserve(size_ + nn); // may reallocate and invalidate "position" 00478 00479 iterator dst = end() + nn; // for shifting existing data after 00480 iterator src = end(); // insertion point 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()); // 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 00513 , const_iterator last) 00514 { 00515 assert(last <= end()); // the current end 00516 size_t nn = (last - first); 00517 size_t offset = first - begin(); 00518 00519 iterator dst = begin() + offset; // for shifting existing data from last 00520 iterator src = dst + nn; // to first 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 } // namespace 00552 00553 #ifdef UNDEF_TRACE_AT_END 00554 # undef TRACEN 00555 # undef UNDEF_TRACE_AT_END 00556 #endif 00557 #endif /* QuickVec_hh */