Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 #ifndef WAVEPACKET_SMART_PTR_H__
00037 #define WAVEPACKET_SMART_PTR_H__
00038 
00039 
00040 
00041 #include "threadsafe_counter.h"
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 template <class T>
00069 class smart_ptr
00070 {
00071 public:
00072         
00073         smart_ptr(T * pT = NULL) throw() : m_prefcount(NULL), m_pT(NULL) {
00074                 this->assign(pT);
00075         }
00076 
00077         template <class X>
00078         smart_ptr(IN const smart_ptr<X>& from) throw() :
00079             m_prefcount(NULL), m_pT(NULL) {
00080                 this->assign(from);
00081         }
00082 
00083         smart_ptr(IN const smart_ptr<T>& from) throw() :
00084             m_prefcount(NULL), m_pT(NULL) {
00085                 this->assign(from);
00086         }
00087         
00088         
00089         ~smart_ptr(void) throw() { this->release(); }
00090 
00091         
00092         T * operator -> (void) throw() {
00093                 ASSERT(m_pT, "NULL smart pointer");
00094                 return m_pT;
00095         }
00096 
00097         const T * operator -> (void) const throw() {
00098                 ASSERT(m_pT, "NULL smart pointer");
00099                 return m_pT;
00100         }
00101 
00102         operator T * (void) throw() {
00103                 return m_pT;
00104         }
00105 
00106         operator const T * (void) const throw() {
00107                 return m_pT;
00108         }
00109 
00110         bool operator ! (void) const throw() {
00111                 return !m_pT;
00112         }
00113 
00114         const smart_ptr<T>& operator = (IN T * pT) throw() {
00115                 this->assign(pT);
00116                 return *this;
00117         }
00118 
00119         template <class X>
00120         const smart_ptr<T>& operator = (IN const smart_ptr<X>& from) throw() {
00121                 this->assign(from);
00122                 return *this;
00123         }
00124 
00125         const smart_ptr<T>& operator = (IN const smart_ptr<T>& from) throw() {
00126                 this->assign(from);
00127                 return *this;
00128         }
00129 
00130         long get_ref_count(void) const throw() {
00131                 return (m_prefcount) ? m_prefcount->getCount() : 0;
00132         }
00133 
00134         T * disown(void) throw() {
00135                 
00136                 
00137                 ASSERT(m_prefcount && m_pT,
00138                     "calling disown() on empty smart_ptr<T>");
00139                 ASSERT(!m_prefcount->decrement(),
00140                     "Can only disown() smart_ptr<T>'s with 1 ref");
00141                 delete m_prefcount;
00142                 m_prefcount = NULL;
00143                 T * pT = m_pT;
00144                 m_pT = NULL;
00145                 return pT;
00146         }
00147 
00148 private:
00149         
00150 
00151         
00152         void assign(IN T * pT) throw() {
00153                 this->release();
00154                 if (pT) {
00155                         m_prefcount = new threadsafe_counter;
00156                         ASSERT(m_prefcount, "out of memory");
00157                         m_prefcount->increment();
00158                         m_pT = pT;
00159                 }
00160         }
00161 
00162         template <class X>
00163         void assign(IN const smart_ptr<X>& from) throw() {
00164                 this->release();
00165 
00166                 
00167                 smart_ptr<T> * pfoo =
00168                     (smart_ptr<T> *) ((void *) &from);
00169 
00170                 
00171                 
00172                 
00173                 
00174                 long incCount = pfoo->increment();
00175                 if (incCount < 2) {
00176                         
00177                         pfoo->decrement();
00178                         return;
00179                 }
00180 
00181                 
00182                 
00183 
00184                 
00185                 const X * pX = (const X *) from;
00186                 const T * pT = dynamic_cast<const T *>(pX);
00187                 if (!pT) {
00188                         
00189                         pfoo->decrement();
00190                         return;
00191                 }
00192 
00193                 
00194                 ASSERT(pT, "should have non-null pointer");
00195 
00196                 
00197                 T * new_pT = (T *) pT;
00198 
00199                 
00200                 m_prefcount = pfoo->m_prefcount;
00201                 m_pT = new_pT;
00202 
00203                 
00204                 
00205         }
00206 
00207         void release(void) throw() {
00208                 if (m_prefcount) {
00209                         
00210                         long count = m_prefcount->decrement();
00211                         if (count < 1) {
00212                                 
00213                                 m_prefcount->increment();   
00214                                 delete m_pT;
00215                                 delete m_prefcount;
00216                         }
00217 
00218                         
00219                         m_prefcount = NULL;
00220                         m_pT = NULL;
00221                 }
00222                 ASSERT(!m_pT && !m_prefcount, "Invalid release");
00223         }
00224 
00225         long increment(void) throw() {
00226                         if (m_prefcount) {
00227                                 return m_prefcount->increment();
00228                         }
00229                         return 0;
00230                 }
00231 
00232         long decrement(void) throw() {
00233                         if (m_prefcount) {
00234                                 return m_prefcount->decrement();
00235                         }
00236                         return 0;
00237                 }
00238 
00239         
00240         threadsafe_counter *    m_prefcount;    
00241         T      *m_pT;           
00242 };
00243 
00244 
00245 
00246 #endif  // WAVEPACKET_SMART_PTR_H__
00247