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 #define CS_VOIDED_PTR ((intptr_t)-1) 00030 00031 template <class T> class csRef; 00032 00033 #if defined(CS_DEBUG) 00034 # define CS_TEST_VOIDPTRUSAGE 00035 #else 00036 # undef CS_TEST_VOIDPTRUSAGE 00037 #endif 00038 00039 #ifdef CS_REF_TRACKER 00040 #include <typeinfo> 00041 #include "csutil/reftrackeraccess.h" 00042 00043 #define CSREF_TRACK(x, cmd, refCount, obj, tag) \ 00044 { \ 00045 const int rc = obj ? refCount : -1; \ 00046 if (obj) \ 00047 { \ 00048 cmd; \ 00049 csRefTrackerAccess::SetDescription (obj, \ 00050 typeid(T).name()); \ 00051 csRefTrackerAccess::Match ## x (obj, rc, tag);\ 00052 } \ 00053 } 00054 #define CSREF_TRACK_INCREF(obj,tag) \ 00055 CSREF_TRACK(IncRef, obj->IncRef(), obj->GetRefCount(), obj, tag); 00056 #define CSREF_TRACK_DECREF(obj,tag) \ 00057 CSREF_TRACK(DecRef, obj->DecRef(), obj->GetRefCount(), obj, tag); 00058 #define CSREF_TRACK_ASSIGN(obj,tag) \ 00059 CSREF_TRACK(IncRef, void(0), obj->GetRefCount() - 1, obj, tag); 00060 #else 00061 #define CSREF_TRACK_INCREF(obj,tag) \ 00062 if (obj) obj->IncRef(); 00063 #define CSREF_TRACK_DECREF(obj,tag) \ 00064 if (obj) obj->DecRef(); 00065 #define CSREF_TRACK_ASSIGN(obj,tag) 00066 #endif 00067 00084 template <class T> 00085 class csPtr 00086 { 00087 private: 00088 friend class csRef<T>; 00089 T* obj; 00090 00091 public: 00092 csPtr (T* p) : obj (p) { CSREF_TRACK_ASSIGN(obj, this); } 00093 00094 template <class T2> 00095 explicit csPtr (csRef<T2> const& r) : obj((T2*)r) 00096 { 00097 CSREF_TRACK_INCREF (obj, this); 00098 } 00099 00100 #ifdef CS_TEST_VOIDPTRUSAGE 00101 ~csPtr () 00102 { 00103 // If not assigned to a csRef we have a problem (leak). 00104 // So if this assert fires for you, then you are calling 00105 // a function that returns a csPtr and not using the result 00106 // (or at least not assigning it to a csRef). This is a memory 00107 // leak and you should fix that. 00108 CS_ASSERT_MSG ("csPtr<> was not assigned to a csRef<> prior destruction", 00109 obj == (T*)CS_VOIDED_PTR); 00110 } 00111 #endif 00112 00113 csPtr (const csPtr<T>& copy) 00114 { 00115 obj = copy.obj; 00116 #ifdef CS_TEST_VOIDPTRUSAGE 00117 ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR; 00118 #endif 00119 } 00120 }; 00121 00132 template <class T> 00133 class csRef 00134 { 00135 private: 00136 T* obj; 00137 00138 public: 00144 csRef () : obj (0) {} 00145 00151 csRef (const csPtr<T>& newobj) 00152 { 00153 obj = newobj.obj; 00154 # ifdef CS_TEST_VOIDPTRUSAGE 00155 CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>", 00156 newobj.obj != (T*)CS_VOIDED_PTR); 00157 # endif 00158 // The following line is outside the ifdef to make sure 00159 // we have binary compatibility. 00160 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00161 } 00162 00167 csRef (T* newobj) : obj (newobj) 00168 { 00169 CSREF_TRACK_INCREF (obj, this); 00170 } 00171 00176 template <class T2> 00177 csRef (T2* newobj) : obj ((T2*)newobj) 00178 { 00179 CSREF_TRACK_INCREF (obj, this); 00180 } 00181 00185 template <class T2> 00186 csRef (csRef<T2> const& other) : obj ((T2*)other) 00187 { 00188 CSREF_TRACK_INCREF (obj, this); 00189 } 00190 00194 csRef (csRef const& other) : obj (other.obj) 00195 { 00196 CSREF_TRACK_INCREF (obj, this); 00197 } 00198 00202 ~csRef () 00203 { 00204 CSREF_TRACK_DECREF (obj, this); 00205 } 00206 00216 csRef& operator = (const csPtr<T>& newobj) 00217 { 00218 T* oldobj = obj; 00219 // First assign and then DecRef() of old object! 00220 obj = newobj.obj; 00221 # ifdef CS_TEST_VOIDPTRUSAGE 00222 CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>", 00223 newobj.obj != (T*)CS_VOIDED_PTR); 00224 # endif 00225 // The following line is outside the ifdef to make sure 00226 // we have binary compatibility. 00227 ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR; 00228 CSREF_TRACK_DECREF (oldobj, this); 00229 return *this; 00230 } 00231 00244 csRef& operator = (T* newobj) 00245 { 00246 if (obj != newobj) 00247 { 00248 T* oldobj = obj; 00249 // It is very important to first assign the new value to 00250 // 'obj' BEFORE calling DecRef() on the old object. Otherwise 00251 // it is easy to get in infinite loops with objects being 00252 // destructed forever (when ref=0 is used for example). 00253 obj = newobj; 00254 CSREF_TRACK_INCREF (newobj, this); 00255 CSREF_TRACK_DECREF (oldobj, this); 00256 } 00257 return *this; 00258 } 00259 00282 void AttachNew (csPtr<T> newObj) 00283 { 00284 // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is 00285 // deliberate and not to be considered a bug. 00286 00287 // Just Re-use csPtr assignment logic 00288 *this = newObj; 00289 } 00290 00292 template <class T2> 00293 csRef& operator = (csRef<T2> const& other) 00294 { 00295 T* p = (T2*)other; 00296 this->operator=(p); 00297 return *this; 00298 } 00299 00301 csRef& operator = (csRef const& other) 00302 { 00303 this->operator=(other.obj); 00304 return *this; 00305 } 00306 00308 inline friend bool operator == (const csRef& r1, const csRef& r2) 00309 { 00310 return r1.obj == r2.obj; 00311 } 00313 inline friend bool operator != (const csRef& r1, const csRef& r2) 00314 { 00315 return r1.obj != r2.obj; 00316 } 00318 inline friend bool operator == (const csRef& r1, T* obj) 00319 { 00320 return r1.obj == obj; 00321 } 00323 inline friend bool operator != (const csRef& r1, T* obj) 00324 { 00325 return r1.obj != obj; 00326 } 00328 inline friend bool operator == (T* obj, const csRef& r1) 00329 { 00330 return r1.obj == obj; 00331 } 00333 inline friend bool operator != (T* obj, const csRef& r1) 00334 { 00335 return r1.obj != obj; 00336 } 00342 inline friend bool operator < (const csRef& r1, const csRef& r2) 00343 { 00344 return r1.obj < r2.obj; 00345 } 00346 00347 00349 T* operator -> () const 00350 { return obj; } 00351 00353 operator T* () const 00354 { return obj; } 00355 00357 T& operator* () const 00358 { return *obj; } 00359 00364 bool IsValid () const 00365 { return (obj != 0); } 00366 00368 void Invalidate() 00369 { *this = (T*)0; } 00370 00372 uint GetHash() const 00373 { return (uintptr_t)obj; } 00374 }; 00375 00376 #undef CSREF_TRACK_INCREF 00377 #undef CSREF_TRACK_DECREF 00378 #undef CSREF_TRACK_ASSIGN 00379 00380 #endif // __CS_REF_H__
Generated for Crystal Space by doxygen 1.4.7