src/Utility/RefCounted.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef REF_COUNTED_H
00012 #define REF_COUNTED_H
00013 
00015 
00016 class RefCounted
00017 {
00018 public: 
00019 
00020   // The reference count.
00021   int RefCount;
00022 
00023   // The constructor just initializes the reference count.
00024   RefCounted()
00025     : RefCount(0)
00026       {
00027       }
00028 
00029 };
00030 
00032 
00033 template < class T >
00034 class RefCountedP
00035 {
00036 public: 
00037 
00038   // Null ctor constructs with a null ptr.
00039   RefCountedP()
00040     : p(0)
00041       {
00042       }
00043 
00044   // Initialize from a pointer to the pointed class.
00045   RefCountedP(T* pp)
00046     : p(pp) 
00047       {
00048         if (pp)
00049           ++(pp->RefCount);
00050       }
00051 
00052   // Copy ctor.
00053   RefCountedP(const RefCountedP<T>& pp)
00054     : p(pp.p)
00055       {
00056         if(p)
00057           ++(p->RefCount);
00058       }
00059 
00060   // When you destroy one of these, decrement the RefCount.
00061   ~RefCountedP()
00062     {
00063       if (p) {
00064         if ( (--(p->RefCount)) == 0 )
00065           delete p;
00066         p = 0;
00067       }
00068     }
00069 
00070   // Assignment operator increments the refcount.
00071   RefCountedP& operator=(const RefCountedP& rhs)
00072     {
00073       // First unlink from the one we're pointing to now.
00074       if ( p && (--(p->RefCount)==0) )
00075         delete p;
00076       // Assign the new one.
00077       if (p = rhs.p)
00078         ++(p->RefCount);
00079       return *this;
00080     }
00081 
00082   // Assignment operator increments the refcount.
00083   RefCountedP& operator=(T* pp)
00084     {
00085       // First unlink from the one we're pointing to now.
00086       if ( p && (--(p->RefCount)==0) )
00087         delete p;
00088       // Assign the new one.
00089       if (p = pp)
00090         ++(p->RefCount);
00091       return *this;
00092     }
00093 
00094   // Two ways to use the pointer.
00095   T* operator->() const { return p;  }
00096   T& operator*()  const { return *p; }
00097 
00098   // Just extract the pointer if you need it.
00099   operator T*() { return p; }
00100   operator const T*() const { return p; }
00101 
00102   void invalidate()
00103     {
00104       if ( p && (--(p->RefCount)==0) )
00105         delete p;
00106       p = 0;
00107     }
00108   bool valid()
00109     {
00110       return p!=0;
00111     }
00112 
00113   // Utility function for implementing copy-on-write semantics.
00114   RefCountedP<T>& CopyForWrite()
00115     {
00116       // If more than one thing is referring to this one
00117       if ( p && (p->RefCount > 1) )
00118         {
00119           // Unlink from the existing object.
00120           --(p->RefCount);
00121           // Copy it.
00122           p = new T( *p );
00123           // Inform it that we are watching.
00124           p->RefCount = 1;
00125         }
00126       // Return yourself for further processing.
00127       return *this;
00128     }
00129 
00130 private:
00131   // The pointer itself.
00132   T *p;
00133 };
00134 
00136 
00137 #endif // REF_COUNTED_H
00138 
00139 /***************************************************************************
00140  * $RCSfile: RefCounted.h,v $   $Author: adelmann $
00141  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00142  * IPPL_VERSION_ID: $Id: RefCounted.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00143  ***************************************************************************/

Generated on Mon Jan 16 13:23:59 2006 for IPPL by  doxygen 1.4.6