refcnt.hxx

Go to the documentation of this file.
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_

Generated on Thu Mar 22 13:51:08 2007 for anvil by  doxygen 1.5.1