CrystalSpace

Public API Reference

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

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 #define CS_VOIDED_PTR 0xffffffff
00024 
00025 template <class T> class csRef;
00026 
00027 #if defined(CS_DEBUG)
00028 #  define CS_TEST_VOIDPTRUSAGE
00029 #else
00030 #  undef CS_TEST_VOIDPTRUSAGE
00031 #endif
00032 
00043 template <class T>
00044 class csPtr
00045 {
00046 private:
00047   friend class csRef<T>;
00048   T* obj;
00049 
00050 public:
00051   csPtr (T* p) : obj (p) { }
00052 
00053   template <class T2>
00054   explicit csPtr (csRef<T2> const& r) : obj((T2*)r) { if (obj) obj->IncRef(); }
00055 
00056 #ifdef CS_TEST_VOIDPTRUSAGE
00057   ~csPtr ()
00058   {
00059     // If not assigned to a csRef we have a problem (leak).
00060     // So if this assert fires for you, then you are calling
00061     // a function that returns a csPtr and not using the result
00062     // (or at least not assigning it to a csRef). This is a memory
00063     // leak and you should fix that.
00064     CS_ASSERT (obj == (T*)CS_VOIDED_PTR);
00065   }
00066 #endif
00067 
00068   csPtr (const csPtr<T>& copy)
00069   {
00070     obj = copy.obj;
00071 #ifdef CS_TEST_VOIDPTRUSAGE
00072     ((csPtr<T>&)copy).obj = (T*)CS_VOIDED_PTR;
00073 #endif
00074   }
00075 };
00076 
00083 template <class T>
00084 class csRef
00085 {
00086 private:
00087   T* obj;
00088 
00089 public:
00095   csRef () : obj (0) {}
00096 
00102   csRef (const csPtr<T>& newobj)
00103   {
00104     obj = newobj.obj;
00105 #   ifdef CS_TEST_VOIDPTRUSAGE
00106     CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR);
00107 #   endif
00108     // The following line is outside the ifdef to make sure
00109     // we have binary compatibility.
00110     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
00111   }
00112 
00117   csRef (T* newobj) : obj (newobj)
00118   {
00119     if (obj)
00120       obj->IncRef ();
00121   }
00122   
00126   csRef (csRef const& other) : obj (other.obj)
00127   {
00128     if (obj)
00129       obj->IncRef ();
00130   }
00131 
00135   ~csRef ()
00136   {
00137     if (obj)
00138       obj->DecRef ();
00139   }
00140 
00150   csRef& operator = (const csPtr<T>& newobj)
00151   {
00152     T* oldobj = obj;
00153     // First assign and then DecRef() of old object!
00154     obj = newobj.obj;
00155 #   ifdef CS_TEST_VOIDPTRUSAGE
00156     CS_ASSERT (newobj.obj != (T*)CS_VOIDED_PTR);
00157 #   endif
00158     // The following line is outside the ifdef to make sure
00159     // we have binary compatibility.
00160     ((csPtr<T>&)newobj).obj = (T*)CS_VOIDED_PTR;
00161     if (oldobj)
00162       oldobj->DecRef ();
00163     return *this;
00164   }
00165 
00178   csRef& operator = (T* newobj)
00179   {
00180     if (obj != newobj)
00181     {
00182       T* oldobj = obj;
00183       // It is very important to first assign the new value to
00184       // 'obj' BEFORE calling DecRef() on the old object. Otherwise
00185       // it is easy to get in infinite loops with objects being
00186       // destructed forever (when ref=0 is used for example).
00187       obj = newobj;
00188       if (newobj)
00189         newobj->IncRef ();
00190       if (oldobj)
00191         oldobj->DecRef ();
00192     }
00193     return *this;
00194   }
00195 
00218   void AttachNew (csPtr<T> newObj)
00219   {
00220     // Note: The parameter usage of csPtr<T> instead of csPtr<T>& is
00221     // deliberate and not to be considered a bug.
00222 
00223     // Just Re-use csPtr assignment logic
00224     *this = newObj;
00225   }
00226 
00230   csRef& operator = (csRef const& other)
00231   {
00232     this->operator=(other.obj);
00233     return *this;
00234   }
00235 
00237   inline friend bool operator == (const csRef& r1, const csRef& r2)
00238   {
00239     return r1.obj == r2.obj;
00240   }
00242   inline friend bool operator != (const csRef& r1, const csRef& r2)
00243   {
00244     return r1.obj != r2.obj;
00245   }
00247   inline friend bool operator == (const csRef& r1, T* obj)
00248   {
00249     return r1.obj == obj;
00250   }
00252   inline friend bool operator != (const csRef& r1, T* obj)
00253   {
00254     return r1.obj != obj;
00255   }
00257   inline friend bool operator == (T* obj, const csRef& r1)
00258   {
00259     return r1.obj == obj;
00260   }
00262   inline friend bool operator != (T* obj, const csRef& r1)
00263   {
00264     return r1.obj != obj;
00265   }
00266 
00268   T* operator -> () const
00269   { return obj; }
00270   
00272   operator T* () const
00273   { return obj; }
00274   
00276   T& operator* () const
00277   { return *obj; }
00278 
00283   bool IsValid () const
00284   { return (obj != 0); }
00285 };
00286 
00287 #endif // __CS_REF_H__

Generated for Crystal Space by doxygen 1.2.14