CrystalSpace

Public API Reference

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__

Generated for Crystal Space 2.0 by doxygen 1.7.6.1