00001 ////////////////////////////////////////////////////////////// 00002 // 00003 // 00004 // by Joe Kniss 00005 // jmk@cs.utah.edu 00006 // June 2003 00007 // 00008 ////////////////////////////////////////////////////////////// 00009 00010 #ifndef __GUTZ_SMARTPTR_DOT_H 00011 #define __GUTZ_SMARTPTR_DOT_H 00012 00013 // Turns out this is the documentation for the namespace... 00014 00015 /// GUTZ, the innards of all my applications. 00016 /// Tons of usefull stuff, that in my mind really should be in 00017 /// the C++ standard library, or a Graphics standard libarary. 00018 namespace gutz { 00019 00020 // forward decl of SmartPtr 00021 template <class T> class SmartPtr; 00022 00023 ////////////////////////////////////////////////////////////// 00024 /// Counted, Derive your class from it if you want SmartPtr s to it. 00025 ///\code 00026 /// class CMyObject : public Counted { ... }; 00027 ///\endcode 00028 /// Remember, never create a counted object on the stack! 00029 /// (unless you never have SmartPtr s to it) 00030 /// 00031 /// TODO: add stack-heap check using operator new and a 00032 /// a static pointer map. 00033 class Counted { 00034 public: 00035 00036 virtual ~Counted() {} 00037 00038 protected: 00039 00040 template< class T > friend class SmartPtr; 00041 template< class T > friend class SmartPtrRef; 00042 00043 /// gutz::Counted interface, increment reference count by one. 00044 /// Not generaly used by subclasses, mostly for 00045 /// collaboration with gutz::SmartPtr. Sometimes 00046 /// you need to call this though, see the 00047 /// documentation for gutz::SmartPtr 00048 virtual void _incCount() {++_count; } 00049 /// gutz::Counted interface, decrement reference count by one. 00050 /// Not generaly used by subclasses, mostly for 00051 /// collaboration with gutz::SmartPtr. Sometimes 00052 /// you need to call this though, see the 00053 /// documentation for gutz::SmartPtr 00054 virtual void _decCount() {--_count; } 00055 /// gutz::Counted interface, get the current reference count. 00056 /// Not generaly used by subclasses, mostly for 00057 /// collaboration with gutz::SmartPtr. 00058 virtual int _getCount() const {return _count;} 00059 00060 /// protected constructor since this class does nothing by itself 00061 Counted(const Counted &c):_count(0) {} 00062 /// need to handle this correctly 00063 Counted &operator=(const Counted &c) {return *this;} 00064 /// default constructor, protected! 00065 Counted():_count(0) {} 00066 private: 00067 /// Counted: reference count, if _getCount() == 0 then delete 00068 int _count; 00069 }; 00070 00071 00072 00073 ////////////////////////////////////////////////////////////// 00074 /// Smart Pointer class. 00075 /// Smart Pointers are FUN FUN FUN. 00076 /// 00077 /// For all intents an purposes, SmartPtrs work just like regular 00078 /// pointers, for instance you can: 00079 /// \code 00080 /// gutz::SmartPtr<MyClass> mcsp(); // create a "0" (Null) pointer by default 00081 /// mcsp = new MyClass(); // assign a pointer 00082 /// if( mcsp ) // check if the pointer is non-zero 00083 /// if( !mcsp ) // check if the pointer is zero 00084 /// if( mcsp == mcp ) // compare against another SmartPtr or raw pointer 00085 /// mcsp->myFunction(); // call a member function 00086 /// (*mcsp) = blah; // de-refrence 00087 /// 00088 /// // declaration of some function taking a pointer to MyClass 00089 /// void someFunc(MyClass *mcp); 00090 /// // call that function, but let the SmartPtr auto-cast to a pointer 00091 /// someFunc( mcsp ); // works fine too 00092 /// \endcode 00093 /// The difference is that you don't need to call delete on your 00094 /// pointer, the SmartPtr<> will delete it when it gets deleted 00095 /// AND holds the last reference to that object. Just imagine a world 00096 /// with no memory leaks. 00097 /// 00098 /// Const SmartPtrs work just like const ptrs. 00099 /// \code const SmartPtr<T> ~= T const* \endcode 00100 /// You can always get at the "raw" pointer using: 00101 /// \code mySP.getPtr(); \endcode; 00102 /// 00103 /// There is one major caveaut: Any class that can have a SmartPtr 00104 /// to it MUST be a subclass of gutz::Counted. This insures that 00105 /// we only have one (1) reference counter to any pointer, since it 00106 /// is a member of the class rather than a "proxy-class". One day I will 00107 /// implement an "AutoDeletPtr" which allows you to do the same thing with 00108 /// non-Counted classes. Forcing a Counted subclass, however, has advantages: 00109 /// - You can cast to different levels of the hierarchy and still have valid SmartPtrs 00110 /// - You can convert a pointer to a SmartPtr any time and still have valid refcounts 00111 /// - A Counted Base class insures, via type checking, that we have only 1 refcounter per ptr 00112 /// 00113 /// SmartPtr is itself a subclass of counted so that you can have 00114 /// SmartPtrs to SmartPtrs and SmartPtrRef s. 00115 /// 00116 /// Notes: Having issues? 00117 /// You shouldn't create a Counted object on the stack. 00118 /// If you do, and somebody else gets a smart pointer to 00119 /// that object, the smartptr will call delete on 00120 /// stack memory when the refcount drops to 0, which it 00121 /// might if the function doesn't delete the object 00122 /// first, both cases are bad. 00123 /// Here is an example that would cause an error. 00124 ///\code 00125 /// SmartPtr<T> newObjSP; 00126 /// T newObj; 00127 /// newObjSP = &newObj; 00128 ///\endcode 00129 /// Notice that newObj is a local (stack) object. 00130 /// The right way: 00131 ///\code 00132 /// SmartPtr<T> newObjSP = new T; 00133 ///\endcode 00134 /// the new object will get deleted when no one else has 00135 /// a reference to it. 00136 /// 00137 /// Another caveaut of smartptrs is that if an object is 00138 /// using a smartptr to itself (why? who knows?), when 00139 /// the smartptr is deleted it might just delete the object 00140 /// that is using it. This happens especially when the 00141 /// constructor uses the smartptr, badness! If 00142 /// you have to do this, you need to increment your own 00143 /// reference counter first, then decrement when the ptr 00144 /// is gone (to avoid memory leaks). Again, be carefull, 00145 /// if the smartptr is created on the stack, you're pretty 00146 /// much screwed, because you can't possibly decrement 00147 /// after the smartptr is deleted. This reference to self 00148 /// situation can come up when iterators use smartptrs to the 00149 /// object they are iterating through. If the iterator is 00150 /// used internally, then when it goes away, the object itself 00151 /// might get deleted. Like say, when you need to iterate 00152 /// through yourself in the constructor :) You know you are 00153 /// getting into the danger zone when you do this 00154 /// (no pun intended): 00155 ///\code 00156 /// // somewhere in a member function of "MyObj" 00157 /// SmartPtr<MyObj> s(this); /// this!!! 00158 ///\endcode 00159 /// The right way would be: 00160 ///\code 00161 /// // somewhere in a member function of "MyObj" 00162 /// _incCount(); 00163 /// SmartPtr<MyObj> *sp = new SmartPtr<MyObj>(this); 00164 /// <... do what you gota do ...> 00165 /// delete sp; 00166 /// _decCount(); 00167 ///\endcode 00168 /// Function calls are often the culprit, but this case is 00169 /// simpler, just inc and dec around the call: 00170 ///\code 00171 /// // somewhere in a member function of "MyObj" 00172 /// _incCount(); 00173 /// someFunctionUsingSPs(SmartPtr<MyObj>(this)); 00174 /// _decCount(); 00175 ///\endcode 00176 /// Remember, this only applies to use of a smartptr to "this" in 00177 /// the objects member functions, or any function call using the "this" 00178 /// pointer or a SmartPtr to "this" in the objects constructors. 00179 template <class T> 00180 class SmartPtr : public Counted 00181 { 00182 public: 00183 typedef T type; 00184 00185 SmartPtr() { _ref = 0; } 00186 SmartPtr(T* const ptr) { _ref = 0; assign(ptr);} 00187 SmartPtr(const SmartPtr &sp) { _ref = 0; assign(sp._ref);} 00188 virtual ~SmartPtr() { assign((T*)0); } 00189 00190 ////////////////////////////////////////// 00191 ///@name get the contained pointer 00192 ///@{ 00193 T* getPtr() { return _ref; } 00194 T* const getPtr() const { return _ref; } 00195 ///@} 00196 00197 ////////////////////////////////////////// 00198 ///@name assign another smart pointer, or a raw pointer 00199 ///@{ 00200 SmartPtr & operator = (const SmartPtr &sp) {assign(sp._ref); return *this;} 00201 // assign pointer or NULL 00202 T *operator = (T* const ptr) {assign(ptr); return getPtr();} 00203 ///@} 00204 00205 ////////////////////////////////////////// 00206 ///@name access members of T 00207 /// ex \code mySmartPtr->myFunction() \endcode 00208 ///@{ 00209 T* operator ->() { return getPtr(); } 00210 T* const operator ->() const { return getPtr(); } 00211 ///@} 00212 00213 ///////////////////////////////////////// 00214 ///@name De-reference like a regular pointer 00215 /// ex \code (*mySmartPtr).myFunction() \endcode 00216 ///@{ 00217 T& operator*() { return *getPtr(); } 00218 T& operator*() const { return *getPtr(); } 00219 ///@} 00220 00221 ////////////////////////////////////////// 00222 ///@name Implicit conversion to T* 00223 /// good for function calls that take a 00224 /// regular pointer, for example: 00225 /// \code 00226 /// ///declaration of some function, taking a pointer 00227 /// void someFunc(someType *sc); 00228 /// ///calling "someFunc" using a smartptr as the parameter 00229 /// someFunc( mySP2someType ); /// converts SP to a raw pointer implicitly 00230 /// \endcode 00231 /// also needed for "if" tests: 00232 /// \code if( mySP2someType ) /// test if ptr != 0 \endcode 00233 ///@{ 00234 operator T* const () const { return getPtr();} 00235 //operator T* () { return getPtr();} 00236 ///@} 00237 00238 ////////////////////////////////////////// 00239 ///@name Casting for convenience 00240 /// Handles dynamic cast for you. 00241 ///@{ 00242 00243 /// \code 00244 /// mySubClassSP = myBaseClassSP.down_cast<MySubClassType>(); 00245 /// \endcode 00246 /// You don't need this for an "up-cast" since this thing automatically 00247 /// casts itself to a pointer which will then be up-casted by the compiler. 00248 template< class CT > 00249 SmartPtr<CT> cast() const 00250 { return SmartPtr<CT>((CT*const)dynamic_cast<CT*const>(_ref)); } 00251 ///@} 00252 00253 ////////////////////////////////////////// 00254 ///@name utilities, comparison ops 00255 /// just like raw ptrs, 00256 /// \code 00257 /// if(SP != 0)... 00258 /// if(SP == NULL) 00259 /// \endcode 00260 ///@{ 00261 bool operator!() const { return getPtr()==0;} 00262 #if 0 // these are completely redundant because of the auto cast 00263 bool operator==(const T *const ptr) const { return getPtr()==ptr; } 00264 bool operator==(const SmartPtr<T> &sp) const { return getPtr()==sp.getPtr();} 00265 bool operator!=(const T *const ptr) const { return getPtr()==ptr; } 00266 bool operator!=(const SmartPtr<T> &sp) const { return getPtr()!=sp.getPtr();} 00267 /// these may or maynot be what you want! be carefull 00268 /// they compare pointer values.. 00269 bool operator<(const SmartPtr<T> &sp) const { return getPtr()<sp.getPtr();} 00270 bool operator<=(const SmartPtr<T> &sp) const { return getPtr()<=sp.getPtr();} 00271 bool operator>(const SmartPtr<T> &sp) const { return getPtr()>sp.getPtr();} 00272 bool operator>=(const SmartPtr<T> &sp) const { return getPtr()>=sp.getPtr();} 00273 #endif 00274 /// just for convienence. access via, 00275 /// \code mySp.isNull() \endcode 00276 bool isNull() const { return (getPtr()==0); } 00277 ///@} 00278 00279 00280 protected: 00281 /// The only data we have is this pointer, so we have the same memory 00282 /// foot print of a regular pointer. 00283 T *_ref; 00284 00285 void assign(T* const ref) 00286 { 00287 /// inc ref if non-zero 00288 if(ref!=0) ref->_incCount(); 00289 /// save off old reference 00290 T *oldref = _ref; 00291 /// assign _ref = ref 00292 _ref = ref; 00293 /// delete the old reference 00294 if(oldref!=0){ 00295 /// just a dec most of the time... 00296 oldref->_decCount(); 00297 /// but if we hold the last reference, nuke it 00298 if((oldref->_getCount() <= 0)) 00299 { 00300 delete oldref; 00301 } 00302 } 00303 } 00304 00305 }; 00306 00307 ////////////////////////////////////////////////////////////// 00308 /// Smart Pointer Reference class, behaves like a 00309 /// reference to a pointer. 00310 /// This class can be used for clean double indirection 00311 /// of objects, ie. when an object changes all those with 00312 /// one of these objects referencing it will see the 00313 /// changes. Great for volitle pointers. 00314 ////////////////////////////////////////////////////////////// 00315 template<class T> 00316 class SmartPtrRef { 00317 public: 00318 typedef SmartPtr<T> type; 00319 00320 SmartPtrRef() { _ref = 0; assign(new type(0));} 00321 SmartPtrRef(T * ptr) { _ref = 0; assign(new type(ptr));} 00322 SmartPtrRef(const SmartPtrRef &dsp) { _ref = 0; assign(dsp._ref); } 00323 SmartPtrRef(SmartPtr<T> *sp) { _ref = 0; assign(sp);} 00324 virtual ~SmartPtrRef() { assign((type*)0); } 00325 00326 ////////////////////////////////////////// 00327 ///@name get the contained pointer 00328 ///@{ 00329 T* getPtr() { return _ref->getPtr(); } 00330 T const* getPtr() const { return _ref->getPtr(); } 00331 ///@} 00332 00333 ////////////////////////////////////////// 00334 ///@name assign smart pointer, remember this is 00335 /// a reference to a pointer, not a pointer. 00336 ///@{ 00337 SmartPtrRef & operator= (const SmartPtrRef &sp) { *_ref = *(sp._ref); return *this;} 00338 // assign pointer or NULL 00339 T *operator = (T * ptr) {*_ref = ptr; return ptr;} 00340 ///@} 00341 00342 ////////////////////////////////////////// 00343 ///@name access members of T 00344 /// ex. T->myFunction() 00345 ///@{ 00346 T* operator ->() { return getPtr(); } 00347 T const* operator ->() const { return getPtr(); } 00348 ///@} 00349 00350 ///////////////////////////////////////// 00351 ///@name De-reference like a regular pointer 00352 /// ex (*mySmartPRef).myFunction() 00353 ///@{ 00354 T& operator*() { return *getPtr(); } 00355 T const& operator*() const { return *getPtr(); } 00356 ///@} 00357 00358 ////////////////////////////////////////// 00359 /// Implicit conversion to T* (for function calls) 00360 operator T* () { return _ref.getPtr();} 00361 00362 00363 ////////////////////////////////////////// 00364 ///@name utilities, comparison ops 00365 /// just like raw ptrs, if(T != 0)... if(T == NULL) 00366 ///@{ 00367 bool operator!() const { return getPtr()==0;} 00368 bool operator==(const T* ptr) const { return getPtr()==ptr; } 00369 bool operator==(const SmartPtrRef &sp) const { return getPtr()==sp.getPtr();} 00370 bool operator!=(const T* ptr) const { return getPtr()==ptr; } 00371 bool operator!=(const SmartPtrRef &sp) const { return getPtr()!=sp.getPtr();} 00372 /// these may or maynot be what you want! be carefull 00373 bool operator<(const SmartPtrRef &sp) const { return getPtr()<sp.getPtr();} 00374 bool operator<=(const SmartPtrRef &sp) const { return getPtr()<=sp.getPtr();} 00375 bool operator>(const SmartPtrRef &sp) const { return getPtr()>sp.getPtr();} 00376 bool operator>=(const SmartPtrRef &sp) const { return getPtr()>=sp.getPtr();} 00377 /// for convienence since if(mySP) is always true, 00378 /// use if(!myPtr.isNull())... 00379 ///@} 00380 bool isNull() const { return (getPtr()==0); } 00381 00382 ////////////////////////////////////////// 00383 /// Private from here down 00384 protected: 00385 type *_ref; 00386 00387 void assign(type *ref) 00388 { 00389 /// add a reference to the new guy 00390 if(ref!=0) ref->_incCount(); 00391 type *oldref = _ref; //< save off old reference 00392 _ref = ref; //< assign new guy 00393 /// deleting the old guy 00394 if(oldref!=0){ 00395 /// just a dec most of the time 00396 oldref->_decCount(); 00397 /// but if we are the last reference, nuke it 00398 if(oldref->_getCount() <= 0) 00399 { 00400 delete oldref; 00401 } 00402 } 00403 } 00404 }; 00405 00406 00407 } /// end namespace gutz 00408 00409 #endif