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
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
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
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
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
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
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
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
00218
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
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
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
00283
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
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__