00001 #ifdef CH_LANG_CC 00002 /* 00003 * _______ __ 00004 * / ___/ / ___ __ _ / / ___ 00005 * / /__/ _ \/ _ \/ V \/ _ \/ _ \ 00006 * \___/_//_/\___/_/_/_/_.__/\___/ 00007 * Please refer to Copyright.txt, in Chombo's root directory. 00008 */ 00009 #endif 00010 00011 #ifndef _REFCOUNTEDPTR_H_ 00012 #define _REFCOUNTEDPTR_H_ 00013 00014 #include <string> 00015 #include <typeinfo> 00016 #include "MayDay.H" 00017 #include "Arena.H" 00018 #include "CH_assert.H" 00019 #include "BaseNamespaceHeader.H" 00020 00021 /// A reference-counting handle class. 00022 /** 00023 This is to be used as a pointer to class T. 00024 This will feel and smell just like a built-in pointer except: 00025 -# There is no need to call delete on the pointer. 00026 -# The default copy constructor and assignment implement ref-counting. 00027 -# The user may call isNonUnique to determine if this pointer is 00028 the only pointer to the data. This can be used to hide the 00029 ref-counting behavior of a class. 00030 -# Checks for dereference of a null pointer. 00031 00032 This class is completely inlined. 00033 00034 typical usage: 00035 00036 \code 00037 00038 { 00039 Box b; 00040 IntVect a; 00041 //refCount() == 1 00042 RefCountedPtr<IntVectSet> set(new IntVectSet()); 00043 00044 // still just one IntVectSet, but refCount()==2 00045 RefCountedPtr<IntVectSet> otherSet(set); 00046 00047 // Like a pointer, modifying one modifies the other 00048 otherSet->define(b); 00049 (*set)|=a; 00050 { 00051 RefCountedPtr<IntVectSet> anotherSet; // null 00052 anotherSet = otherSet ; //now all three have refCount()==3 00053 }//anotherSet out of scope, so deleted. IntVectSet NOT deleted. 00054 00055 // set.refCount() == 2 00056 // otherSet.refCount() == 2; 00057 // otherset == set; 00058 00059 } 00060 // when all RefCountedPtr's for a given object are deleted, the last 00061 // one calls 'delete' on the member pointer. 00062 \endcode 00063 00064 */ 00065 template <class T> 00066 class RefCountedPtr 00067 { 00068 public: 00069 // 00070 explicit inline RefCountedPtr(T* ptr = 0); 00071 // 00072 inline RefCountedPtr(const RefCountedPtr<T>& other); 00073 // 00074 inline ~RefCountedPtr(); 00075 /// assignement operator. copies pointer member 00076 /** copies pointer member and integer pointer, decreases refcount of rhs member 00077 before assignment. this refcount increased my one. */ 00078 inline const RefCountedPtr<T>& operator =(const RefCountedPtr<T>& rhs); 00079 /// dereference access operator. use like a pointer derefence access function. 00080 inline T* operator ->(); 00081 inline const T* operator ->() const; 00082 // 00083 inline bool isNull() const; 00084 // 00085 /// pointer dereference. 00086 inline T& operator *(); 00087 #ifdef CH_TEMPEST 00088 inline T& operator *() const; // As in Boost::shared_ptr. 00089 #else 00090 inline const T& operator *() const; 00091 #endif 00092 // 00093 /// auto conversion to regular const pointer where required. 00094 inline operator const T* () const; 00095 00096 /// true when refcount is one. 00097 inline bool isNonUnique() const; 00098 00099 inline int refCount() const; 00100 00101 inline void swap(RefCountedPtr<T>& b); 00102 00103 /// Template Conversion 00104 /** 00105 provides a mechanism for the compiler to generate a conversion to a base class, like 00106 a real pointer would have 00107 */ 00108 template<class T2> inline operator RefCountedPtr<T2>(); 00109 00110 // Will never delete ptr_. Useful in functions that need to return a 00111 // pointer which, under some circumstances, we want to own, and under others 00112 // we don't. 00113 inline void neverDelete(); 00114 00115 template<class T2> friend class RefCountedPtr; 00116 00117 static const std::string& name() 00118 { 00119 return name_; 00120 } 00121 00122 inline void increment(); 00123 inline void decrement(); 00124 protected: 00125 T* ptr_; 00126 int* refCount_; 00127 static std::string name_; 00128 static BArena s_Arena; 00129 static int size_; 00130 private: 00131 00132 }; 00133 00134 template<class T> 00135 std::string RefCountedPtr<T>::name_(std::string("RefCountedPtr ")+std::string(typeid(T).name())); 00136 00137 //template<class T> 00138 //BArena RefCountedPtr<T>::s_Arena(name_.c_str()); 00139 template<class T> 00140 BArena RefCountedPtr<T>::s_Arena(typeid(T).name()); 00141 00142 template<class T> 00143 int RefCountedPtr<T>::size_ = sizeof(T)+2*sizeof(int); 00144 00145 template <class T> inline 00146 void RefCountedPtr<T>::increment() 00147 { 00148 #ifdef CH_USE_MEMORY_TRACKING 00149 s_Arena.bytes += size_; 00150 refCount_[1] = size_; 00151 if (s_Arena.bytes > s_Arena.peak) 00152 { 00153 s_Arena.peak = s_Arena.bytes; 00154 } 00155 #endif 00156 } 00157 template <class T> inline 00158 void RefCountedPtr<T>::decrement() 00159 { 00160 #ifdef CH_USE_MEMORY_TRACKING 00161 s_Arena.bytes -= refCount_[1]; 00162 #endif 00163 } 00164 00165 template <class T> inline 00166 RefCountedPtr<T>::RefCountedPtr(T* ptr) 00167 : ptr_(ptr), 00168 refCount_(0) 00169 { 00170 if (ptr_) 00171 { 00172 refCount_ = new int[2]; 00173 if (refCount_ == 0) 00174 MayDay::Error("RefCountedPtr::RefCountedPtr(T* ptr) out of memory"); 00175 *refCount_ = 1; 00176 increment(); 00177 } 00178 } 00179 00180 template <class T> inline 00181 RefCountedPtr<T>::RefCountedPtr(const RefCountedPtr<T>& other) 00182 : ptr_(other.ptr_), 00183 refCount_(other.refCount_) 00184 { 00185 if (refCount_ != 0) 00186 ++(*refCount_); 00187 } 00188 00189 template <class T> inline 00190 RefCountedPtr<T>::~RefCountedPtr() 00191 { 00192 if (refCount_ != 0 && --(*refCount_) == 0) 00193 { 00194 decrement(); 00195 delete ptr_; 00196 ptr_ = 0; 00197 delete [] refCount_; 00198 refCount_ = 0; 00199 00200 } 00201 } 00202 00203 template <class T> inline 00204 const RefCountedPtr<T>& RefCountedPtr<T>::operator =(const RefCountedPtr<T>& rhs) 00205 { 00206 if (ptr_ != rhs.ptr_) 00207 { 00208 if (refCount_ != 0 && --(*refCount_) == 0) 00209 { 00210 decrement(); 00211 delete ptr_; 00212 delete [] refCount_; 00213 } 00214 ptr_ = rhs.ptr_; 00215 refCount_ = rhs.refCount_; 00216 if (refCount_ != 0) 00217 ++(*refCount_); 00218 } 00219 return *this; 00220 } 00221 00222 template <class T> inline 00223 bool RefCountedPtr<T>::isNull() const 00224 { 00225 return (ptr_ == 0); 00226 } 00227 00228 template <class T> inline 00229 T* RefCountedPtr<T>::operator ->() 00230 { 00231 if (ptr_ == 0) 00232 MayDay::Error("RefCountedPtr<T>::operator ->() on null pointer"); 00233 return ptr_; 00234 } 00235 00236 template <class T> inline 00237 const T* RefCountedPtr<T>::operator ->() const 00238 { 00239 if (ptr_ == 0) 00240 MayDay::Error("RefCountedPtr<T>::operator ->() on null pointer"); 00241 return ptr_; 00242 } 00243 00244 template <class T> inline 00245 T& RefCountedPtr<T>::operator *() 00246 { 00247 if (ptr_ == 0) 00248 MayDay::Error("RefCountedPtr<T>::operator *() on null pointer"); 00249 return *ptr_; 00250 } 00251 00252 template <class T> inline 00253 #ifndef CH_TEMPEST 00254 const 00255 #endif 00256 T& RefCountedPtr<T>::operator *() const 00257 { 00258 if (ptr_ == 0) 00259 MayDay::Error("RefCountedPtr<T>::operator *() on null pointer"); 00260 return *ptr_; 00261 } 00262 00263 template <class T> inline 00264 RefCountedPtr<T>::operator const T* () const 00265 { 00266 return ptr_; 00267 } 00268 00269 template <class T> inline 00270 bool RefCountedPtr<T>::isNonUnique() const 00271 { 00272 return refCount_ == 0 ? false : *refCount_ != 1; 00273 } 00274 00275 template <class T> inline 00276 int RefCountedPtr<T>::refCount() const 00277 { 00278 return refCount_ == 0 ? 0 : *refCount_; 00279 } 00280 00281 00282 00283 00284 template <class T> 00285 template <class T2> 00286 inline RefCountedPtr<T>::operator RefCountedPtr<T2> () 00287 { 00288 T2* t2 = dynamic_cast<T2*>(ptr_); // Handles upward and downward casts... -JNJ 00289 CH_assert(t2 != NULL); // ... unless the cast fails, of course. :-) 00290 RefCountedPtr<T2> rtn; // if you have a compiler error that points here, then T2 is probably not a T 00291 rtn.ptr_= t2; 00292 #ifdef CH_USE_MEMORY_TRACKING 00293 // by fiat the derived classes memory is transfered to the base class Arena 00294 s_Arena.bytes -=refCount_[1]; 00295 rtn.s_Arena.bytes +=refCount_[1]; 00296 #endif 00297 00298 ++ *refCount_; 00299 rtn.refCount_ = refCount_; 00300 return rtn; 00301 } 00302 00303 00304 template <class T> inline 00305 void RefCountedPtr<T>::swap(RefCountedPtr<T>& b) 00306 { 00307 T* s = ptr_; 00308 ptr_ = b.ptr_; 00309 b.ptr_ = s; 00310 00311 int* r = refCount_; 00312 refCount_ = b.refCount_; 00313 b.refCount_ = r; 00314 00315 } 00316 00317 template <class T> inline 00318 void RefCountedPtr<T>::neverDelete() 00319 { 00320 ++ *refCount_; 00321 } 00322 00323 #include "BaseNamespaceFooter.H" 00324 #endif
1.5.5