00001 /* 00002 * xyzzy 00003 * Copyright (C) 2007 Karl W. Pfalzer 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the 00017 * Free Software Foundation, Inc. 00018 * 51 Franklin Street, Fifth Floor 00019 * Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #if !defined(_xyzzy_refcnt_hxx_) 00023 # define _xyzzy_refcnt_hxx_ 00024 00025 #include "xyzzy/util.hxx" 00026 #include "xyzzy/exception.hxx" 00027 00028 namespace xyzzy 00029 { 00030 // Any reference counted object must derive from TRcObj. 00031 class TRcObj 00032 { 00033 public: 00034 virtual ~TRcObj() 00035 {} 00036 }; 00037 00038 // A class used by PTRcPtr. 00039 struct _TRcPtr 00040 { 00041 _TRcPtr() 00042 : mp_dat(0), m_cnt(1) 00043 {} 00044 00045 _TRcPtr(TRcObj *p) 00046 : mp_dat(p), m_cnt(1) 00047 {} 00048 00049 bool decr() 00050 { 00051 if (1 > --m_cnt) 00052 { 00053 delete mp_dat; 00054 } 00055 return (1 > m_cnt) ? true : false; 00056 } 00057 00058 ~_TRcPtr() 00059 {} 00060 00061 TRcObj *mp_dat; 00062 unsigned m_cnt; 00063 }; 00064 00065 template<class T> class PTRcObjPtr; 00066 00067 template<class T> _TRcPtr* getBasePtr(const PTRcObjPtr<T> &r); 00068 00069 // A class derived from TRcObj uses PTRcObjPtr for refence counting. 00070 // Casting between Base <--> Derived can be done using: 00071 // downcast (base to derived) 00072 // and upcast (derived to base) functions. 00073 template<class T> 00074 class PTRcObjPtr 00075 { 00076 public: 00077 explicit PTRcObjPtr(); 00078 00079 PTRcObjPtr(T *p); 00080 00081 PTRcObjPtr(const PTRcObjPtr &r); 00082 00083 explicit PTRcObjPtr(_TRcPtr *p); 00084 00085 const PTRcObjPtr& operator=(const PTRcObjPtr &r); 00086 00087 const PTRcObjPtr& operator=(T *p); 00088 00089 bool isNull() const; 00090 00091 T* operator->(); 00092 00093 const T* operator->() const; 00094 00095 T& operator*() {return *this->operator->();} 00096 00097 const T& operator*() const {return *this->operator->();} 00098 00099 ~PTRcObjPtr(); 00100 00101 private: 00102 void decr(); 00103 00104 _TRcPtr *m_p; 00105 00106 friend _TRcPtr* getBasePtr<T>(const PTRcObjPtr<T> &r); 00107 00108 #if defined(DEBUG) 00109 const T *p_t; 00110 00111 # define SET_T p_t = dynamic_cast<const T*>(m_p->mp_dat) 00112 #else 00113 # define SET_T 00114 #endif 00115 }; 00116 00117 template<class T> 00118 _TRcPtr* 00119 getBasePtr(const PTRcObjPtr<T> &r) 00120 { 00121 return r.m_p; 00122 } 00123 00124 template<class Base, class Derived> 00125 PTRcObjPtr<Derived> 00126 downcast(const PTRcObjPtr<Base> &p) 00127 { 00128 _TRcPtr *rp = getBasePtr(p); 00129 return PTRcObjPtr<Derived>(rp); 00130 } 00131 00132 template<class Base, class Derived> 00133 PTRcObjPtr<Base> 00134 upcast(const PTRcObjPtr<Derived> &p) 00135 { 00136 _TRcPtr *rp = getBasePtr(p); 00137 return PTRcObjPtr<Base>(rp); 00138 } 00139 00140 // A class *not* derived from TRcObj uses PTRcPtr for reference counting. 00141 // NOTE: Casting between Base <--> Derived cannot (easily!) be done 00142 // (except using getPtr(), but not recommended.) 00143 template<class T> 00144 class PTRcPtr 00145 { 00146 public: 00147 explicit PTRcPtr(); 00148 00149 PTRcPtr(T *p); 00150 00151 PTRcPtr(const PTRcPtr &r); 00152 00153 const PTRcPtr& operator=(const PTRcPtr &r); 00154 00155 const PTRcPtr& operator=(T *p); 00156 00157 bool isNull() const; 00158 00159 T* operator->(); 00160 00161 const T* operator->() const; 00162 00163 T* getPtr() 00164 { 00165 return this->operator->(); 00166 } 00167 00168 const T* getPtr() const 00169 { 00170 return this->operator->(); 00171 } 00172 00173 ~PTRcPtr(); 00174 00175 private: 00176 void decr(); 00177 00178 struct TRcPtr2 00179 { 00180 TRcPtr2() 00181 : mp_dat(0), m_cnt(1) 00182 {} 00183 00184 TRcPtr2(T *p) 00185 : mp_dat(p), m_cnt(1) 00186 {} 00187 00188 bool decr() 00189 { 00190 if (1 > --m_cnt) 00191 { 00192 delete mp_dat; 00193 } 00194 return (1 > m_cnt) ? true : false; 00195 } 00196 00197 ~TRcPtr2() 00198 {} 00199 00200 T *mp_dat; 00201 unsigned m_cnt; 00202 }; 00203 00204 TRcPtr2 *m_p; 00205 }; 00206 00207 // 00208 // Class definitions 00209 // 00210 template<class T> 00211 PTRcObjPtr<T>::PTRcObjPtr() 00212 { 00213 m_p = new _TRcPtr(); 00214 SET_T; 00215 } 00216 00217 template<class T> 00218 PTRcObjPtr<T>::PTRcObjPtr(T *p) 00219 { 00220 m_p = new _TRcPtr(p); 00221 SET_T; 00222 } 00223 00224 template<class T> 00225 PTRcObjPtr<T>::PTRcObjPtr(const PTRcObjPtr &r) 00226 { 00227 m_p = r.m_p; 00228 m_p->m_cnt++; 00229 SET_T; 00230 } 00231 00232 template<class T> 00233 PTRcObjPtr<T>::PTRcObjPtr(_TRcPtr *p) 00234 { 00235 m_p = p; 00236 m_p->m_cnt++; 00237 SET_T; 00238 } 00239 00240 template<class T> 00241 const PTRcObjPtr<T>& 00242 PTRcObjPtr<T>::operator=(const PTRcObjPtr &r) 00243 { 00244 if (this != &r) 00245 { 00246 decr(); 00247 m_p = r.m_p; 00248 m_p->m_cnt++; 00249 SET_T; 00250 } 00251 return *this; 00252 } 00253 00254 template<class T> 00255 const PTRcObjPtr<T>& 00256 PTRcObjPtr<T>::operator=(T *p) 00257 { 00258 decr(); 00259 m_p = new _TRcPtr(p); 00260 SET_T; 00261 return *this; 00262 } 00263 00264 template<class T> 00265 bool 00266 PTRcObjPtr<T>::isNull() const 00267 { 00268 return (0 != m_p->mp_dat) ? false : true; 00269 } 00270 00271 template<class T> 00272 T* 00273 PTRcObjPtr<T>::operator->() 00274 { 00275 if (isNull()) 00276 { 00277 throw TNullPointerException(); 00278 } 00279 T* p = dynamic_cast<T*>(m_p->mp_dat); 00280 if (0 == p) 00281 { 00282 throw TDynamicCastException(); 00283 } 00284 return p; 00285 } 00286 00287 template<class T> 00288 const T* 00289 PTRcObjPtr<T>::operator->() const 00290 { 00291 if (isNull()) 00292 { 00293 throw TNullPointerException(); 00294 } 00295 const T* p = dynamic_cast<const T*>(m_p->mp_dat); 00296 if (0 == p) 00297 { 00298 throw TDynamicCastException(); 00299 } 00300 return p; 00301 } 00302 00303 template<class T> 00304 PTRcObjPtr<T>::~PTRcObjPtr() 00305 { 00306 decr(); 00307 } 00308 00309 template<class T> 00310 void 00311 PTRcObjPtr<T>::decr() 00312 { 00313 if (true == m_p->decr()) 00314 { 00315 delete m_p; 00316 } 00317 } 00318 00319 template<class T> 00320 PTRcPtr<T>::PTRcPtr() 00321 { 00322 m_p = new TRcPtr2(); 00323 } 00324 00325 template<class T> 00326 PTRcPtr<T>::PTRcPtr(T *p) 00327 { 00328 m_p = new TRcPtr2(p); 00329 } 00330 00331 template<class T> 00332 PTRcPtr<T>::PTRcPtr(const PTRcPtr &r) 00333 { 00334 m_p = r.m_p; 00335 m_p->m_cnt++; 00336 } 00337 00338 template<class T> 00339 const PTRcPtr<T>& 00340 PTRcPtr<T>::operator=(const PTRcPtr &r) 00341 { 00342 if (this != &r) 00343 { 00344 decr(); 00345 m_p = r.m_p; 00346 m_p->m_cnt++; 00347 } 00348 return *this; 00349 } 00350 00351 template<class T> 00352 const PTRcPtr<T>& 00353 PTRcPtr<T>::operator=(T *p) 00354 { 00355 decr(); 00356 m_p = new TRcPtr2(p); 00357 return *this; 00358 } 00359 00360 template<class T> 00361 bool 00362 PTRcPtr<T>::isNull() const 00363 { 00364 return (0 != m_p->mp_dat) ? false : true; 00365 } 00366 00367 template<class T> 00368 T* 00369 PTRcPtr<T>::operator->() 00370 { 00371 if (isNull()) 00372 { 00373 throw TNullPointerException(); 00374 } 00375 return m_p->mp_dat; 00376 } 00377 00378 template<class T> 00379 const T* 00380 PTRcPtr<T>::operator->() const 00381 { 00382 if (isNull()) 00383 { 00384 throw TNullPointerException(); 00385 } 00386 return m_p->mp_dat; 00387 } 00388 00389 template<class T> 00390 PTRcPtr<T>::~PTRcPtr() 00391 { 00392 decr(); 00393 } 00394 00395 template<class T> 00396 void 00397 PTRcPtr<T>::decr() 00398 { 00399 if (true == m_p->decr()) 00400 { 00401 delete m_p; 00402 } 00403 } 00404 } 00405 00406 # undef SET_T 00407 00408 #endif //_xyzzy_refcnt_hxx_