00001
00002
00003
00004
00005
00006
00007 #ifndef QuickVec_hh
00008 #define QuickVec_hh
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cassert>
00018
00019
00020
00021 #include <vector>
00022
00023
00024 #ifndef TRACE
00025 # define TRACE( lvl, ... )
00026 # define UNDEF_TRACE_AT_END
00027 #endif
00028
00029 #define USE_UNIQUE_PTR 0
00030 #define QV_ALIGN 512
00031 static inline void *QV_MEMALIGN(size_t boundary, size_t size) { void *retadr; posix_memalign(&retadr, boundary, size); return retadr; }
00032
00033 #ifndef QUICKVEC_DO_TEMPLATE
00034 # define QUICKVEC_DO_TEMPLATE 1
00035 #endif
00036
00037 #undef NOT_OLD_CXXSTD
00038 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
00039 # define NOT_OLD_CXXSTD 1
00040 #endif
00041
00042 #if QUICKVEC_DO_TEMPLATE == 0
00043 # ifndef QUICKVEC_TT
00044 # define QUICKVEC_TT unsigned long long
00045 # endif
00046 # define TT_ QUICKVEC_TT
00047 # define QUICKVEC_TEMPLATE
00048 # define QUICKVEC QuickVec
00049 # define QUICKVEC_TN QuickVec
00050 # define QUICKVEC_VERSION
00051 #else
00052 # define QUICKVEC_TEMPLATE template <typename TT_>
00053 # define QUICKVEC QuickVec<TT_>
00054 # define QUICKVEC_TN typename QuickVec<TT_>
00055
00056 # define QUICKVEC_VERSION static short Class_Version() { return 5; } // proper version for templates
00057 #endif
00058
00059 namespace artdaq {
00060
00061 QUICKVEC_TEMPLATE
00062 struct QuickVec
00063 {
00064 typedef TT_* iterator;
00065 typedef const TT_* const_iterator;
00066 typedef TT_& reference;
00067 typedef const TT_& const_reference;
00068 typedef TT_ value_type;
00069 typedef ptrdiff_t difference_type;
00070 typedef size_t size_type;
00071
00072 QuickVec(size_t sz);
00073 QuickVec(size_t sz, TT_ val);
00074 # if USE_UNIQUE_PTR == 0
00075 virtual ~QuickVec() noexcept;
00076 # define PTR_(xx) xx
00077 # else
00078 # define PTR_(xx) xx.get()
00079 # endif
00080 QuickVec(std::vector<TT_> & other)
00081
00082 : size_(other.size()), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity())
00083 {
00084 memcpy(PTR_(data_), (void*)&other[0], size_ * sizeof(TT_));
00085 }
00086 void clear() { size_ = 0; }
00087
00088 QuickVec(const QuickVec & other)
00089
00090 : size_(other.size_), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity_)
00091 {
00092 TRACE(10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00093 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00094 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00095 }
00096 QUICKVEC & operator=(const QuickVec & other)
00097 {
00098 TRACE(10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00099 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00100 resize(other.size_);
00101 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00102 return *this;
00103 }
00104 # if NOT_OLD_CXXSTD
00105 QuickVec(QuickVec && other) noexcept
00106 : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
00107 {
00108 TRACE(10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00109 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00110 # if USE_UNIQUE_PTR == 0
00111 other.data_ = nullptr;
00112 # endif
00113 }
00114 QUICKVEC & operator=(QuickVec && other) noexcept
00115 {
00116 TRACE(10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00117 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00118 size_ = other.size_;
00119
00120 free(data_);
00121 data_ = std::move(other.data_);
00122 capacity_ = other.capacity_;
00123 # if USE_UNIQUE_PTR == 0
00124 other.data_ = nullptr;
00125 # endif
00126 return *this;
00127 }
00128 # endif
00129
00130 TT_& operator[](int idx);
00131 const TT_& operator[](int idx) const;
00132 size_t size() const;
00133 size_t capacity() const;
00134 iterator begin();
00135 const_iterator begin() const;
00136 iterator end();
00137 const_iterator end() const;
00138 void reserve(size_t size);
00139 void resize(size_t size);
00140 void resize(size_t size, TT_ val);
00141 iterator insert(const_iterator position, size_t nn, const TT_& val);
00142 iterator insert(const_iterator position, const_iterator first
00143 , const_iterator last);
00144 iterator erase(const_iterator first, const_iterator last);
00145 void swap(QuickVec& x) noexcept;
00146 void push_back(const value_type& val);
00147
00148 QUICKVEC_VERSION
00149
00150 private:
00151
00152
00153
00154 unsigned size_;
00155 # if USE_UNIQUE_PTR == 0
00156 TT_ * data_;
00157 # else
00158 std::unique_ptr<TT_[]> data_;
00159 # endif
00160 unsigned capacity_;
00161 };
00162
00163 QUICKVEC_TEMPLATE
00164 inline QUICKVEC::QuickVec(size_t sz)
00165
00166 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
00167 {
00168 TRACE(15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_));
00169 }
00170 QUICKVEC_TEMPLATE
00171 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00172
00173 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
00174 {
00175 TRACE(15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_));
00176 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00177
00178 }
00179
00180 #if USE_UNIQUE_PTR == 0
00181 QUICKVEC_TEMPLATE
00182 inline QUICKVEC::~QuickVec() noexcept
00183 {
00184 TRACE(15, "QuickVec %p dtor start data_=%p size_=%d"
00185 , (void*)this, (void*)PTR_(data_), size_);
00186
00187 free(data_);
00188 TRACE(15, "QuickVec %p dtor return", (void*)this);
00189 }
00190 #endif
00191
00192 QUICKVEC_TEMPLATE
00193 inline TT_& QUICKVEC::operator[](int idx)
00194 {
00195 assert(idx < (int)size_); return data_[idx];
00196 }
00197
00198 QUICKVEC_TEMPLATE
00199 inline const TT_& QUICKVEC::operator[](int idx) const
00200 {
00201 assert(idx < (int)size_);
00202 return data_[idx];
00203 }
00204
00205 QUICKVEC_TEMPLATE
00206 inline size_t QUICKVEC::size() const { return size_; }
00207 QUICKVEC_TEMPLATE
00208 inline size_t QUICKVEC::capacity() const { return capacity_; }
00209
00210 QUICKVEC_TEMPLATE
00211 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
00212 QUICKVEC_TEMPLATE
00213 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
00214 QUICKVEC_TEMPLATE
00215 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_) + size_); }
00216 QUICKVEC_TEMPLATE
00217 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_) + size_); }
00218
00219 QUICKVEC_TEMPLATE
00220 inline void QUICKVEC::reserve(size_t size)
00221 {
00222 if (size > capacity_)
00223 {
00224 # if USE_UNIQUE_PTR == 0
00225 TT_ * old = data_;
00226
00227 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00228 memcpy(data_, old, size_ * sizeof(TT_));
00229 TRACE(13, "QUICKVEC::reserve this=%p old=%p data_=%p"
00230 , (void*)this, (void*)old, (void*)data_);
00231
00232 free(old);
00233 # else
00234 std::unique_ptr<TT_[]> old = std::move(data_);
00235
00236 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00237 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00238 # endif
00239 capacity_ = size;
00240
00241 }
00242 }
00243
00244 QUICKVEC_TEMPLATE
00245 inline void QUICKVEC::resize(size_t size)
00246 {
00247 if (size < size_) size_ = size;
00248 else if (size <= capacity_) size_ = size;
00249 else
00250 {
00251 # if USE_UNIQUE_PTR == 0
00252 TT_ * old = data_;
00253
00254 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00255 memcpy(data_, old, size_ * sizeof(TT_));
00256 TRACE(13, "QUICKVEC::resize this=%p old=%p data_=%p"
00257 , (void*)this, (void*)old, (void*)data_);
00258
00259 free(old);
00260 # else
00261 std::unique_ptr<TT_[]> old = std::move(data_);
00262
00263 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00264 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00265 # endif
00266 size_ = capacity_ = size;
00267
00268 }
00269 }
00270 QUICKVEC_TEMPLATE
00271 inline void QUICKVEC::resize(size_type size, TT_ val)
00272 {
00273 size_type old_size = size;
00274 resize(size);
00275 if (size > old_size)
00276 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00277 }
00278
00279 QUICKVEC_TEMPLATE
00280 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00281 , size_t nn
00282 , const TT_& val)
00283 {
00284 assert(position <= end());
00285 size_t offset = position - begin();
00286 reserve(size_ + nn);
00287
00288 iterator dst = end() + nn;
00289 iterator src = end();
00290 size_t cnt = end() - (begin() + offset);
00291 while (cnt--) *--dst = *--src;
00292
00293 dst = begin() + offset;
00294 size_ += nn;
00295 while (nn--) *dst++ = val;
00296 return begin() + offset;
00297 }
00298 QUICKVEC_TEMPLATE
00299 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00300 , const_iterator first
00301 , const_iterator last)
00302 {
00303 assert(position <= end());
00304 size_t nn = (last - first);
00305 size_t offset = position - begin();
00306 reserve(size_ + nn);
00307
00308 iterator dst = end() + nn;
00309 iterator src = end();
00310 size_t cnt = end() - (begin() + offset);
00311 while (cnt--) *--dst = *--src;
00312
00313 dst = begin() + offset;
00314 size_ += nn;
00315 while (nn--) *dst++ = *first++;
00316 return begin() + offset;
00317 }
00318
00319 QUICKVEC_TEMPLATE
00320 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00321 , const_iterator last)
00322 {
00323 assert(last <= end());
00324 size_t nn = (last - first);
00325 size_t offset = first - begin();
00326
00327 iterator dst = begin() + offset;
00328 iterator src = dst + nn;
00329 size_t cnt = end() - src;
00330 while (cnt--) *dst++ = *src++;
00331
00332 size_ -= nn;
00333 return begin() + offset;
00334 }
00335
00336 QUICKVEC_TEMPLATE
00337 inline void QUICKVEC::swap(QuickVec& x) noexcept
00338 {
00339 TRACE(12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00340 , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_));
00341 std::swap(data_, x.data_);
00342 std::swap(size_, x.size_);
00343 std::swap(capacity_, x.capacity_);
00344 TRACE(12, "QUICKVEC::swap return data_=%p x.data_=%p"
00345 , (void*)PTR_(data_), (void*)PTR_(x.data_));
00346 }
00347
00348 QUICKVEC_TEMPLATE
00349 inline void QUICKVEC::push_back(const value_type& val)
00350 {
00351 if (size_ == capacity_)
00352 {
00353 reserve(size_ + size_ / 10 + 1);
00354 }
00355 *end() = val;
00356 ++size_;
00357 }
00358
00359 }
00360
00361 #ifdef UNDEF_TRACE_AT_END
00362 # undef TRACE
00363 #endif
00364 #endif