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

| ## Public API Reference

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

- 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 #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__