csutil/ref.h
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 00023 #include "csextern.h" 00024 00025 #define CS_VOIDED_PTR 0xffffffff 00026 00027 template <class T> class csRef; 00028 00029 #if defined(CS_DEBUG) 00030 # define CS_TEST_VOIDPTRUSAGE 00031 #else 00032 # undef CS_TEST_VOIDPTRUSAGE 00033 #endif 00034 00035 #ifdef CS_REF_TRACKER 00036 #include <typeinfo> 00037 #include "csutil/reftrackeraccess.h" 00038 00039 #define CSREF_TRACK(x, cmd, refCount, obj, tag) \ 00040 { \ 00041 const int rc = obj ? refCount : -1; \ 00042 if (obj) cmd; \ 00043 if (obj) \ 00044 { \ 00045 csRefTrackerAccess::SetDescription (obj, \ 00046 typeid(T).name()); \ 00047 csRefTrackerAccess::Match ## x (obj, rc, tag);\ 00048 } \ 00049 } 00050 #define CSREF_TRACK_INCREF(obj,tag) \ 00051 CSREF_TRACK(IncRef, obj->IncRef(), obj->GetRefCount(), obj, tag); 00052 #define CSREF_TRACK_DECREF(obj,tag) \ 00053 CSREF_TRACK(DecRef, obj->DecRef(), obj->GetRefCount(), obj, tag); 00054 #define CSREF_TRACK_ASSIGN(obj,tag) \ 00055 CSREF_TRACK(IncRef, (0), obj->GetRefCount() - 1, obj, tag); 00056 #else 00057 #define CSREF_TRACK_INCREF(obj,tag) \ 00058 if (obj) obj->IncRef(); 00059 #define CSREF_TRACK_DECREF(obj,tag) \ 00060 if (obj) obj->DecRef(); 00061 #define CSREF_TRACK_ASSIGN(obj,tag) 00062 #endif 00063 00074 template <class T> 00075 class csPtr 00076 { 00077 private: 00078 friend class csRef<T>; 00079 T* obj; 00080 00081 public: 00082 csPtr (T* p) : obj (p) { CSREF_TRACK_ASSIGN(obj, this); } 00083 00084 template <class T2> 00085 explicit csPtr (csRef<T2> const& r) : obj((T2*)r) 00086 { 00087 CSREF_TRACK_INCREF (obj, this); 00088 } 00089 00090 #ifdef CS_TEST_VOIDPTRUSAGE 00091 ~csPtr () 00092 { 00093 // If not assigned to a csRef we have a problem (leak). 00094 // So if this assert fires for you, then you are calling 00095 // a function that returns a csPtr and not using the result 00096 // (or at least not assigning it to a csRef). This is a memory 00097 // leak and you should fix that. 00098 CS_ASSERT (obj == (T*)CS_VOIDED_PTR); 00099 } 00100 #endif 00101 00102 csPtr (const csPtr<T>& copy) 00103 { 00104 obj = copy.obj; 00105 #ifdef CS_TEST_VOIDPTRUSAGE 00106 ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR; 00107 #endif 00108 } 00109 }; 00110 00117 template <class T> 00118 class csRef 00119 { 00120 private: 00121 T* obj; 00122 00123 public: 00129 csRef () : obj (0) {} 00130 00136 csRef (const csPtr<T>& newobj) 00137 { 00138 obj = newobj.obj; 00139 # ifdef CS_TEST_VOIDPTRUSAGE 00140 CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR); 00141 # endif 00142 // The following line is outside the ifdef to make sure 00143 // we have binary compatibility. 00144 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00145 } 00146 00151 csRef (T* newobj) : obj (newobj) 00152 { 00153 CSREF_TRACK_INCREF (obj, this); 00154 } 00155 00159 template <class T2> 00160 csRef (csRef<T2> const& other) : obj ((T2*)other) 00161 { 00162 CSREF_TRACK_INCREF (obj, this); 00163 } 00164 00168 csRef (csRef const& other) : obj (other.obj) 00169 { 00170 CSREF_TRACK_INCREF (obj, this); 00171 } 00172 00176 ~csRef () 00177 { 00178 CSREF_TRACK_DECREF (obj, this); 00179 } 00180 00190 csRef& operator = (const csPtr<T>& newobj) 00191 { 00192 T* oldobj = obj; 00193 // First assign and then DecRef() of old object! 00194 obj = newobj.obj; 00195 # ifdef CS_TEST_VOIDPTRUSAGE 00196 CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR); 00197 # endif 00198 // The following line is outside the ifdef to make sure 00199 // we have binary compatibility. 00200 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00201 CSREF_TRACK_DECREF (oldobj, this); 00202 return *this; 00203 } 00204 00217 csRef& operator = (T* newobj) 00218 { 00219 if (obj != newobj) 00220 { 00221 T* oldobj = obj; 00222 // It is very important to first assign the new value to 00223 // 'obj' BEFORE calling DecRef() on the old object. Otherwise 00224 // it is easy to get in infinite loops with objects being 00225 // destructed forever (when ref=0 is used for example). 00226 obj = newobj; 00227 CSREF_TRACK_INCREF (newobj, this); 00228 CSREF_TRACK_DECREF (oldobj, this); 00229 } 00230 return *this; 00231 } 00232 00255 void AttachNew (csPtr<T> newObj) 00256 { 00257 // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is 00258 // deliberate and not to be considered a bug. 00259 00260 // Just Re-use csPtr assignment logic 00261 *this = newObj; 00262 } 00263 00265 template <class T2> 00266 csRef& operator = (csRef<T2> const& other) 00267 { 00268 T* p = (T2*)other; 00269 this->operator=(p); 00270 return *this; 00271 } 00272 00274 csRef& operator = (csRef const& other) 00275 { 00276 this->operator=(other.obj); 00277 return *this; 00278 } 00279 00281 inline friend bool operator == (const csRef& r1, const csRef& r2) 00282 { 00283 return r1.obj == r2.obj; 00284 } 00286 inline friend bool operator != (const csRef& r1, const csRef& r2) 00287 { 00288 return r1.obj != r2.obj; 00289 } 00291 inline friend bool operator == (const csRef& r1, T* obj) 00292 { 00293 return r1.obj == obj; 00294 } 00296 inline friend bool operator != (const csRef& r1, T* obj) 00297 { 00298 return r1.obj != obj; 00299 } 00301 inline friend bool operator == (T* obj, const csRef& r1) 00302 { 00303 return r1.obj == obj; 00304 } 00306 inline friend bool operator != (T* obj, const csRef& r1) 00307 { 00308 return r1.obj != obj; 00309 } 00310 00312 T* operator -> () const 00313 { return obj; } 00314 00316 operator T* () const 00317 { return obj; } 00318 00320 T& operator* () const 00321 { return *obj; } 00322 00327 bool IsValid () const 00328 { return (obj != 0); } 00329 }; 00330 00331 #undef CSREF_TRACK_INCREF 00332 #undef CSREF_TRACK_DECREF 00333 #undef CSREF_TRACK_ASSIGN 00334 00335 #endif // __CS_REF_H__
Generated for Crystal Space by doxygen 1.2.18