MboRefCntPtr.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Copyright (c) 2001 - 2008 Marcus Boerger.  All rights reserved.
00003 *
00004 * This library is free software; you can redistribute it and/or
00005 * modify it under the terms of the GNU Lesser General Public
00006 * License as published by the Free Software Foundation; either
00007 * version 2.1 of the License, or (at your option) any later version.
00008 *
00009 * This library is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 * Lesser General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU Lesser General Public
00015 * License along with this library; if not, write to the Free Software
00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00017 * ========================================================================= */
00018 
00019 /* ------------------------------------------------------------------------ */
00020 /* Name:      MboRefCntPtr.h
00021  *
00022  * Requires:  
00023  * - Mbo.h
00024  * - MboSynch.h
00025  * - MboSynch.cpp
00026  */
00037 /* ------------------------------------------------------------------------ */
00038 
00039 #ifndef _MBOREFCNTPTR_H_
00040 #define _MBOREFCNTPTR_H_
00041 
00042 #include "Mbo.h"
00043 #include "MboSynch.h"
00044 
00045 #if MBO_USE_DEBUG_NEW
00046 #pragma push_macro("new")
00047 #define new DEBUG_NEW
00048 #endif
00049 
00050 namespace mbo
00051 {
00052 
00053 /* ------------------------------------------------------------------------ */
00065 template <class _Ty, 
00066           class _THREAD_MODEL = ThreadModel
00067          >
00068 struct RefCntRep
00069 {
00073     typedef RefCntRep<_Ty, _THREAD_MODEL>      Rep;
00074 
00077     typedef IncDecVal  refcount_type;
00078 
00081     mutable refcount_type refCnt;
00082 
00085     _Ty* pData;
00086 
00091     inline RefCntRep(_IN _Ty* p = NULL) 
00092         : refCnt(p ? 1 : 0)
00093         , pData(p) 
00094     {
00095     }
00096 
00099     inline RefCntRep& AddRef() 
00100     { 
00101         _THREAD_MODEL::Increment(&refCnt); 
00102         return *this;
00103     }
00104 
00112     inline bool Release() 
00113     { 
00114         return !_THREAD_MODEL::Decrement(&refCnt); 
00115     }
00116 
00122     static Rep* Alloc(_IN _Ty* p) 
00123     { 
00124         return new Rep(p); 
00125     }
00126 
00131     static void Dealloc(_IN Rep *& pRep) 
00132     { 
00133         if (pRep)
00134         {
00135             if (pRep->pData)
00136             {
00137                 delete pRep->pData;
00138             }
00139             delete pRep; 
00140             pRep = 0;
00141         }
00142     }
00143 };
00144 
00150 template <class _Ty>
00151 class NullPointer
00152 {
00153 protected:
00154 
00157     class nullptr_access: public mbo::runtime_error {
00158     public:
00159 
00162         explicit nullptr_access(_IN const char *szWhat = "Null pointer access")
00163             : mbo::runtime_error(szWhat)
00164         {
00165         }
00166     };
00167 
00168 public:
00169 
00173     inline _Ty& operator*()
00174     {
00175         throw nullptr_access();
00176 #if defined(_MSC_VER) && _MSC_VER < 1300
00177         return *((_Ty*)(0));
00178 #endif
00179     }
00180 
00184     inline const _Ty& operator*() const
00185     {
00186         throw nullptr_access();
00187 #if defined(_MSC_VER) && _MSC_VER < 1300
00188         return *((const _Ty*)(0));
00189 #endif
00190     }
00191 
00195     inline operator bool() const
00196     {
00197         return false;
00198     }
00199 };
00200 
00201 template <class _Ty, 
00202           class _THREAD_MODEL,
00203           class _THREAD_MODEL_PTR
00204          >
00205 class RefCntConstPtr;
00206 
00207 template<class ThreadModel1, class ThreadModel2>
00208 struct AutoFastLock
00209 {
00210     typedef typename ThreadModel1::Lock  FastLock;
00211 };
00212 
00213 template<>
00214 struct AutoFastLock<MultiThreadedModel, SingleThreadedModel>
00215 {
00216     typedef CLockFake  FastLock;
00217 };
00218 
00219 template<>
00220 struct AutoFastLock<SingleThreadedModel, MultiThreadedModel>
00221 {
00222     typedef CLockFake  FastLock;
00223 };
00224 
00225 template<>
00226 struct AutoFastLock<SingleThreadedModel, SingleThreadedModel>
00227 {
00228     typedef CLockFake  FastLock;
00229 };
00230 
00231 /* ------------------------------------------------------------------------ */
00301 template <class _Ty, 
00302           class _THREAD_MODEL     = ThreadModel,
00303           class _THREAD_MODEL_PTR = SingleThreadedModel
00304          >
00305 class RefCntPtr: public AutoFastLock<_THREAD_MODEL, _THREAD_MODEL_PTR>
00306 {
00307 public:
00308     typedef _THREAD_MODEL                    ThreadModel;    
00309     typedef _THREAD_MODEL_PTR                ThreadModelPtr; 
00310     typedef _Ty                              Type;           
00311     typedef RefCntRep<_Ty, ThreadModel>      RepType;        
00312     typedef typename RepType::refcount_type  refcount_type;  
00313     typedef NullPointer<_Ty>                 NullPtr;        
00314     typedef typename ThreadModel::Lock       ExtLock;        
00315     typedef typename ThreadModel::CriticalSection CriticalSection;      
00316     typedef RefCntConstPtr<Type, ThreadModel, ThreadModelPtr> ConstPtr; 
00318 protected:
00321     RepType* pRep;
00322 
00325     mutable CriticalSection mx;
00326 
00329     inline void __release()
00330     {
00331         if (pRep && pRep->Release())
00332         {
00333             RepType::Dealloc(pRep); 
00334         }
00335     }
00336 
00337 public:
00338 
00346     inline RefCntPtr(_IN _Ty* p = 0)
00347         : pRep(p ? RepType::Alloc(p) : 0) 
00348     {
00349     }
00350 
00365     template <class _Tx>
00366     inline RefCntPtr(_IN const _Tx& x)
00367         : pRep(RepType::Alloc(new _Tx(x)))
00368     {
00369     }
00370 
00375     inline RefCntPtr(_IN const RefCntPtr& oth)
00376         : pRep(0) 
00377     {   
00378         FastLock lock(&oth.mx);
00379 
00380         pRep = oth.pRep;
00381         if (pRep)
00382         {
00383             pRep->AddRef(); 
00384         }
00385     }
00386 
00395     inline ~RefCntPtr()
00396     { 
00397         FastLock lock(&mx);
00398 
00399         __release();
00400     }                                              
00401 
00407     inline RefCntPtr& operator=(_IN _Ty* p)
00408     {
00409         FastLock lock(&mx);
00410 
00411         if (!pRep || pRep->pData != p)
00412         {
00413             __release();
00414             pRep = p ? RepType::Alloc(p) : 0;
00415         }
00416         return *this;
00417     }
00418 
00432     inline RefCntPtr& __assign(_IN const _Ty & ref)
00433     {
00434         FastLock lock(&mx);
00435 
00436         if (pRep) 
00437         {
00438             if (pRep->pData)
00439             {
00440                 *pRep->pData = ref;
00441             }
00442             else
00443             {
00444                 pRep->pData = new _Ty(ref);
00445             }
00446         }
00447         else
00448         {
00449             pRep = RepType::Alloc(new _Ty(ref));
00450         }
00451         return *this;
00452     }
00453 
00462     inline _Ty & __clone(_IN _OUT _Ty & ref) const
00463     {
00464         FastLock lock(&mx);
00465 
00466         ref = pRep && pRep->pData ? *pRep->pData : *NullPtr();
00467 
00468         return ref;
00469     }
00470 
00476     inline RefCntPtr& operator=(_IN const RefCntPtr& oth)
00477     {
00478         FastLock lock(&mx);
00479 
00480         if (pRep != oth.pRep) 
00481         {
00482             __release();
00483             pRep = oth.pRep; 
00484             if (pRep)
00485             {
00486                 pRep->AddRef();
00487             }
00488         }
00489         return *this;
00490     }
00491 
00492 #if !defined(_MSC_VER) || _MSC_VER >= 1300
00493     typedef const RepType* const RefCntPtr::*unspecified_bool_type;
00494 
00503     inline operator unspecified_bool_type() const
00504     {
00505         FastLock lock(&mx);
00506 
00507         return (pRep != 0 && pRep->pData != 0) ? &RefCntPtr::pRep : 0;
00508     }
00509 #else
00510     inline operator bool() const
00511     {
00512         FastLock lock(&mx);
00513 
00514         return (pRep != 0 && pRep->pData != 0);
00515     }
00516 #endif
00517 
00522     inline refcount_type __referenceCount() const
00523     { 
00524         FastLock lock(&mx);
00525 
00526         return pRep ? pRep->refCnt : 0;
00527     }
00528 
00531     inline ExtLock __getLock() const
00532     {
00533         return ExtLock(&mx);
00534     }
00535 
00536     inline RepType* __getRep()
00537     {
00538         return pRep;
00539     }
00540 
00541     inline const RepType* __getRep() const
00542     {
00543         return pRep;
00544     }
00545 
00553     inline _Ty& operator*()
00554     {
00555         FastLock lock(&mx);
00556 
00557         return pRep && pRep->pData ? *pRep->pData : *NullPtr();
00558     }
00559 
00567     inline const _Ty& operator*() const
00568     { 
00569         FastLock lock(&mx);
00570 
00571         return pRep && pRep->pData ? *pRep->pData : *NullPtr();
00572     }
00573 
00578     inline _Ty* operator->()
00579     { 
00580         FastLock lock(&mx);
00581 
00582         return pRep ? pRep->pData : 0;
00583     }
00584 
00589     inline const _Ty* operator->() const
00590     { 
00591         FastLock lock(&mx);
00592 
00593         return pRep ? pRep->pData : 0;
00594     }
00595 
00596 /*  friend class RefCntPtr<_Ty, _THREAD_MODEL, SingleThreadedModel>;
00597     operator RefCntPtr<_Ty, _THREAD_MODEL, MultiThreadedModel> () const
00598     {
00599         FastLock lock(&mx);
00600 
00601         RefCntPtr<_Ty, _THREAD_MODEL, MultiThreadedModel>  copy;
00602         if (pRep)
00603         {
00604             pRep->AddRef();
00605             copy.pRep = this->pRep;
00606         }
00607         return copy;
00608     }*/
00609 };
00610 
00611 /* ------------------------------------------------------------------------ */
00626 template <class _Ty, 
00627           class _THREAD_MODEL     = ThreadModel,
00628           class _THREAD_MODEL_PTR = SingleThreadedModel
00629          >
00630 class RefCntConstPtr: protected RefCntPtr<_Ty, _THREAD_MODEL, _THREAD_MODEL_PTR>
00631 {
00632 public:
00633 
00634     typedef RefCntPtr<_Ty, _THREAD_MODEL, _THREAD_MODEL_PTR> BaseRefCntPtr;
00635 
00636     using BaseRefCntPtr::ThreadModel;
00637     using BaseRefCntPtr::ThreadModelPtr;
00638     using BaseRefCntPtr::Type;
00639     using BaseRefCntPtr::RepType;
00640     using BaseRefCntPtr::refcount_type;
00641     using BaseRefCntPtr::NullPtr;
00642     using BaseRefCntPtr::CriticalSection;
00643     using BaseRefCntPtr::FastLock;
00644     using BaseRefCntPtr::ExtLock;
00645     using BaseRefCntPtr::ConstPtr;
00646     
00647 public:
00648 
00649     using BaseRefCntPtr::__getLock;
00650     using BaseRefCntPtr::__referenceCount;
00651 
00652     // TODO instead of the 'using' clause EA 6.1.792 requires us to use
00653     // an inline call to the inherited base template class destructor.
00654 #ifndef ENTERPRISE_ARCHITECT
00655 
00656     using BaseRefCntPtr::~RefCntPtr;
00657 
00658 #else
00659 
00660     ~RefCntConstPtr()
00661     {
00662         BaseRefCntPtr::~RefCntPtr();
00663     }
00664 
00665 #endif //ENTERPRISE_ARCHITECT
00666 
00667 #if !defined(_MSC_VER) || _MSC_VER >= 1300
00668     using BaseRefCntPtr::unspecified_bool_type;
00669     inline operator unspecified_bool_type() const
00670     {
00671         FastLock lock(&mx);
00672 
00673         return (pRep != 0 && pRep->pData != 0) ? &RefCntConstPtr::pRep : 0;
00674     }
00675 #else
00676     using BaseRefCntPtr::operator bool;
00677 #endif
00678 
00679     inline const RepType* __getRep() const
00680     {
00681         return pRep;
00682     }
00683 
00688     inline RefCntConstPtr()
00689         : BaseRefCntPtr()
00690     {
00691     }
00692 
00700     inline RefCntConstPtr(_IN const _Ty* p)
00701         : BaseRefCntPtr()
00702     {
00703         operator=(p);
00704     }
00705 
00710     inline RefCntConstPtr(_IN const BaseRefCntPtr& oth)
00711         : BaseRefCntPtr(/*oth*/) 
00712     {
00713         *this = oth;
00714     }
00715 
00720     inline RefCntConstPtr(_IN const RefCntConstPtr& oth)
00721         : BaseRefCntPtr(/*oth*/) 
00722     {   
00723         *this = oth;
00724     }
00725 
00731     inline RefCntConstPtr& operator=(_IN const _Ty* p)
00732     {
00733         FastLock lock(&mx);
00734 
00735         if (!pRep || pRep->pData != p)
00736         {
00737             __release();
00738             pRep = p ? RepType::Alloc(const_cast<_Ty*>(p)) : 0;
00739         }
00740         return *this;
00741     }
00742 
00748     inline RefCntConstPtr& operator=(_IN const BaseRefCntPtr& oth)
00749     {
00750         FastLock lock(&mx);
00751 
00752         if (pRep != oth.__getRep()) 
00753         {
00754             __release();
00755             pRep = const_cast<BaseRefCntPtr&>(oth).__getRep(); 
00756             if (pRep)
00757             {
00758                 pRep->AddRef();
00759             }
00760         }
00761         return *this;
00762     }
00763 
00771     inline const _Ty& operator*() const
00772     { 
00773         FastLock lock(&mx);
00774 
00775         return BaseRefCntPtr::operator*();
00776     }
00777 
00782     inline const _Ty* operator->() const
00783     { 
00784         FastLock lock(&mx);
00785 
00786         return BaseRefCntPtr::operator->();
00787     }
00788 };
00789 
00790 /*
00791 template <class _Ty, 
00792           class _THREAD_MODEL = ThreadModel
00793          >
00794 class RefCntPtr<_Ty, _THREAD_MODEL, SingleThreadedModel>: public RefCntPtr<_Ty, _THREAD_MODEL_PTR, SingleThreadedModel>
00795 {
00796 public:
00797 
00798     operator RefCntPtr<_Ty, _THREAD_MODEL, MultiThreadedModel> ()
00799     {
00800         RefCntPtr<_Ty, _THREAD_MODEL, MultiThreadedModel>  copy;
00801         copy.rep = this->rep;
00802         return copy;
00803     }
00804 };
00805 */
00806 
00822 template <class _Ty, class _THM, class _THM_PTR>
00823 bool operator< (_IN const RefCntPtr<_Ty, _THM, _THM_PTR> & lhs, _IN const RefCntPtr<_Ty, _THM, _THM_PTR> & rhs)
00824 {
00825     return lhs && rhs && *lhs < *rhs;
00826 }
00827 
00843 template <class _Ty, class _THM, class _THM_PTR>
00844 bool operator== (_IN const RefCntPtr<_Ty, _THM, _THM_PTR> & lhs, _IN const RefCntPtr<_Ty, _THM, _THM_PTR> & rhs)
00845 {
00846     return lhs && rhs && *lhs == *rhs;
00847 }
00848 
00864 template <class _Ty, class _THM, class _THM_PTR>
00865 bool operator!= (_IN const RefCntPtr<_Ty, _THM, _THM_PTR> & lhs, _IN const RefCntPtr<_Ty, _THM, _THM_PTR> & rhs)
00866 {
00867     return !lhs || !rhs || *lhs != *rhs;
00868 }
00869 
00870 #if MBO_USE_DEBUG_NEW
00871 #pragma pop_macro("new")
00872 #endif
00873 
00874 }; // namespace mbo
00875 
00876 #endif // _MBOREFCNTPTR_H_

  Hosted on code.google.com  
© Marcus Börger
Generated on Fri Jan 18 21:21:08 2008 for MBO-lib by doxygen 1.5.4