00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _refcountptr_h
00018 #define _refcountptr_h
00019
00020 #include <spl/types.h>
00021 #include <spl/Debug.h>
00022 #include <spl/Exception.h>
00023 #include <spl/threading/InterlockCounter.h>
00024 #include <spl/Memory.h>
00025
00033 template<class Y>
00034 struct _PtrHolder
00035 {
00036 private:
00037 bool m_threadSafe;
00038 mutable volatile short m_icount;
00039 mutable InterlockCounter m_tcount;
00040
00041 public:
00042 mutable Y* ptr;
00043
00044 inline _PtrHolder (Y* rhs, bool threadSafe)
00045 : ptr(rhs), m_icount(1), m_tcount(1), m_threadSafe(threadSafe)
00046 {
00047 }
00048
00049 inline void SetThreadSafeOn()
00050 {
00051 m_threadSafe = true;
00052 }
00053
00054 inline void ValidateThis() const
00055 {
00056 ASSERT_MEM(this, sizeof(_PtrHolder<Y>));
00057 }
00058
00059 inline int Count() const
00060 {
00061 if (m_threadSafe)
00062 {
00063 return (int)m_tcount;
00064 }
00065 return m_icount;
00066 }
00067
00068 inline void Inc()
00069 {
00070 if (m_threadSafe)
00071 {
00072 m_tcount++;
00073 }
00074 else
00075 {
00076 m_icount++;
00077 }
00078 }
00079
00080 inline int Dec()
00081 {
00082 if (m_threadSafe)
00083 {
00084 m_tcount--;
00085 return (int)m_tcount;
00086 }
00087 m_icount--;
00088 return m_icount;
00089 }
00090
00091 inline bool IsThreadSafe() const
00092 {
00093 return m_threadSafe;
00094 }
00095 };
00096
00097 template<class T>
00098 class RefCountPtr : public IMemoryValidate
00099 {
00100 private:
00101 mutable _PtrHolder<T> *m_ptr;
00102
00103 inline void _Dec()
00104 {
00105 if (NULL != m_ptr)
00106 {
00107 ASSERT(m_ptr->Count() > 0);
00108 if (0 == m_ptr->Dec())
00109 {
00110 delete m_ptr->ptr;
00111 delete m_ptr;
00112 }
00113 }
00114 }
00115
00116 public:
00117 typedef T element_type;
00118
00119
00120 explicit RefCountPtr (T* ptr, bool threadSafe = false)
00121 {
00122 if (NULL == ptr)
00123 {
00124 m_ptr = NULL;
00125 return;
00126 }
00127 ASSERT_PTR(ptr);
00128 m_ptr = new _PtrHolder<T>(ptr, threadSafe);
00129 }
00130
00131
00132
00133 RefCountPtr (const RefCountPtr<T>& rhs)
00134 : m_ptr(rhs.m_ptr)
00135 {
00136 if (NULL != m_ptr)
00137 {
00138 ASSERT(m_ptr->Count() > 0);
00139 m_ptr->ValidateThis();
00140 m_ptr->Inc();
00141 }
00142 }
00143
00144 RefCountPtr ()
00145 : m_ptr(NULL)
00146 {
00147 }
00148
00149 RefCountPtr(_PtrHolder<T> *ptr)
00150 : m_ptr(ptr)
00151 {
00152 if(NULL != ptr)
00153 {
00154 m_ptr->Inc();
00155 }
00156 }
00157
00158
00159
00160 RefCountPtr<T>& operator =(const RefCountPtr<T>& rhs)
00161 {
00162 _Dec();
00163
00164 if (NULL != (m_ptr = rhs.m_ptr))
00165 {
00166 ASSERT_MEM(m_ptr, sizeof(_PtrHolder<T>));
00167 m_ptr->Inc();
00168 }
00169
00170 return *this;
00171 }
00172
00173 RefCountPtr<T>& operator =(T *p)
00174 {
00175 _Dec();
00176 if (NULL == p)
00177 {
00178 m_ptr = NULL;
00179 return *this;
00180 }
00181 ASSERT_PTR(p);
00182 m_ptr = new _PtrHolder<T>(p, NULL == m_ptr ? false : m_ptr->IsThreadSafe());
00183
00184 return *this;
00185 }
00186
00187 #ifndef _WINDOWS
00188
00189
00190
00191 RefCountPtr<T>& operator= (RefCountPtr<T>& rhs)
00192 {
00193 return *this = (const RefCountPtr<T>&)rhs;
00194 }
00195 #endif
00196
00197
00198 virtual ~RefCountPtr()
00199 {
00200 Release();
00201 }
00202
00203 inline void SetThreadSafeOn()
00204 {
00205 ASSERT(NULL != m_ptr);
00206 m_ptr->SetThreadSafeOn();
00207 }
00208
00209 inline int ReferenceCount() const
00210 {
00211 return NULL == m_ptr ? 0 : m_ptr->Count();
00212 }
00213
00214 inline bool IsNull() const
00215 {
00216 return NULL == m_ptr || NULL == m_ptr->ptr;
00217 }
00218
00219 inline bool IsNotNull() const
00220 {
00221 return !IsNull();
00222 }
00223
00224 void Release()
00225 {
00226 if (NULL != m_ptr)
00227 {
00228 m_ptr->ValidateThis();
00229 ASSERT(m_ptr->Count() > 0);
00230
00231 if (0 == m_ptr->Dec())
00232 {
00233 delete m_ptr->ptr;
00234 delete m_ptr;
00235 }
00236 m_ptr = NULL;
00237 }
00238 }
00239
00240 T* Detach()
00241 {
00242 if(m_ptr == NULL)
00243 {
00244 return NULL;
00245 }
00246 ASSERT(m_ptr->Count() == 1);
00247 T* ret = m_ptr->ptr;
00248 delete m_ptr;
00249 m_ptr = NULL;
00250 return ret;
00251 }
00252
00253
00254 inline T* Get() const
00255 {
00256 if (NULL == m_ptr)
00257 {
00258 return NULL;
00259 }
00260 ASSERT(m_ptr->Count() > 0);
00261 return m_ptr->ptr;
00262 }
00263
00264
00265 inline _PtrHolder<T> *GetHolder() const
00266 {
00267 ASSERT(NULL == m_ptr || m_ptr->Count() > 0);
00268 return m_ptr;
00269 }
00270
00271 inline T& operator*() const
00272 {
00273 ASSERT(NULL != m_ptr);
00274 ASSERT(m_ptr->Count() > 0);
00275 return *m_ptr->ptr;
00276 }
00277
00278 inline T* operator->() const
00279 {
00280 ASSERT(NULL != m_ptr);
00281 ASSERT(m_ptr->Count() > 0);
00282 return m_ptr->ptr;
00283 }
00284
00285 inline operator T&() const
00286 {
00287 if (NULL == m_ptr)
00288 {
00289 throw new Exception("NULL pointer");
00290 }
00291 ASSERT(m_ptr->Count() > 0);
00292 return *m_ptr->ptr;
00293 }
00294
00295 #if defined(DEBUG) || defined(_DEBUG)
00296 void CheckMem() const
00297 {
00298 if (NULL != m_ptr)
00299 {
00300 DEBUG_NOTE_MEM(m_ptr);
00301 DEBUG_NOTE_MEM(m_ptr->ptr);
00302 ValidateType( m_ptr->ptr );
00303 }
00304 }
00305
00306 void ValidateMem() const
00307 {
00308 if (NULL != m_ptr)
00309 {
00310 m_ptr->ValidateThis();
00311 ASSERT_MEM(m_ptr->ptr, sizeof(T));
00312 ValidateType( m_ptr->ptr );
00313 }
00314 }
00315 #endif
00316 };
00317
00320 #endif