csutil/ref.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Smart Pointers 00003 Copyright (C) 2002 by Jorrit Tyberghein and Matthias Braun 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #ifndef __CS_REF_H__ 00021 #define __CS_REF_H__ 00022 00027 #include "csextern.h" 00028 00029 #include "csutil/customallocated.h" 00030 00031 #define CS_VOIDED_PTR ((intptr_t)-1) 00032 00033 template <class T> class csRef; 00034 00035 #if defined(CS_DEBUG) 00036 # define CS_TEST_VOIDPTRUSAGE 00037 #else 00038 # undef CS_TEST_VOIDPTRUSAGE 00039 #endif 00040 00041 #ifdef CS_REF_TRACKER 00042 #include <typeinfo> 00043 #include "csutil/reftrackeraccess.h" 00044 00045 #define CSREF_TRACK(x, cmd, refCount, obj, tag) \ 00046 { \ 00047 const int rc = obj ? refCount : -1; \ 00048 if (obj) \ 00049 { \ 00050 cmd; \ 00051 csRefTrackerAccess::SetDescriptionWeak (obj, \ 00052 typeid(T).name()); \ 00053 csRefTrackerAccess::Match ## x (obj, rc, tag);\ 00054 } \ 00055 } 00056 #define CSREF_TRACK_INCREF(obj,tag) \ 00057 CSREF_TRACK(IncRef, obj->IncRef(), obj->GetRefCount(), obj, tag); 00058 #define CSREF_TRACK_DECREF(obj,tag) \ 00059 CSREF_TRACK(DecRef, obj->DecRef(), obj->GetRefCount(), obj, tag); 00060 #define CSREF_TRACK_ASSIGN(obj,tag) \ 00061 CSREF_TRACK(IncRef, void(0), obj->GetRefCount() - 1, obj, tag); 00062 #else 00063 #define CSREF_TRACK_INCREF(obj,tag) \ 00064 if (obj) obj->IncRef(); 00065 #define CSREF_TRACK_DECREF(obj,tag) \ 00066 if (obj) obj->DecRef(); 00067 #define CSREF_TRACK_ASSIGN(obj,tag) 00068 #endif 00069 00086 template <class T> 00087 class csPtr : public CS::Memory::CustomAllocated 00088 { 00089 private: 00090 friend class csRef<T>; 00091 T* obj; 00092 00093 public: 00094 csPtr (T* p) : obj (p) { CSREF_TRACK_ASSIGN(obj, this); } 00095 00096 template <class T2> 00097 explicit csPtr (csRef<T2> const& r) : obj((T2*)r) 00098 { 00099 CSREF_TRACK_INCREF (obj, this); 00100 } 00101 00102 #ifdef CS_TEST_VOIDPTRUSAGE 00103 ~csPtr () 00104 { 00105 // If not assigned to a csRef we have a problem (leak). 00106 // So if this assert fires for you, then you are calling 00107 // a function that returns a csPtr and not using the result 00108 // (or at least not assigning it to a csRef). This is a memory 00109 // leak and you should fix that. 00110 CS_ASSERT_MSG ("csPtr<> was not assigned to a csRef<> prior destruction", 00111 obj == (T*)CS_VOIDED_PTR); 00112 } 00113 #endif 00114 00115 csPtr (const csPtr<T>& copy) 00116 { 00117 obj = copy.obj; 00118 #ifdef CS_TEST_VOIDPTRUSAGE 00119 ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR; 00120 #endif 00121 } 00122 }; 00123 00134 template <class T> 00135 class csRef : public CS::Memory::CustomAllocated 00136 { 00137 private: 00138 T* obj; 00139 00140 public: 00146 csRef () : obj (0) {} 00147 00153 csRef (const csPtr<T>& newobj) 00154 { 00155 obj = newobj.obj; 00156 # ifdef CS_TEST_VOIDPTRUSAGE 00157 CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>", 00158 newobj.obj != (T*)CS_VOIDED_PTR); 00159 # endif 00160 // The following line is outside the ifdef to make sure 00161 // we have binary compatibility. 00162 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00163 } 00164 00169 csRef (T* newobj) : obj (newobj) 00170 { 00171 CSREF_TRACK_INCREF (obj, this); 00172 } 00173 00178 template <class T2> 00179 csRef (T2* newobj) : obj ((T2*)newobj) 00180 { 00181 CSREF_TRACK_INCREF (obj, this); 00182 } 00183 00187 template <class T2> 00188 csRef (csRef<T2> const& other) : obj ((T2*)other) 00189 { 00190 CSREF_TRACK_INCREF (obj, this); 00191 } 00192 00196 csRef (csRef const& other) : obj (other.obj) 00197 { 00198 CSREF_TRACK_INCREF (obj, this); 00199 } 00200 00204 ~csRef () 00205 { 00206 CSREF_TRACK_DECREF (obj, this); 00207 } 00208 00218 csRef& operator = (const csPtr<T>& newobj) 00219 { 00220 T* oldobj = obj; 00221 // First assign and then DecRef() of old object! 00222 obj = newobj.obj; 00223 # ifdef CS_TEST_VOIDPTRUSAGE 00224 CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>", 00225 newobj.obj != (T*)CS_VOIDED_PTR); 00226 # endif 00227 // The following line is outside the ifdef to make sure 00228 // we have binary compatibility. 00229 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00230 CSREF_TRACK_DECREF (oldobj, this); 00231 return *this; 00232 } 00233 00246 csRef& operator = (T* newobj) 00247 { 00248 if (obj != newobj) 00249 { 00250 T* oldobj = obj; 00251 // It is very important to first assign the new value to 00252 // 'obj' BEFORE calling DecRef() on the old object. Otherwise 00253 // it is easy to get in infinite loops with objects being 00254 // destructed forever (when ref=0 is used for example). 00255 obj = newobj; 00256 CSREF_TRACK_INCREF (newobj, this); 00257 CSREF_TRACK_DECREF (oldobj, this); 00258 } 00259 return *this; 00260 } 00261 00284 void AttachNew (csPtr<T> newObj) 00285 { 00286 // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is 00287 // deliberate and not to be considered a bug. 00288 00289 // Just Re-use csPtr assignment logic 00290 *this = newObj; 00291 } 00292 00294 template <class T2> 00295 csRef& operator = (csRef<T2> const& other) 00296 { 00297 T* p = (T2*)other; 00298 this->operator=(p); 00299 return *this; 00300 } 00301 00303 csRef& operator = (csRef const& other) 00304 { 00305 this->operator=(other.obj); 00306 return *this; 00307 } 00308 00310 inline friend bool operator == (const csRef& r1, const csRef& r2) 00311 { 00312 return r1.obj == r2.obj; 00313 } 00315 inline friend bool operator != (const csRef& r1, const csRef& r2) 00316 { 00317 return r1.obj != r2.obj; 00318 } 00320 inline friend bool operator == (const csRef& r1, T* obj) 00321 { 00322 return r1.obj == obj; 00323 } 00325 inline friend bool operator != (const csRef& r1, T* obj) 00326 { 00327 return r1.obj != obj; 00328 } 00330 inline friend bool operator == (T* obj, const csRef& r1) 00331 { 00332 return r1.obj == obj; 00333 } 00335 inline friend bool operator != (T* obj, const csRef& r1) 00336 { 00337 return r1.obj != obj; 00338 } 00344 inline friend bool operator < (const csRef& r1, const csRef& r2) 00345 { 00346 return r1.obj < r2.obj; 00347 } 00348 00349 00351 T* operator -> () const 00352 { return obj; } 00353 00355 operator T* () const 00356 { return obj; } 00357 00359 T& operator* () const 00360 { return *obj; } 00361 00366 bool IsValid () const 00367 { return (obj != 0); } 00368 00370 void Invalidate() 00371 { *this = (T*)0; } 00372 00374 uint GetHash() const 00375 { return (uintptr_t)obj; } 00376 }; 00377 00378 #undef CSREF_TRACK_INCREF 00379 #undef CSREF_TRACK_DECREF 00380 #undef CSREF_TRACK_ASSIGN 00381 00382 #endif // __CS_REF_H__
Generated for Crystal Space 2.0 by doxygen 1.6.1