CrystalSpace

Public API Reference

Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

csutil/ref.h

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 
00023 #include "csextern.h"
00024 
00025 #define CS_VOIDED_PTR 0xffffffff
00026 
00027 template <class T> class csRef;
00028 
00029 #if defined(CS_DEBUG)
00030 #  define CS_TEST_VOIDPTRUSAGE
00031 #else
00032 #  undef CS_TEST_VOIDPTRUSAGE
00033 #endif
00034 
00035 #ifdef CS_REF_TRACKER
00036  #include <typeinfo>
00037  #include "csutil/reftrackeraccess.h"
00038 
00039  #define CSREF_TRACK(x, cmd, refCount, obj, tag)    \
00040   {                                                 \
00041     const int rc = obj ? refCount : -1;             \
00042     if (obj) cmd;                                   \
00043     if (obj)                                        \
00044     {                                               \
00045       csRefTrackerAccess::SetDescription (obj,      \
00046         typeid(T).name());                          \
00047       csRefTrackerAccess::Match ## x (obj, rc, tag);\
00048     }                                               \
00049   }
00050  #define CSREF_TRACK_INCREF(obj,tag)    \
00051   CSREF_TRACK(IncRef, obj->IncRef(), obj->GetRefCount(), obj, tag);
00052  #define CSREF_TRACK_DECREF(obj,tag)    \
00053   CSREF_TRACK(DecRef, obj->DecRef(), obj->GetRefCount(), obj, tag);
00054  #define CSREF_TRACK_ASSIGN(obj,tag)    \
00055   CSREF_TRACK(IncRef, (0), obj->GetRefCount() - 1, obj, tag);
00056 #else
00057  #define CSREF_TRACK_INCREF(obj,tag) \
00058   if (obj) obj->IncRef();
00059  #define CSREF_TRACK_DECREF(obj,tag) \
00060   if (obj) obj->DecRef();
00061  #define CSREF_TRACK_ASSIGN(obj,tag)
00062 #endif
00063 
00074 template <class T>
00075 class  csPtr
00076 {
00077 private:
00078   friend class csRef<T>;
00079   T* obj;
00080 
00081 public:
00082   csPtr (T* p) : obj (p) { CSREF_TRACK_ASSIGN(obj, this); }
00083 
00084   template <class T2>
00085   explicit csPtr (csRef<T2> const& r) : obj((T2*)r) 
00086   { 
00087     CSREF_TRACK_INCREF (obj, this);
00088   }
00089 
00090 #ifdef CS_TEST_VOIDPTRUSAGE
00091   ~csPtr ()
00092   {
00093     // If not assigned to a csRef we have a problem (leak).
00094     // So if this assert fires for you, then you are calling
00095     // a function that returns a csPtr and not using the result
00096     // (or at least not assigning it to a csRef). This is a memory
00097     // leak and you should fix that.
00098     CS_ASSERT (obj == (T*)CS_VOIDED_PTR);
00099   }
00100 #endif
00101 
00102   csPtr (const csPtr<T>& copy)
00103   {
00104     obj = copy.obj;
00105 #ifdef CS_TEST_VOIDPTRUSAGE
00106     ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR;
00107 #endif
00108   }
00109 };
00110 
00117 template <class T>
00118 class  csRef
00119 {
00120 private:
00121   T* obj;
00122 
00123 public:
00129   csRef () : obj (0) {}
00130 
00136   csRef (const csPtr<T>& newobj)
00137   {
00138     obj = newobj.obj;
00139 #   ifdef CS_TEST_VOIDPTRUSAGE
00140     CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR);
00141 #   endif
00142     // The following line is outside the ifdef to make sure
00143     // we have binary compatibility.
00144     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
00145   }
00146 
00151   csRef (T* newobj) : obj (newobj)
00152   {
00153     CSREF_TRACK_INCREF (obj, this);
00154   }
00155   
00159   template <class T2>
00160   csRef (csRef<T2> const& other) : obj ((T2*)other)
00161   {
00162     CSREF_TRACK_INCREF (obj, this);
00163   }
00164 
00168   csRef (csRef const& other) : obj (other.obj)
00169   {
00170     CSREF_TRACK_INCREF (obj, this);
00171   }
00172 
00176   ~csRef ()
00177   {
00178     CSREF_TRACK_DECREF (obj, this);
00179   }
00180 
00190   csRef& operator = (const csPtr<T>& newobj)
00191   {
00192     T* oldobj = obj;
00193     // First assign and then DecRef() of old object!
00194     obj = newobj.obj;
00195 #   ifdef CS_TEST_VOIDPTRUSAGE
00196     CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR);
00197 #   endif
00198     // The following line is outside the ifdef to make sure
00199     // we have binary compatibility.
00200     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
00201     CSREF_TRACK_DECREF (oldobj, this);
00202     return *this;
00203   }
00204 
00217   csRef& operator = (T* newobj)
00218   {
00219     if (obj != newobj)
00220     {
00221       T* oldobj = obj;
00222       // It is very important to first assign the new value to
00223       // 'obj' BEFORE calling DecRef() on the old object. Otherwise
00224       // it is easy to get in infinite loops with objects being
00225       // destructed forever (when ref=0 is used for example).
00226       obj = newobj;
00227       CSREF_TRACK_INCREF (newobj, this);
00228       CSREF_TRACK_DECREF (oldobj, this);
00229     }
00230     return *this;
00231   }
00232 
00255   void AttachNew (csPtr<T> newObj)
00256   {
00257     // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is
00258     // deliberate and not to be considered a bug.
00259 
00260     // Just Re-use csPtr assignment logic
00261     *this = newObj;
00262   }
00263 
00265   template <class T2>
00266   csRef& operator = (csRef<T2> const& other)
00267   {
00268     T* p = (T2*)other;
00269     this->operator=(p);
00270     return *this;
00271   }
00272 
00274   csRef& operator = (csRef const& other)
00275   {
00276     this->operator=(other.obj);
00277     return *this;
00278   }
00279 
00281   inline friend bool operator == (const csRef& r1, const csRef& r2)
00282   {
00283     return r1.obj == r2.obj;
00284   }
00286   inline friend bool operator != (const csRef& r1, const csRef& r2)
00287   {
00288     return r1.obj != r2.obj;
00289   }
00291   inline friend bool operator == (const csRef& r1, T* obj)
00292   {
00293     return r1.obj == obj;
00294   }
00296   inline friend bool operator != (const csRef& r1, T* obj)
00297   {
00298     return r1.obj != obj;
00299   }
00301   inline friend bool operator == (T* obj, const csRef& r1)
00302   {
00303     return r1.obj == obj;
00304   }
00306   inline friend bool operator != (T* obj, const csRef& r1)
00307   {
00308     return r1.obj != obj;
00309   }
00310 
00312   T* operator -> () const
00313   { return obj; }
00314   
00316   operator T* () const
00317   { return obj; }
00318   
00320   T& operator* () const
00321   { return *obj; }
00322 
00327   bool IsValid () const
00328   { return (obj != 0); }
00329 };
00330 
00331 #undef CSREF_TRACK_INCREF
00332 #undef CSREF_TRACK_DECREF
00333 #undef CSREF_TRACK_ASSIGN
00334 
00335 #endif // __CS_REF_H__

Generated for Crystal Space by doxygen 1.2.18