00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00106
00107
00108
00109
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
00161
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
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
00228
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
00252
00253
00254
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
00287
00288
00289
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__