Crystal Space: csutil/ref.h Source File (Crystal Space Public API Reference)

| ## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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
    00078 template <class T>
    00079 class  csPtr
    00080 {
    00081 private:
    00082   friend class csRef<T>;
    00083   T* obj;
    00084
    00085 public:
    00086   csPtr (T* p) : obj (p) { CSREF_TRACK_ASSIGN(obj, this); }
    00087
    00088   template <class T2>
    00089   explicit csPtr (csRef<T2> const& r) : obj((T2*)r)
    00090   {
    00091     CSREF_TRACK_INCREF (obj, this);
    00092   }
    00093
    00094 #ifdef CS_TEST_VOIDPTRUSAGE
    00095   ~csPtr ()
    00096   {
    00097     // If not assigned to a csRef we have a problem (leak).
    00098     // So if this assert fires for you, then you are calling
    00099     // a function that returns a csPtr and not using the result
    00100     // (or at least not assigning it to a csRef). This is a memory
    00101     // leak and you should fix that.
    00102     CS_ASSERT_MSG ("csPtr<> was not assigned to a csRef<> prior destruction",
    00103       obj == (T*)CS_VOIDED_PTR);
    00104   }
    00105 #endif
    00106
    00107   csPtr (const csPtr<T>& copy)
    00108   {
    00109     obj = copy.obj;
    00110 #ifdef CS_TEST_VOIDPTRUSAGE
    00111     ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR;
    00112 #endif
    00113   }
    00114 };
    00115
    00122 template <class T>
    00123 class  csRef
    00124 {
    00125 private:
    00126   T* obj;
    00127
    00128 public:
    00134   csRef () : obj (0) {}
    00135
    00141   csRef (const csPtr<T>& newobj)
    00142   {
    00143     obj = newobj.obj;
    00144 #   ifdef CS_TEST_VOIDPTRUSAGE
    00145     CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>",
    00146       newobj.obj != (T*)CS_VOIDED_PTR);
    00147 #   endif
    00148     // The following line is outside the ifdef to make sure
    00149     // we have binary compatibility.
    00150     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
    00151   }
    00152
    00157   csRef (T* newobj) : obj (newobj)
    00158   {
    00159     CSREF_TRACK_INCREF (obj, this);
    00160   }
    00161
    00166   template <class T2>
    00167   csRef (T2* newobj) : obj ((T2*)newobj)
    00168   {
    00169     CSREF_TRACK_INCREF (obj, this);
    00170   }
    00171
    00175   template <class T2>
    00176   csRef (csRef<T2> const& other) : obj ((T2*)other)
    00177   {
    00178     CSREF_TRACK_INCREF (obj, this);
    00179   }
    00180
    00184   csRef (csRef const& other) : obj (other.obj)
    00185   {
    00186     CSREF_TRACK_INCREF (obj, this);
    00187   }
    00188
    00192   ~csRef ()
    00193   {
    00194     CSREF_TRACK_DECREF (obj, this);
    00195   }
    00196
    00206   csRef& operator = (const csPtr<T>& newobj)
    00207   {
    00208     T* oldobj = obj;
    00209     // First assign and then DecRef() of old object!
    00210     obj = newobj.obj;
    00211 #   ifdef CS_TEST_VOIDPTRUSAGE
    00212     CS_ASSERT_MSG ("csPtr<> was already assigned to a csRef<>",
    00213       newobj.obj != (T*)CS_VOIDED_PTR);
    00214 #   endif
    00215     // The following line is outside the ifdef to make sure
    00216     // we have binary compatibility.
    00217     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
    00218     CSREF_TRACK_DECREF (oldobj, this);
    00219     return *this;
    00220   }
    00221
    00234   csRef& operator = (T* newobj)
    00235   {
    00236     if (obj != newobj)
    00237     {
    00238       T* oldobj = obj;
    00239       // It is very important to first assign the new value to
    00240       // 'obj' BEFORE calling DecRef() on the old object. Otherwise
    00241       // it is easy to get in infinite loops with objects being
    00242       // destructed forever (when ref=0 is used for example).
    00243       obj = newobj;
    00244       CSREF_TRACK_INCREF (newobj, this);
    00245       CSREF_TRACK_DECREF (oldobj, this);
    00246     }
    00247     return *this;
    00248   }
    00249
    00272   void AttachNew (csPtr<T> newObj)
    00273   {
    00274     // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is
    00275     // deliberate and not to be considered a bug.
    00276
    00277     // Just Re-use csPtr assignment logic
    00278     *this = newObj;
    00279   }
    00280
    00282   template <class T2>
    00283   csRef& operator = (csRef<T2> const& other)
    00284   {
    00285     T* p = (T2*)other;
    00286     this->operator=(p);
    00287     return *this;
    00288   }
    00289
    00291   csRef& operator = (csRef const& other)
    00292   {
    00293     this->operator=(other.obj);
    00294     return *this;
    00295   }
    00296
    00298   inline friend bool operator == (const csRef& r1, const csRef& r2)
    00299   {
    00300     return r1.obj == r2.obj;
    00301   }
    00303   inline friend bool operator != (const csRef& r1, const csRef& r2)
    00304   {
    00305     return r1.obj != r2.obj;
    00306   }
    00308   inline friend bool operator == (const csRef& r1, T* obj)
    00309   {
    00310     return r1.obj == obj;
    00311   }
    00313   inline friend bool operator != (const csRef& r1, T* obj)
    00314   {
    00315     return r1.obj != obj;
    00316   }
    00318   inline friend bool operator == (T* obj, const csRef& r1)
    00319   {
    00320     return r1.obj == obj;
    00321   }
    00323   inline friend bool operator != (T* obj, const csRef& r1)
    00324   {
    00325     return r1.obj != obj;
    00326   }
    00332   inline friend bool operator < (const csRef& r1, const csRef& r2)
    00333   {
    00334     return r1.obj < r2.obj;
    00335   }
    00336
    00337
    00339   T* operator -> () const
    00340   { return obj; }
    00341
    00343   operator T* () const
    00344   { return obj; }
    00345
    00347   T& operator* () const
    00348   { return *obj; }
    00349
    00354   bool IsValid () const
    00355   { return (obj != 0); }
    00356
    00358   void Invalidate()
    00359   { *this = (T*)0; }
    00360
    00362   uint GetHash() const
    00363   { return (uintptr_t)obj;  }
    00364 };
    00365
    00366 #undef CSREF_TRACK_INCREF
    00367 #undef CSREF_TRACK_DECREF
    00368 #undef CSREF_TRACK_ASSIGN
    00369
    00370 #endif // __CS_REF_H__