libRefCount.h

Go to the documentation of this file.
00001 #ifndef __REFERENCECOUNTING_H__
00002 #define __REFERENCECOUNTING_H__
00003 
00004 #include "libUtility.h"
00005 
00006 #undef DEBUG
00007 #define DEBUG 0
00008 #include "libDebug.h"
00009 
00010 class Counted;
00011 class String;
00012 
00013 class CountedReferece //ref
00014 {
00015   static int m_cRefObjects;
00016 
00017   friend int ObjectsOutstanding();
00018   friend class Counted;
00019   friend class String;
00020 
00021 protected:
00022   int m_cReferences;
00023   Counted* m_pcounted;
00024 
00025 public:
00026   CountedReferece(Counted* pcounted)
00027   {
00028     DEBUGONLY(m_cRefObjects++);
00029     UD1("REFCREATE: reference 0x%x created. objects outstanding: %d",
00030         (int) this, m_cRefObjects);
00031 
00032     m_cReferences = 0;
00033     m_pcounted = pcounted;
00034   }
00035 
00036   ~CountedReferece()
00037   {
00038     DEBUGONLY(m_cRefObjects--);
00039     UD1("REFDESTROY: reference 0x%x destroyed. objects outstanding: %d",
00040         (int) this, m_cRefObjects);
00041   }
00042 };
00043 
00044 inline int ObjectsOutstanding()
00045 {
00046 #if DEBUG >= 0
00047   return CountedReferece::m_cRefObjects;
00048 #else
00049   return 0;
00050 #endif
00051 
00052 }
00053 
00054 class Counted // count
00055 {
00056   template<class COUNTED>
00057   friend COUNTED* ClaimPointer(COUNTED *pcount);
00058 
00059   template<class COUNTED>
00060   friend COUNTED* HandoffPointer(COUNTED *pcount);
00061   friend void ReleasePointer(Counted *pcount);
00062 
00063   friend class String;
00064 
00065 protected:
00066   int m_cPointerRefs;
00067 
00068 public:
00069   mutable CountedReferece* m_pref;
00070 
00071   Counted()
00072   {
00073     m_pref = new CountedReferece(this);
00074     UD2("CREATE: counted created 0x%x with reference 0x%x", (int) this,
00075         (int) m_pref);
00076     m_cPointerRefs = 1;
00077     Claim();
00078   }
00079 
00080   Counted(const Counted& refc)
00081   {
00082     m_pref = refc.m_pref;
00083     UD2("CREATE: counted created 0x%x with copied reference 0x%x", (int) this,
00084         (int) m_pref);
00085     m_cPointerRefs = refc.m_cPointerRefs;
00086     Claim();
00087   }
00088 
00089   virtual ~Counted() __attribute__((always_inline))
00090   {
00091     UD2("DESTROY: counted destroyed 0x%x with reference 0x%x", (int) this,
00092         (int) m_pref);
00093     m_cPointerRefs--;
00094     //      WARNIF(m_cPointerRefs==0,"non-zero pointer ref");
00095     Release();
00096   }
00097 
00098   Counted& operator =(const Counted& refc)
00099   {
00100     if (m_pref != refc.m_pref)
00101       {
00102       Release();
00103       m_pref = refc.m_pref;
00104       Claim();
00105       }
00106     UD2("COPY: counted copied  0x%x from reference 0x%x", (int) this,
00107         (int) m_pref);
00108     // dont change m_cPointerRefs;
00109     return *this;
00110   }
00111 
00112   Counted& operator =(Counted& refc)
00113   {
00114     if (m_pref != refc.m_pref)
00115       {
00116       Release();
00117       m_pref = refc.m_pref;
00118       Claim();
00119       }
00120     UD2("COPY: counted copied  0x%x from reference 0x%x", (int) this,
00121         (int) m_pref);
00122     // dont change m_cPointerRefs;
00123     return *this;
00124   }
00125 
00126   int References() const
00127   {
00128     return m_pref->m_cReferences;
00129   }
00130 
00131   int PointerReferences() const
00132   {
00133     return m_cPointerRefs;
00134   }
00135 
00136   void Claim() const
00137   {
00138     m_pref->m_cReferences++;
00139     UD2("CLAIM: counted 0x%x reference 0x%x increased to %d", (int) this,
00140         (int) m_pref, m_pref->m_cReferences);
00141   }
00142 
00143   void Release() const __attribute__((always_inline))
00144   {
00145     m_pref->m_cReferences--;
00146     UD2("RELEASE: counted 0x%x reference 0x%x decreased to %d", (int) this,
00147         (int) m_pref, m_pref->m_cReferences);
00148     if (m_pref->m_cReferences == 0)
00149       {
00150       UD2("KILL: counted 0x%x reference 0x%x destroyed", (int) this,
00151           (int) m_pref);
00152       delete m_pref;
00153       }
00154     UD2("RELEASE: done ");
00155   }
00156 
00157   bool AboutToDie()
00158   {
00159     return (m_pref->m_cReferences == 1);
00160   }
00161 
00162 };
00163 
00164 //============================================================================
00165 // pointer claiming:
00166 //
00167 //   Unlike object claiming, handled via the Claimed class above, which 
00168 //   ensures the proper management of an object's dynamically allocated content,
00169 //   pointer claiming manages the lifetime of dynamically created Claimed-derived 
00170 //   pointers.
00171 //
00172 //   a pointer which is created via new Claimed() begins as a pointer-claim 
00173 //   on it 
00174 //
00175 //   a pointer which has been claimed via ClaimPointer, or created via new
00176 //   must, be released by either calling ReleasePointer() or HandoffPointer() 
00177 //   or TakePointer()
00178 //
00179 //   a pointer which has been released via HandoffPointer() must be claimed
00180 //   via ClaimPointer(), and then handled as above
00181 // 
00182 //   a pointer released via ReleasePointer() may be destroyed, if thre are
00183 //   no other claims on it
00184 // 
00185 //   a pointer released via TakePointer() may be destroyed, if thre are
00186 //   no other claims on it, and an object claim is made and passed back as
00187 //   a stack-allocated object
00188 //
00189 //   when all claims are released via ReleasePointer() or TakePointer() the 
00190 //   pointer is deleted
00191 // 
00192 //============================================================================
00193 
00194 #if MULTITHREADPROTECTION
00195 #  include <pthread.h>
00196 namespace
00197   {
00198   pthread_mutex_t g_mutex;
00199   int Init()
00200     {
00201     D("INITIALIZING REFCOUNT MUTEX");
00202     pthread_mutex_init(&g_mutex,NULL);
00203     }
00204   int g_ignore=Init();
00205   }
00206 
00207 #  define REFCOUNT_LOCK pthread_mutex_lock(&g_mutex);
00208 #  define REFCOUNT_UNLOCK   pthread_mutex_unlock(&g_mutex);
00209 
00210 #else
00211 #  define REFCOUNT_LOCK 
00212 #  define REFCOUNT_UNLOCK   
00213 #endif
00214 
00215 //============================================================================
00216 //============================================================================
00217 // take ownership of a pointer. This commits you to either 
00218 // calling ReleasePointer() or HandoffPointer()
00219 template<class COUNTED>
00220 inline COUNTED* ClaimPointer(COUNTED *pcount) __attribute__((always_inline));
00221 template<class COUNTED>
00222 inline COUNTED* ClaimPointer(COUNTED *pcount)
00223 {
00224   REFCOUNT_LOCK;
00225   ASSERT(pcount != NULL);
00226   pcount->m_cPointerRefs++;
00227   REFCOUNT_UNLOCK;
00228   return pcount;
00229 }
00230 
00231 //============================================================================
00232 //============================================================================
00233 // dismiss ownership of a pointer, but do not free
00234 template<class COUNTED>
00235 inline COUNTED* HandoffPointer(COUNTED *pcount) __attribute__((always_inline));
00236 template<class COUNTED>
00237 inline COUNTED* HandoffPointer(COUNTED *pcount)
00238 {
00239   REFCOUNT_LOCK;
00240   ASSERT(pcount != NULL);
00241   ASSERT(pcount->m_cPointerRefs > 0);
00242   pcount->m_cPointerRefs--;
00243   REFCOUNT_UNLOCK;
00244   return pcount;
00245 }
00246 
00247 //============================================================================
00248 //============================================================================
00249 // dismiss ownership of a pointer, potentially freeing
00250 inline void ReleasePointer(Counted *pcount) __attribute__((always_inline));
00251 inline void ReleasePointer(Counted *pcount)
00252 {
00253   if (pcount == NULL)
00254     {
00255     return;
00256     }
00257 
00258   REFCOUNT_LOCK;
00259 
00260   UD4("PRELEASE: about to release pointer 0x%x %d/%d", (int) pcount,
00261       pcount->m_pref->m_cReferences, pcount->m_cPointerRefs);
00262 
00263   UD1("PRELEASE: releasing pointer 0x%x %d", (int) pcount,
00264       pcount->m_cPointerRefs);
00265   if (pcount->m_cPointerRefs == 1)
00266     {
00267     delete pcount;
00268     UD1("PKILL: deleteing pointer 0x%x", (int) pcount);
00269     }
00270   else
00271     {
00272     pcount->m_cPointerRefs--;
00273     UD1("PRELEASE: releasing pointer 0x%x %d", (int) pcount,
00274         pcount->m_cPointerRefs);
00275     }
00276 
00277   REFCOUNT_UNLOCK;
00278 }
00279 
00280 //============================================================================
00281 //============================================================================
00282 // release the current pointer and take claim of a new one, unless the
00283 // pointers are the same, in which case, do nothing
00284 template<class COUNTED>
00285 inline void ChangePointer(COUNTED*& pcount1, COUNTED*& pcount2) __attribute__((always_inline));
00286 template<class COUNTED>
00287 inline void ChangePointer(COUNTED*& pcount1, COUNTED*& pcount2)
00288 {
00289   REFCOUNT_LOCK;
00290   if (pcount1 != pcount2)
00291     {
00292     ReleasePointer(pcount1);
00293     pcount1 = pcount2;
00294     ClaimPointer(pcount2);
00295     } REFCOUNT_UNLOCK;
00296 }
00297 
00298 //============================================================================
00299 //============================================================================
00300 // release the claim to the pointer, and return copy as a stack-based object
00301 template<class COUNTED>
00302 inline COUNTED DereferencePointer(COUNTED* pcounted)
00303 {
00304   COUNTED counted = *pcounted;
00305   ReleasePointer(pcounted);
00306   counted.Release();
00307   return counted;
00308 }
00309 
00310 #endif //#ifndef __REFERENCEPCOUNTING_H__

Generated on 6 Apr 2011 for Slicer3 by  doxygen 1.6.1