00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _REFCOUNTEDPTR_H_
00012 #define _REFCOUNTEDPTR_H_
00013
00014 #include <cstdlib>
00015 #include <string>
00016 #include <typeinfo>
00017 #include "MayDay.H"
00018 #include "Arena.H"
00019 #include "CH_assert.H"
00020 #ifdef DEBUGRCP
00021 #include "parstream.H"
00022 #endif
00023 #include "BaseNamespaceHeader.H"
00024
00025 #ifdef CH_USE_MEMORY_TRACKING
00026 extern unsigned long long int ch_memcount;
00027 #endif
00028
00029 #ifdef DEBUGRCP
00030 #define RCPDBG(x) x
00031 #else
00032 #define RCPDBG(x) (void)0;
00033 #endif
00034
00035
00036
00037
00038
00039
00040
00041
00042 template <typename T>
00043 struct RCPTypeTr
00044 {
00045 typedef const T InvertConstType;
00046 };
00047
00048
00049 template <typename T>
00050 struct RCPTypeTr<const T>
00051 {
00052 typedef T InvertConstType;
00053 };
00054
00055
00056
00057
00058
00059
00060 template <typename T, typename S>
00061 struct RCPPairTr
00062 {
00063 enum
00064 {
00065 IsSame = 0
00066 };
00067 };
00068
00069
00070 template <typename T>
00071 struct RCPPairTr<T, T>
00072 {
00073 enum
00074 {
00075 IsSame = 1
00076 };
00077 typedef T SamePolicyType;
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087 struct RCPPointerPolicy
00088 {
00089 template <typename T>
00090 static void destroy(T* a_pointer)
00091 {
00092 delete a_pointer;
00093 }
00094 };
00095
00096
00097 struct RCPArrayPolicy
00098 {
00099 template <typename T>
00100 static void destroy(T* a_array)
00101 {
00102 delete[] a_array;
00103 }
00104 };
00105
00106
00107 struct RCPFreePolicy
00108 {
00109 template <typename T>
00110 static void destroy(T* a_mem)
00111 {
00112 free((void*)a_mem);
00113 }
00114 };
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 template <typename T,
00172 typename OP = RCPPointerPolicy>
00173 class RefCountedPtr
00174 {
00175 public:
00176
00177 typedef T value_type;
00178 typedef T* pointer;
00179 typedef T& reference;
00180 typedef RefCountedPtr<T, OP> Self;
00181
00182
00183 explicit RefCountedPtr(pointer const ptr = 0);
00184
00185
00186 RefCountedPtr(const Self& other);
00187
00188
00189
00190
00191
00192 RefCountedPtr(
00193 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP>& other);
00194
00195
00196
00197
00198
00199 template <typename S>
00200 RefCountedPtr(const RefCountedPtr<S, OP>& other);
00201
00202
00203
00204
00205
00206
00207
00208 template <typename OP2>
00209 RefCountedPtr(const RefCountedPtr<T, OP2>& other)
00210 {
00211
00212
00213
00214 MayDay::Error("Invalid runtime code");
00215 }
00216 template <typename OP2>
00217 RefCountedPtr(
00218 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP2>& other)
00219 {
00220
00221
00222
00223 MayDay::Error("Invalid runtime code");
00224 }
00225
00226
00227 ~RefCountedPtr();
00228
00229
00230
00231
00232
00233 Self& operator=(const Self& rhs);
00234
00235
00236 Self& operator=(
00237 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP>& rhs);
00238
00239
00240
00241
00242
00243 template <typename S>
00244 Self& operator=(const RefCountedPtr<S, OP>& rhs);
00245
00246
00247
00248
00249
00250 template <typename OP2>
00251 Self& operator=(const RefCountedPtr<T, OP2>& rhs)
00252 {
00253
00254
00255
00256 MayDay::Error("Invalid runtime code");
00257 }
00258 template <typename OP2>
00259 Self& operator=(
00260 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP2>& rhs)
00261 {
00262
00263
00264
00265 MayDay::Error("Invalid runtime code");
00266 }
00267
00268
00269 pointer operator ->() const;
00270
00271
00272
00273
00274
00275
00276
00277 pointer const& getRefToThePointer() const;
00278
00279
00280 reference operator *() const;
00281
00282
00283 reference operator [](const int a_idx) const;
00284
00285
00286
00287
00288 operator T* () const;
00289
00290 bool isNull() const;
00291
00292
00293 bool isNonUnique() const;
00294
00295 int refCount() const;
00296
00297 void swap(Self& b);
00298
00299
00300
00301
00302
00303
00304 void neverDelete();
00305
00306 template<typename T2, typename OP2>
00307 friend class RefCountedPtr;
00308
00309 static const std::string& name()
00310 {
00311 return name_;
00312 }
00313
00314
00315
00316
00317 void incrementMem();
00318 void freeMem();
00319
00320
00321 inline RefCountedPtr(RefCountedPtr<T,OP>&& a_in) noexcept
00322 :ptr_(a_in.ptr_), refCount_(a_in.refCount_)
00323 {a_in.ptr_=0; a_in.refCount_=0; }
00324
00325 inline RefCountedPtr<T,OP>& operator=(RefCountedPtr<T,OP>&& a_in) noexcept
00326 { std::swap(ptr_, a_in.ptr_); std::swap(refCount_,a_in.refCount_);
00327 return *this;}
00328
00329 protected:
00330 void refUp();
00331 void refDown();
00332 pointer ptr_;
00333 int* refCount_;
00334 static std::string name_;
00335 static BArena s_Arena;
00336 static int size_;
00337 private:
00338
00339 };
00340
00341 template<typename T, typename OP>
00342 std::string RefCountedPtr<T, OP>::name_(
00343 std::string("RefCountedPtr ")+std::string(typeid(T).name()));
00344
00345
00346
00347 template<typename T, typename OP>
00348 BArena RefCountedPtr<T, OP>::s_Arena(typeid(T).name());
00349
00350 template<typename T, typename OP>
00351 int RefCountedPtr<T, OP>::size_ = sizeof(T)+2*sizeof(int);
00352
00353 template <typename T, typename OP>
00354 inline void
00355 RefCountedPtr<T, OP>::incrementMem()
00356 {
00357 #ifdef CH_USE_MEMORY_TRACKING
00358 #pragma omp critical(s_Arena)
00359 {
00360 ch_memcount+=size_;
00361 s_Arena.bytes += size_;
00362 }
00363 refCount_[1] = size_;
00364 if (s_Arena.bytes > s_Arena.peak)
00365 {
00366 s_Arena.peak = s_Arena.bytes;
00367 }
00368 #endif
00369 }
00370
00371 template <typename T, typename OP>
00372 inline
00373 void RefCountedPtr<T, OP>::freeMem()
00374 {
00375 #ifdef CH_USE_MEMORY_TRACKING
00376 #pragma omp critical(s_Arena)
00377 {
00378 ch_memcount-=refCount_[1];
00379 s_Arena.bytes -= refCount_[1];
00380 }
00381 #endif
00382 RCPDBG(pout() << "====> Destroying " << ptr_ << std::endl;)
00383 OP::destroy(ptr_);
00384 ptr_ = 0;
00385 delete [] refCount_;
00386 refCount_ = 0;
00387 }
00388
00389 template <typename T, typename OP>
00390 inline
00391 RefCountedPtr<T, OP>::RefCountedPtr(pointer const ptr)
00392 : ptr_(ptr),
00393 refCount_(0)
00394 {
00395 RCPDBG(pout() << "POD pointer constructor\n";)
00396 if (ptr_)
00397 {
00398 refCount_ = new int[2];
00399 if (refCount_ == 0)
00400 MayDay::Error("RefCountedPtr::RefCountedPtr(T* ptr) out of memory");
00401 *refCount_ = 1;
00402 incrementMem();
00403 RCPDBG(pout() << "====> Creating " << ptr << std::endl;)
00404 }
00405 }
00406
00407 template<typename T, typename OP>
00408 inline
00409 void RefCountedPtr<T, OP>::refUp()
00410 {
00411 RCPDBG(pout() << "refUp " << ptr_ << std::endl;);
00412 if(refCount_ != 0)
00413 {
00414 #pragma omp atomic
00415 ++(*refCount_);
00416 }
00417 }
00418
00419 template<typename T, typename OP>
00420 inline
00421 void RefCountedPtr<T, OP>::refDown()
00422 {
00423 RCPDBG(pout() << "refDown " << ptr_ << std::endl;);
00424 if(refCount_ != 0)
00425 {
00426 int c;
00427 #pragma omp atomic capture
00428 c = --(*refCount_);
00429
00430
00431 if(c==0) freeMem();
00432 }
00433 }
00434 template <typename T, typename OP>
00435 inline
00436 RefCountedPtr<T, OP>::RefCountedPtr(const Self& other)
00437 : ptr_(other.ptr_),
00438 refCount_(other.refCount_)
00439 {
00440 RCPDBG(pout() << "standard copy " << ptr_ << std::endl;);
00441 refUp();
00442 }
00443
00444 template <typename T, typename OP>
00445 inline
00446 RefCountedPtr<T, OP>::RefCountedPtr(
00447 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP>& other)
00448 : ptr_(other.ptr_),
00449 refCount_(other.refCount_)
00450 {
00451 RCPDBG(pout() << "const conversion copy " << ptr_ << std::endl;);
00452 refUp();
00453 }
00454
00455 template <typename T, typename OP>
00456 template <typename S>
00457 inline
00458 RefCountedPtr<T, OP>::RefCountedPtr(const RefCountedPtr<S, OP>& other)
00459 : ptr_(dynamic_cast<T*>(other.ptr_)),
00460 refCount_(other.refCount_)
00461 {
00462 RCPDBG(pout() << "related conversion copy " << ptr_ << std::endl;)
00463
00464
00465 if (other.ptr_ != NULL)
00466 {
00467 CH_assert(ptr_ != NULL);
00468 }
00469 refUp();
00470 }
00471
00472 template <typename T, typename OP>
00473 inline
00474 RefCountedPtr<T, OP>::~RefCountedPtr()
00475 {
00476 refDown();
00477 }
00478
00479 template <typename T, typename OP>
00480 inline typename RefCountedPtr<T, OP>::Self&
00481 RefCountedPtr<T, OP>::operator =(const Self& rhs)
00482 {
00483 RCPDBG(pout() << "standard assign " << rhs.ptr_ << std::endl;)
00484
00485
00486
00487
00488 #pragma omp critical(RCPAssign)
00489 {
00490 if (ptr_ != rhs.ptr_)
00491 {
00492 refDown();
00493
00494 ptr_ = rhs.ptr_;
00495 refCount_ = rhs.refCount_;
00496 refUp();
00497
00498 }
00499 }
00500 return *this;
00501 }
00502
00503 template <typename T, typename OP>
00504 inline typename RefCountedPtr<T, OP>::Self&
00505 RefCountedPtr<T, OP>::operator =(
00506 const RefCountedPtr<typename RCPTypeTr<T>::InvertConstType, OP>& rhs)
00507 {
00508 RCPDBG(pout() << "const conversion assign " << rhs.ptr_ << std::endl;)
00509 #pragma omp critical(RCPAssign)
00510 {
00511 if (ptr_ != rhs.ptr_)
00512 {
00513
00514 if (refCount_ != 0 && --(*refCount_) == 0)
00515 {
00516 freeMem();
00517 }
00518 ptr_ = rhs.ptr_;
00519 refCount_ = rhs.refCount_;
00520
00521 if (refCount_ != 0)
00522 ++(*refCount_);
00523 }
00524 }
00525 return *this;
00526 }
00527
00528 template <typename T, typename OP>
00529 template <typename S>
00530 inline typename RefCountedPtr<T, OP>::Self&
00531 RefCountedPtr<T, OP>::operator =(const RefCountedPtr<S, OP>& rhs)
00532 {
00533 RCPDBG(pout() << "related conversion assign " << rhs.ptr_ << std::endl;)
00534 #pragma omp critical(RCPAssign)
00535 {
00536 if (ptr_ != rhs.ptr_)
00537 {
00538
00539 if (refCount_ != 0 && --(*refCount_) == 0)
00540 {
00541 freeMem();
00542 }
00543 ptr_ = dynamic_cast<T*>(rhs.ptr_);
00544
00545
00546 if (rhs.ptr_ != NULL){ CH_assert(ptr_ != NULL); }
00547 refCount_ = rhs.refCount_;
00548
00549 if (refCount_ != 0)
00550 ++(*refCount_);
00551 }
00552 }
00553 return *this;
00554 }
00555
00556 template <typename T, typename OP>
00557 inline typename RefCountedPtr<T, OP>::pointer
00558 RefCountedPtr<T, OP>::operator ->() const
00559 {
00560 if (ptr_ == 0)
00561 MayDay::Error("RefCountedPtr<T>::operator ->() on null pointer");
00562 return ptr_;
00563 }
00564
00565 template <typename T, typename OP>
00566 inline typename RefCountedPtr<T, OP>::pointer const&
00567 RefCountedPtr<T, OP>::getRefToThePointer() const
00568 {
00569 return ptr_;
00570 }
00571
00572 template <typename T, typename OP>
00573 inline typename RefCountedPtr<T, OP>::reference
00574 RefCountedPtr<T, OP>::operator *() const
00575 {
00576 if (ptr_ == 0)
00577 MayDay::Error("RefCountedPtr<T>::operator *() on null pointer");
00578 return *ptr_;
00579 }
00580
00581 template <typename T, typename OP>
00582 inline typename RefCountedPtr<T, OP>::reference
00583 RefCountedPtr<T, OP>::operator [](const int a_idx) const
00584 {
00585 CH_assert(ptr_);
00586 return ptr_[a_idx];
00587 }
00588
00589 template <class T, typename OP>
00590 inline
00591 RefCountedPtr<T, OP>::operator T* () const
00592 {
00593 RCPDBG(pout() << "auto conversion " << ptr_ << std::endl;)
00594 return ptr_;
00595 }
00596
00597 template <typename T, typename OP>
00598 inline bool
00599 RefCountedPtr<T, OP>::isNull() const
00600 {
00601 return (ptr_ == 0);
00602 }
00603
00604 template <typename T, typename OP>
00605 inline bool
00606 RefCountedPtr<T, OP>::isNonUnique() const
00607 {
00608 return refCount_ == 0 ? false : *refCount_ != 1;
00609 }
00610
00611 template <typename T, typename OP>
00612 inline int
00613 RefCountedPtr<T, OP>::refCount() const
00614 {
00615 return refCount_ == 0 ? 0 : *refCount_;
00616 }
00617
00618 template <typename T, typename OP>
00619 inline void
00620 RefCountedPtr<T, OP>::swap(Self& b)
00621 {
00622 #ifdef _OPENMP
00623 #pragma omp critical
00624 #endif
00625 {
00626
00627 pointer s = ptr_;
00628 ptr_ = b.ptr_;
00629 b.ptr_ = s;
00630
00631 int* r = refCount_;
00632 refCount_ = b.refCount_;
00633 b.refCount_ = r;
00634 }
00635 }
00636
00637 template <typename T, typename OP>
00638 inline void
00639 RefCountedPtr<T, OP>::neverDelete()
00640 {
00641 ++ *refCount_;
00642 }
00643
00644 #include "BaseNamespaceFooter.H"
00645 #endif