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
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
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
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
00653
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()
00712 {
00713 *this = oth;
00714 }
00715
00720 inline RefCntConstPtr(_IN const RefCntConstPtr& oth)
00721 : BaseRefCntPtr()
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
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
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 };
00875
00876 #endif // _MBOREFCNTPTR_H_