00001 #ifndef CORELIB___NCBIOBJ__HPP
00002 #define CORELIB___NCBIOBJ__HPP
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
00037
00038
00039 #include <corelib/ncbicntr.hpp>
00040 #include <corelib/ncbiatomic.hpp>
00041 #include <corelib/ddumpable.hpp>
00042 #include <typeinfo>
00043
00044
00045
00046 #if defined(NCBI_OS_MSWIN)
00047 # include <corelib/ncbi_os_mswin.hpp>
00048 #endif
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 BEGIN_NCBI_SCOPE
00059
00060 class CObjectMemoryPool;
00061 class CObject;
00062 class CObjectEx;
00063
00064
00065
00066 enum ENull {
00067 null = 0
00068 };
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 class CObjectException : public CCoreException
00082 {
00083 public:
00084
00085 enum EErrCode {
00086 eRefDelete,
00087 eDeleted,
00088 eCorrupted,
00089 eRefOverflow,
00090 eNoRef,
00091 eRefUnref
00092
00093 };
00094
00095
00096 virtual const char* GetErrCodeString(void) const;
00097
00098
00099 NCBI_EXCEPTION_DEFAULT(CObjectException, CCoreException);
00100
00101 protected:
00102 void x_InitErrCode(CException::EErrCode err_code);
00103 };
00104
00105
00106
00107
00108
00109
00110 class CObjectCounterLocker
00111 {
00112 public:
00113
00114 void Lock(const CObject* object) const;
00115
00116
00117
00118
00119 void Relock(const CObject* object) const;
00120
00121
00122
00123 void Unlock(const CObject* object) const;
00124
00125
00126 void UnlockRelease(const CObject* object) const;
00127
00128 static
00129 void ReportIncompatibleType(const type_info& type);
00130 };
00131
00132
00133
00134
00135
00136
00137 template <class C>
00138 class CLockerTraits
00139 {
00140 public:
00141 typedef CObjectCounterLocker TLockerType;
00142 };
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 class CObject : public CDebugDumpable
00155 {
00156 public:
00157
00158 typedef CObjectCounterLocker TLockerType;
00159
00160
00161 CObject(void);
00162
00163
00164
00165 CObject(const CObject& src);
00166
00167
00168
00169 virtual ~CObject(void);
00170
00171
00172 CObject& operator=(const CObject& src) THROWS_NONE;
00173
00174
00175 bool CanBeDeleted(void) const THROWS_NONE;
00176
00177
00178 bool IsAllocatedInPool(void) const THROWS_NONE;
00179
00180
00181 bool Referenced(void) const THROWS_NONE;
00182
00183
00184 bool ReferencedOnlyOnce(void) const THROWS_NONE;
00185
00186
00187 void AddReference(void) const;
00188
00189
00190 void RemoveReference(void) const;
00191
00192
00193
00194 void ReleaseReference(void) const;
00195
00196
00197
00198
00199 virtual void DoNotDeleteThisObject(void);
00200
00201
00202
00203 virtual void DoDeleteThisObject(void);
00204
00205
00206
00207
00208
00209 void* operator new(size_t size);
00210
00211
00212
00213 void* operator new[](size_t size);
00214
00215
00216
00217 void operator delete(void* ptr);
00218
00219
00220
00221 void operator delete[](void* ptr);
00222
00223
00224
00225 void* operator new(size_t size, void* place);
00226
00227
00228
00229 void operator delete(void* ptr, void* place);
00230
00231
00232
00233 void* operator new(size_t size, CObjectMemoryPool* place);
00234
00235
00236
00237 void operator delete(void* ptr, CObjectMemoryPool* place);
00238
00239
00240
00241 virtual void DebugDump(CDebugDumpContext ddc, unsigned int depth) const;
00242
00243
00244
00245
00246
00247
00248 static void ThrowNullPointerException(void);
00249
00250 static void ThrowNullPointerException(const type_info& type);
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 enum EAllocFillMode {
00262 eAllocFillNone = 1,
00263 eAllocFillZero,
00264 eAllocFillPattern
00265 };
00266 static EAllocFillMode GetAllocFillMode(void);
00267 static void SetAllocFillMode(EAllocFillMode mode);
00268
00269 static void SetAllocFillMode(const string& value);
00270
00271 protected:
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 virtual void DeleteThis(void) const;
00282
00283 private:
00284 typedef CAtomicCounter TCounter;
00285 typedef TCounter::TValue TCount;
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 enum EObjectState {
00309 eStateBitsInHeap = 1 << 0,
00310 eStateBitsHeapSignature = 1 << 1,
00311
00312
00313 eStateBitsInHeapMask = eStateBitsInHeap | eStateBitsHeapSignature,
00314
00315 #ifdef NCBI_COUNTER_UNSIGNED
00316
00317 eStateBitsValid = (unsigned int)(1 << (sizeof(TCount) * 8 - 1)),
00318 #else
00319
00320 eStateBitsValid = (unsigned int)(1 << (sizeof(TCount) * 8 - 2)),
00321 #endif
00322
00323 eStateMask = eStateBitsValid | eStateBitsInHeapMask,
00324
00325
00326 eCounterStep = 1 << 2,
00327
00328
00329 eCounterValid = eStateBitsValid,
00330
00331
00332 eCounterValidRef1 = eCounterValid + eCounterStep,
00333
00334
00335 eCounterValidRef2 = eCounterValid + eCounterStep*2,
00336
00337
00338 eInitCounterNotInHeap = eStateBitsValid,
00339
00340
00341 eInitCounterInHeap = eStateBitsValid | eStateBitsHeapSignature |
00342 eStateBitsInHeap,
00343
00344
00345 eInitCounterInPool = eStateBitsValid | eStateBitsInHeap,
00346
00347
00348 eInitCounterInStack = eStateBitsValid | eStateBitsHeapSignature,
00349
00350
00351
00352 eMagicCounterDeleted = 0x5b4d9f34 & ~eStateMask,
00353
00354
00355 eMagicCounterNew = 0x3423cb13 & ~eStateMask,
00356
00357
00358 eMagicCounterPoolDeleted= 0x4229775b & ~eStateMask,
00359
00360
00361 eMagicCounterPoolNew = 0x54917ec2 & ~eStateMask
00362 };
00363 friend class CObjectMemoryPool;
00364 friend class CObjectEx;
00365
00366
00367
00368
00369 static bool ObjectStateValid(TCount count);
00370
00371
00372 static bool ObjectStateCanBeDeleted(TCount count);
00373
00374
00375 static bool ObjectStateIsAllocatedInPool(TCount count);
00376
00377
00378 static bool ObjectStateUnreferenced(TCount count);
00379
00380
00381 static bool ObjectStateReferenced(TCount count);
00382
00383
00384 static bool ObjectStateReferencedOnlyOnce(TCount count);
00385
00386
00387 void InitCounter(void);
00388
00389
00390
00391 void RemoveLastReference(TCount count) const;
00392
00393
00394
00395
00396
00397
00398 void InvalidObject(void) const;
00399
00400
00401
00402 void CheckReferenceOverflow(TCount count) const;
00403
00404 mutable TCounter m_Counter;
00405 };
00406
00407
00408
00409
00410
00411
00412
00413 inline
00414 bool CObject::ObjectStateCanBeDeleted(TCount count)
00415 {
00416 return (count & eStateBitsInHeap) != 0;
00417 }
00418
00419
00420 inline
00421 bool CObject::ObjectStateIsAllocatedInPool(TCount count)
00422 {
00423 return (count & eStateBitsInHeapMask) ==
00424 (eInitCounterInPool & eStateBitsInHeapMask);
00425 }
00426
00427
00428 inline
00429 bool CObject::ObjectStateValid(TCount count)
00430 {
00431 return count >= TCount(eCounterValid);
00432 }
00433
00434
00435 inline
00436 bool CObject::ObjectStateReferenced(TCount count)
00437 {
00438 return count >= TCount(eCounterValidRef1);
00439 }
00440
00441
00442 inline
00443 bool CObject::ObjectStateUnreferenced(TCount count)
00444 {
00445 return (count & ~eStateBitsInHeapMask) == TCount(eCounterValid);
00446 }
00447
00448
00449 inline
00450 bool CObject::ObjectStateReferencedOnlyOnce(TCount count)
00451 {
00452 return (count & ~eStateBitsInHeapMask) == TCount(eCounterValidRef1);
00453 }
00454
00455
00456 inline
00457 bool CObject::CanBeDeleted(void) const THROWS_NONE
00458 {
00459 return ObjectStateCanBeDeleted(m_Counter.Get());
00460 }
00461
00462
00463 inline
00464 bool CObject::IsAllocatedInPool(void) const THROWS_NONE
00465 {
00466 return ObjectStateIsAllocatedInPool(m_Counter.Get());
00467 }
00468
00469
00470 inline
00471 bool CObject::Referenced(void) const THROWS_NONE
00472 {
00473 return ObjectStateReferenced(m_Counter.Get());
00474 }
00475
00476
00477 inline
00478 bool CObject::ReferencedOnlyOnce(void) const THROWS_NONE
00479 {
00480 return ObjectStateReferencedOnlyOnce(m_Counter.Get());
00481 }
00482
00483
00484 inline
00485 CObject& CObject::operator=(const CObject& ) THROWS_NONE
00486 {
00487 return *this;
00488 }
00489
00490
00491 inline
00492 void CObject::AddReference(void) const
00493 {
00494 TCount newCount = m_Counter.Add(eCounterStep);
00495 if ( !ObjectStateReferenced(newCount) ) {
00496 m_Counter.Add(-eCounterStep);
00497 CheckReferenceOverflow(newCount - eCounterStep);
00498 }
00499 }
00500
00501
00502 inline
00503 void CObject::RemoveReference(void) const
00504 {
00505 TCount newCount = m_Counter.Add(-eCounterStep);
00506 if ( !ObjectStateReferenced(newCount) ) {
00507 RemoveLastReference(newCount);
00508 }
00509 }
00510
00511
00512
00513
00514
00515
00516 inline
00517 void CObjectCounterLocker::Lock(const CObject* object) const
00518 {
00519 object->AddReference();
00520 }
00521
00522
00523 inline
00524 void CObjectCounterLocker::Relock(const CObject* object) const
00525 {
00526 Lock(object);
00527 }
00528
00529
00530 inline
00531 void CObjectCounterLocker::Unlock(const CObject* object) const
00532 {
00533 object->RemoveReference();
00534 }
00535
00536
00537 inline
00538 void CObjectCounterLocker::UnlockRelease(const CObject* object) const
00539 {
00540 object->ReleaseReference();
00541 }
00542
00543
00544
00545
00546
00547
00548 template<class Interface>
00549 class CInterfaceObjectLocker
00550 {
00551 public:
00552 void Lock(const Interface* object) const
00553 {
00554 const CObject* cobject = dynamic_cast<const CObject*>(object);
00555 if ( !cobject ) {
00556 CObjectCounterLocker::ReportIncompatibleType(typeid(*object));
00557 }
00558 cobject->AddReference();
00559 }
00560
00561 void Relock(const Interface* object) const
00562 {
00563 const CObject* cobject = dynamic_cast<const CObject*>(object);
00564 _ASSERT(cobject);
00565 cobject->AddReference();
00566 }
00567
00568 void Unlock(const Interface* object) const
00569 {
00570 const CObject* cobject = dynamic_cast<const CObject*>(object);
00571 _ASSERT(cobject);
00572 cobject->RemoveReference();
00573 }
00574
00575 void UnlockRelease(const Interface* object) const
00576 {
00577 const CObject* cobject = dynamic_cast<const CObject*>(object);
00578 _ASSERT(cobject);
00579 cobject->ReleaseReference();
00580 }
00581 };
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 template<class C, class Locker = typename CLockerTraits<C>::TLockerType>
00592 class CRef {
00593 public:
00594 typedef C element_type;
00595 typedef element_type TObjectType;
00596 typedef Locker locker_type;
00597 typedef CRef<C, Locker> TThisType;
00598
00599
00600 inline
00601 CRef(void) THROWS_NONE
00602 {
00603 }
00604
00605
00606 inline
00607 CRef(ENull ) THROWS_NONE
00608 {
00609 }
00610
00611
00612 explicit CRef(TObjectType* ptr)
00613 {
00614 if ( ptr ) {
00615 m_Data.first().Lock(ptr);
00616 m_Data.second() = ptr;
00617 }
00618 }
00619
00620
00621 CRef(TObjectType* ptr, const locker_type& locker_value)
00622 : m_Data(locker_value, 0)
00623 {
00624 if ( ptr ) {
00625 m_Data.first().Lock(ptr);
00626 m_Data.second() = ptr;
00627 }
00628 }
00629
00630
00631 CRef(const TThisType& ref)
00632 : m_Data(ref.GetLocker(), 0)
00633 {
00634 TObjectType* newPtr = ref.GetNCPointerOrNull();
00635 if ( newPtr ) {
00636 m_Data.first().Relock(newPtr);
00637 m_Data.second() = newPtr;
00638 }
00639 }
00640
00641
00642 ~CRef(void)
00643 {
00644 Reset();
00645 }
00646
00647
00648 const locker_type& GetLocker(void) const
00649 {
00650 return m_Data.first();
00651 }
00652
00653
00654
00655
00656
00657
00658 bool operator!(void) const THROWS_NONE
00659 {
00660 return m_Data.second() == 0;
00661 }
00662
00663
00664
00665
00666
00667
00668 bool Empty(void) const THROWS_NONE
00669 {
00670 return m_Data.second() == 0;
00671 }
00672
00673
00674
00675 bool NotEmpty(void) const THROWS_NONE
00676 {
00677 return m_Data.second() != 0;
00678 }
00679
00680
00681
00682
00683
00684 bool IsNull(void) const THROWS_NONE
00685 {
00686 return m_Data.second() == 0;
00687 }
00688
00689
00690
00691
00692
00693 bool NotNull(void) const THROWS_NONE
00694 {
00695 return m_Data.second() != 0;
00696 }
00697
00698
00699
00700
00701
00702 inline
00703 void Swap(TThisType& ref)
00704 {
00705 swap(m_Data, ref.m_Data);
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715 inline
00716 void Reset(void)
00717 {
00718 TObjectType* ptr = m_Data.second();
00719 if ( ptr ) {
00720 m_Data.second() = 0;
00721 m_Data.first().Unlock(ptr);
00722 }
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732 inline
00733 void Reset(TObjectType* newPtr)
00734 {
00735 TObjectType* oldPtr = m_Data.second();
00736 if ( newPtr != oldPtr ) {
00737 if ( newPtr ) {
00738 m_Data.first().Lock(newPtr);
00739 }
00740 m_Data.second() = newPtr;
00741 if ( oldPtr ) {
00742 m_Data.first().Unlock(oldPtr);
00743 }
00744 }
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 inline
00759 TObjectType* ReleaseOrNull(void)
00760 {
00761 TObjectType* ptr = m_Data.second();
00762 if ( !ptr ) {
00763 return 0;
00764 }
00765 m_Data.second() = 0;
00766 m_Data.first().UnlockRelease(ptr);
00767 return ptr;
00768 }
00769
00770 static void ThrowNullPointerException(void)
00771 {
00772 CObject::ThrowNullPointerException();
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 inline
00788 TObjectType* Release(void)
00789 {
00790 TObjectType* ptr = m_Data.second();
00791 if ( ptr ) {
00792 m_Data.second() = 0;
00793 m_Data.first().UnlockRelease(ptr);
00794 return ptr;
00795 }
00796 else {
00797 ThrowNullPointerException();
00798 return ptr;
00799 }
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 inline
00814 void AtomicResetFrom(const TThisType& ref)
00815 {
00816 TObjectType* ptr = ref.m_Data.second();
00817 if ( ptr )
00818 m_Data.first().Lock(ptr);
00819 TObjectType* old_ptr = AtomicSwap(ptr);
00820 if ( old_ptr )
00821 m_Data.first().Unlock(old_ptr);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 inline
00835 void AtomicReleaseTo(TThisType& ref)
00836 {
00837 TObjectType* old_ptr = AtomicSwap(0);
00838 if ( old_ptr ) {
00839 ref.Reset(old_ptr);
00840 m_Data.first().Unlock(old_ptr);
00841 }
00842 else {
00843 ref.Reset();
00844 }
00845 }
00846
00847
00848 TThisType& operator=(const TThisType& ref)
00849 {
00850 Reset(ref.m_Data.second());
00851 return *this;
00852 }
00853
00854
00855
00856 TThisType& operator=(TObjectType* ptr)
00857 {
00858 Reset(ptr);
00859 return *this;
00860 }
00861
00862
00863 TThisType& operator=(ENull )
00864 {
00865 Reset();
00866 return *this;
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 inline
00879 TObjectType* GetNonNullPointer(void)
00880 {
00881 TObjectType* ptr = m_Data.second();
00882 if ( !ptr ) {
00883 ThrowNullPointerException();
00884 }
00885 return ptr;
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896 inline
00897 TObjectType* GetPointerOrNull(void) THROWS_NONE
00898 {
00899 return m_Data.second();
00900 }
00901
00902
00903
00904
00905
00906
00907
00908 inline
00909 TObjectType* GetPointer(void) THROWS_NONE
00910 {
00911 return GetPointerOrNull();
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921 inline
00922 TObjectType& GetObject(void)
00923 {
00924 return *GetNonNullPointer();
00925 }
00926
00927
00928
00929
00930
00931 inline
00932 TObjectType& operator*(void)
00933 {
00934 return *GetNonNullPointer();
00935 }
00936
00937
00938
00939
00940
00941 inline
00942 TObjectType* operator->(void)
00943 {
00944 return GetNonNullPointer();
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 const TObjectType* GetNonNullPointer(void) const
00959 {
00960 const TObjectType* ptr = m_Data.second();
00961 if ( !ptr ) {
00962 ThrowNullPointerException();
00963 }
00964 return ptr;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 const TObjectType* GetPointerOrNull(void) const THROWS_NONE
00976 {
00977 return m_Data.second();
00978 }
00979
00980
00981
00982
00983
00984
00985
00986 inline
00987 const TObjectType* GetPointer(void) const THROWS_NONE
00988 {
00989 return GetPointerOrNull();
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999 inline
01000 const TObjectType& GetObject(void) const
01001 {
01002 return *GetNonNullPointer();
01003 }
01004
01005
01006
01007
01008
01009 inline
01010 const TObjectType& operator*(void) const
01011 {
01012 return *GetNonNullPointer();
01013 }
01014
01015
01016
01017
01018
01019 inline
01020 const TObjectType* operator->(void) const
01021 {
01022 return GetNonNullPointer();
01023 }
01024
01025
01026
01027
01028
01029 inline
01030 operator TObjectType*(void)
01031 {
01032 return GetPointerOrNull();
01033 }
01034
01035
01036
01037
01038
01039 inline
01040 operator const TObjectType*(void) const
01041 {
01042 return GetPointerOrNull();
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 inline
01055 TObjectType* GetNonNullNCPointer(void) const
01056 {
01057 TObjectType* ptr = m_Data.second();
01058 if ( !ptr ) {
01059 ThrowNullPointerException();
01060 }
01061 return ptr;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 inline
01073 TObjectType* GetNCPointerOrNull(void) const THROWS_NONE
01074 {
01075 return m_Data.second();
01076 }
01077
01078
01079
01080
01081
01082
01083
01084 inline
01085 TObjectType* GetNCPointer(void) const THROWS_NONE
01086 {
01087 return GetNCPointerOrNull();
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097 inline
01098 TObjectType& GetNCObject(void) const
01099 {
01100 return *GetNonNullNCPointer();
01101 }
01102
01103 private:
01104 TObjectType* AtomicSwap(TObjectType* ptr)
01105 {
01106
01107 return reinterpret_cast<TObjectType*>
01108 (SwapPointers(const_cast<void*volatile*>(
01109 reinterpret_cast<void**>(&m_Data.second())),
01110 ptr));
01111 }
01112
01113 pair_base_member<locker_type, TObjectType*> m_Data;
01114
01115 private:
01116
01117 void operator-(TObjectType*) const;
01118 void operator-(int) const;
01119 void operator+(int) const;
01120 };
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 template<class C, class Locker = CObjectCounterLocker>
01131 class CConstRef {
01132 public:
01133 typedef C element_type;
01134 typedef const element_type TObjectType;
01135 typedef Locker locker_type;
01136 typedef CConstRef<C, Locker> TThisType;
01137
01138
01139 inline
01140 CConstRef(void) THROWS_NONE
01141 {
01142 }
01143
01144
01145 inline
01146 CConstRef(ENull ) THROWS_NONE
01147 {
01148 }
01149
01150
01151 explicit CConstRef(TObjectType* ptr)
01152 {
01153 if ( ptr ) {
01154 m_Data.first().Lock(ptr);
01155 m_Data.second() = ptr;
01156 }
01157 }
01158
01159
01160 CConstRef(TObjectType* ptr, const locker_type& locker_value)
01161 : m_Data(locker_value, 0)
01162 {
01163 if ( ptr ) {
01164 m_Data.first().Lock(ptr);
01165 m_Data.second() = ptr;
01166 }
01167 }
01168
01169
01170 CConstRef(const TThisType& ref)
01171 : m_Data(ref.GetLocker(), 0)
01172 {
01173 TObjectType* newPtr = ref.GetPointerOrNull();
01174 if ( newPtr ) {
01175 m_Data.first().Relock(newPtr);
01176 m_Data.second() = newPtr;
01177 }
01178 }
01179
01180
01181 CConstRef(const CRef<C, Locker>& ref)
01182 : m_Data(ref.GetLocker(), 0)
01183 {
01184 TObjectType* newPtr = ref.GetPointerOrNull();
01185 if ( newPtr ) {
01186 m_Data.first().Relock(newPtr);
01187 m_Data.second() = newPtr;
01188 }
01189 }
01190
01191
01192 ~CConstRef(void)
01193 {
01194 Reset();
01195 }
01196
01197
01198 const locker_type& GetLocker(void) const
01199 {
01200 return m_Data.first();
01201 }
01202
01203
01204
01205
01206
01207
01208 bool operator!(void) const THROWS_NONE
01209 {
01210 return m_Data.second() == 0;
01211 }
01212
01213
01214
01215
01216
01217
01218 bool Empty(void) const THROWS_NONE
01219 {
01220 return m_Data.second() == 0;
01221 }
01222
01223
01224
01225 bool NotEmpty(void) const THROWS_NONE
01226 {
01227 return m_Data.second() != 0;
01228 }
01229
01230
01231
01232
01233
01234 bool IsNull(void) const THROWS_NONE
01235 {
01236 return m_Data.second() == 0;
01237 }
01238
01239
01240
01241
01242
01243 bool NotNull(void) const THROWS_NONE
01244 {
01245 return m_Data.second() != 0;
01246 }
01247
01248
01249
01250
01251
01252 inline
01253 void Swap(TThisType& ref)
01254 {
01255 swap(m_Data, ref.m_Data);
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265 inline
01266 void Reset(void)
01267 {
01268 TObjectType* ptr = m_Data.second();
01269 if ( ptr ) {
01270 m_Data.second() = 0;
01271 m_Data.first().Unlock(ptr);
01272 }
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282 inline
01283 void Reset(TObjectType* newPtr)
01284 {
01285 TObjectType* oldPtr = m_Data.second();
01286 if ( newPtr != oldPtr ) {
01287 if ( newPtr ) {
01288 m_Data.first().Lock(newPtr);
01289 }
01290 m_Data.second() = newPtr;
01291 if ( oldPtr ) {
01292 m_Data.first().Unlock(oldPtr);
01293 }
01294 }
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 inline
01309 TObjectType* ReleaseOrNull(void)
01310 {
01311 TObjectType* ptr = m_Data.second();
01312 if ( !ptr ) {
01313 return 0;
01314 }
01315 m_Data.second() = 0;
01316 m_Data.first().UnlockRelease(ptr);
01317 return ptr;
01318 }
01319
01320 static void ThrowNullPointerException(void)
01321 {
01322 CObject::ThrowNullPointerException();
01323 }
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337 inline
01338 TObjectType* Release(void)
01339 {
01340 TObjectType* ptr = m_Data.second();
01341 if ( ptr ) {
01342 m_Data.second() = 0;
01343 m_Data.first().UnlockRelease(ptr);
01344 return ptr;
01345 }
01346 else {
01347 ThrowNullPointerException();
01348 return ptr;
01349 }
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 inline
01364 void AtomicResetFrom(const CConstRef& ref)
01365 {
01366 TObjectType* ptr = ref.m_Data.second();
01367 if ( ptr )
01368 m_Data.first().Lock(ptr);
01369 TObjectType* old_ptr = AtomicSwap(ptr);
01370 if ( old_ptr )
01371 m_Data.first().Unlock(old_ptr);
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 inline
01385 void AtomicReleaseTo(CConstRef& ref)
01386 {
01387 TObjectType* old_ptr = AtomicSwap(0);
01388 if ( old_ptr ) {
01389 ref.Reset(old_ptr);
01390 m_Data.first().Unlock(old_ptr);
01391 }
01392 else {
01393 ref.Reset();
01394 }
01395 }
01396
01397
01398 TThisType& operator=(const TThisType& ref)
01399 {
01400 Reset(ref.m_Data.second());
01401 return *this;
01402 }
01403
01404
01405 TThisType& operator=(const CRef<C, Locker>& ref)
01406 {
01407 Reset(ref.GetPointerOrNull());
01408 return *this;
01409 }
01410
01411
01412
01413 TThisType& operator=(TObjectType* ptr)
01414 {
01415 Reset(ptr);
01416 return *this;
01417 }
01418
01419
01420 TThisType& operator=(ENull )
01421 {
01422 Reset();
01423 return *this;
01424 }
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 inline
01436 TObjectType* GetNonNullPointer(void) const
01437 {
01438 TObjectType* ptr = m_Data.second();
01439 if ( !ptr ) {
01440 ThrowNullPointerException();
01441 }
01442 return ptr;
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 inline
01454 TObjectType* GetPointerOrNull(void) const THROWS_NONE
01455 {
01456 return m_Data.second();
01457 }
01458
01459
01460
01461
01462
01463
01464
01465 inline
01466 TObjectType* GetPointer(void) const THROWS_NONE
01467 {
01468 return GetPointerOrNull();
01469 }
01470
01471
01472
01473
01474
01475
01476
01477
01478 inline
01479 TObjectType& GetObject(void) const
01480 {
01481 return *GetNonNullPointer();
01482 }
01483
01484
01485
01486
01487
01488 inline
01489 TObjectType& operator*(void) const
01490 {
01491 return *GetNonNullPointer();
01492 }
01493
01494
01495
01496
01497
01498 inline
01499 TObjectType* operator->(void) const
01500 {
01501 return GetNonNullPointer();
01502 }
01503
01504
01505
01506
01507
01508 inline
01509 operator TObjectType*(void) const
01510 {
01511 return GetPointerOrNull();
01512 }
01513
01514 private:
01515 TObjectType* AtomicSwap(TObjectType* ptr)
01516 {
01517
01518 return reinterpret_cast<TObjectType*>
01519 (SwapPointers(const_cast<void*volatile*>(
01520 const_cast<void**>(
01521 reinterpret_cast<const void**>(&m_Data.second()))),
01522 const_cast<C*>(ptr)));
01523 }
01524
01525 pair_base_member<locker_type, TObjectType*> m_Data;
01526
01527 private:
01528
01529 void operator-(TObjectType*) const;
01530 void operator-(int) const;
01531 void operator+(int) const;
01532 };
01533
01534
01535
01536
01537
01538
01539 template<class T, class L>
01540 inline
01541 bool operator== (const CRef<T,L>& r1, ENull )
01542 {
01543 return r1.IsNull();
01544 }
01545
01546
01547 template<class T, class L>
01548 inline
01549 bool operator== (ENull , const CRef<T,L>& r1)
01550 {
01551 return r1.IsNull();
01552 }
01553
01554
01555 template<class T, class L>
01556 inline
01557 bool operator!= (const CRef<T,L>& r1, ENull )
01558 {
01559 return !r1.IsNull();
01560 }
01561
01562
01563 template<class T, class L>
01564 inline
01565 bool operator!= (ENull , const CRef<T,L>& r1)
01566 {
01567 return !r1.IsNull();
01568 }
01569
01570
01571 template<class T, class L>
01572 inline
01573 bool operator== (const CConstRef<T,L>& r1, ENull )
01574 {
01575 return r1.IsNull();
01576 }
01577
01578
01579 template<class T, class L>
01580 inline
01581 bool operator== (ENull , const CConstRef<T,L>& r1)
01582 {
01583 return r1.IsNull();
01584 }
01585
01586
01587 template<class T, class L>
01588 inline
01589 bool operator!= (const CConstRef<T,L>& r1, ENull )
01590 {
01591 return !r1.IsNull();
01592 }
01593
01594
01595 template<class T, class L>
01596 inline
01597 bool operator!= (ENull , const CConstRef<T,L>& r1)
01598 {
01599 return !r1.IsNull();
01600 }
01601
01602
01603 #if defined(NCBI_COMPILER_WORKSHOP)
01604
01605
01606
01607
01608
01609 template<class T, class L>
01610 inline
01611 bool operator< (const CRef<T,L>& r1, const CRef<T,L>& r2)
01612 {
01613 return r1.GetPointerOrNull() < r2.GetPointerOrNull();
01614 }
01615
01616
01617 template<class T, class L>
01618 inline
01619 bool operator> (const CRef<T,L>& r1, const CRef<T,L>& r2)
01620 {
01621 return r1.GetPointerOrNull() > r2.GetPointerOrNull();
01622 }
01623
01624
01625 template<class T, class L>
01626 inline
01627 bool operator<= (const CRef<T,L>& r1, const CRef<T,L>& r2)
01628 {
01629 return r1.GetPointerOrNull() <= r2.GetPointerOrNull();
01630 }
01631
01632
01633 template<class T, class L>
01634 inline
01635 bool operator>= (const CRef<T,L>& r1, const CRef<T,L>& r2)
01636 {
01637 return r1.GetPointerOrNull() >= r2.GetPointerOrNull();
01638 }
01639
01640
01641 template<class T, class L>
01642 inline
01643 bool operator== (const CRef<T,L>& r1, const CRef<T,L>& r2)
01644 {
01645 return r1.GetPointerOrNull() == r2.GetPointerOrNull();
01646 }
01647
01648
01649 template<class T, class L>
01650 inline
01651 bool operator!= (const CRef<T,L>& r1, const CRef<T,L>& r2)
01652 {
01653 return r1.GetPointerOrNull() != r2.GetPointerOrNull();
01654 }
01655
01656
01657
01658
01659
01660 template<class T, class L>
01661 inline
01662 bool operator< (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01663 {
01664 return r1.GetPointerOrNull() < r2.GetPointerOrNull();
01665 }
01666
01667
01668 template<class T, class L>
01669 inline
01670 bool operator> (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01671 {
01672 return r1.GetPointerOrNull() > r2.GetPointerOrNull();
01673 }
01674
01675
01676 template<class T, class L>
01677 inline
01678 bool operator<= (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01679 {
01680 return r1.GetPointerOrNull() <= r2.GetPointerOrNull();
01681 }
01682
01683
01684 template<class T, class L>
01685 inline
01686 bool operator>= (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01687 {
01688 return r1.GetPointerOrNull() >= r2.GetPointerOrNull();
01689 }
01690
01691
01692 template<class T, class L>
01693 inline
01694 bool operator== (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01695 {
01696 return r1.GetPointerOrNull() == r2.GetPointerOrNull();
01697 }
01698
01699
01700 template<class T, class L>
01701 inline
01702 bool operator!= (const CConstRef<T,L>& r1, const CConstRef<T,L>& r2)
01703 {
01704 return r1.GetPointerOrNull() != r2.GetPointerOrNull();
01705 }
01706
01707
01708
01709
01710
01711
01712 template<class T, class L>
01713 inline
01714 bool operator== (const CConstRef<T,L>& r1, const CRef<T,L>& r2)
01715 {
01716 return r1.GetPointerOrNull() == r2.GetPointerOrNull();
01717 }
01718
01719
01720 template<class T, class L>
01721 inline
01722 bool operator== (const CRef<T,L>& r1, const CConstRef<T,L>& r2)
01723 {
01724 return r1.GetPointerOrNull() == r2.GetPointerOrNull();
01725 }
01726
01727
01728 template<class T, class L>
01729 inline
01730 bool operator!= (const CConstRef<T,L>& r1, const CRef<T,L>& r2)
01731 {
01732 return r1.GetPointerOrNull() != r2.GetPointerOrNull();
01733 }
01734
01735
01736 template<class T, class L>
01737 inline
01738 bool operator!= (const CRef<T,L>& r1, const CConstRef<T,L>& r2)
01739 {
01740 return r1.GetPointerOrNull() != r2.GetPointerOrNull();
01741 }
01742 #endif
01743
01744
01745
01746
01747
01748
01749 template<class C>
01750 inline
01751 CRef<C> Ref(C* object)
01752 {
01753 return CRef<C>(object);
01754 }
01755
01756
01757
01758 template<class C>
01759 inline
01760 CConstRef<C> ConstRef(const C* object)
01761 {
01762 return CConstRef<C>(object);
01763 }
01764
01765
01766
01767 template<class Interface, class Locker = CInterfaceObjectLocker<Interface> >
01768 class CIRef : public CRef<Interface, Locker>
01769 {
01770 typedef CRef<Interface, Locker> TParent;
01771 public:
01772 typedef typename TParent::TObjectType TObjectType;
01773 typedef typename TParent::locker_type locker_type;
01774 typedef CIRef<Interface, Locker> TThisType;
01775
01776
01777
01778 CIRef(void) THROWS_NONE
01779 {
01780 }
01781
01782
01783 CIRef(ENull ) THROWS_NONE
01784 {
01785 }
01786
01787
01788 explicit CIRef(TObjectType* ptr)
01789 : TParent(ptr)
01790 {
01791 }
01792
01793
01794 CIRef(TObjectType* ptr, const locker_type& locker_value)
01795 : TParent(ptr, locker_value)
01796 {
01797 }
01798
01799
01800 TThisType& operator=(const TThisType& ref)
01801 {
01802 TParent::operator=(ref);
01803 return *this;
01804 }
01805
01806
01807
01808 TThisType& operator=(TObjectType* ptr)
01809 {
01810 TParent::operator=(ptr);
01811 return *this;
01812 }
01813
01814
01815 TThisType& operator=(ENull null)
01816 {
01817 TParent::operator=(null);
01818 return *this;
01819 }
01820 };
01821
01822
01823 template<class Interface, class Locker = CInterfaceObjectLocker<Interface> >
01824 class CConstIRef : public CConstRef<Interface, Locker>
01825 {
01826 typedef CConstRef<Interface, Locker> TParent;
01827 public:
01828 typedef typename TParent::TObjectType TObjectType;
01829 typedef typename TParent::locker_type locker_type;
01830 typedef CConstIRef<Interface, Locker> TThisType;
01831
01832
01833
01834 CConstIRef(void) THROWS_NONE
01835 {
01836 }
01837
01838
01839 CConstIRef(ENull ) THROWS_NONE
01840 {
01841 }
01842
01843
01844 explicit CConstIRef(TObjectType* ptr)
01845 : TParent(ptr)
01846 {
01847 }
01848
01849
01850 CConstIRef(TObjectType* ptr, const locker_type& locker_value)
01851 : TParent(ptr, locker_value)
01852 {
01853 }
01854
01855
01856 CConstIRef(const CIRef<Interface, Locker>& ref)
01857 : TParent(ref)
01858 {
01859 }
01860
01861
01862 TThisType& operator=(const TThisType& ref)
01863 {
01864 TParent::operator=(ref);
01865 return *this;
01866 }
01867
01868
01869 TThisType& operator=(const CIRef<Interface, Locker>& ref)
01870 {
01871 TParent::operator=(ref);
01872 return *this;
01873 }
01874
01875
01876
01877 TThisType& operator=(TObjectType* ptr)
01878 {
01879 TParent::operator=(ptr);
01880 return *this;
01881 }
01882
01883
01884 TThisType& operator=(ENull null)
01885 {
01886 TParent::operator=(null);
01887 return *this;
01888 }
01889 };
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906 template<typename T>
01907 class CObjectFor : public CObject
01908 {
01909 public:
01910 typedef T TObjectType;
01911
01912 CObjectFor(void)
01913 {
01914 }
01915
01916 explicit CObjectFor(const TObjectType& data)
01917 : m_Data(data)
01918 {
01919 }
01920
01921
01922 T& GetData(void)
01923 {
01924 return m_Data;
01925 }
01926
01927
01928 const T& GetData(void) const
01929 {
01930 return m_Data;
01931 }
01932
01933
01934
01935
01936
01937 operator T& (void)
01938 {
01939 return GetData();
01940 }
01941
01942
01943
01944
01945
01946 operator const T& (void) const
01947 {
01948 return GetData();
01949 }
01950
01951
01952 T& operator=(const T& data)
01953 {
01954 m_Data = data;
01955 return *this;
01956 }
01957
01958 private:
01959 T m_Data;
01960 };
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972 class CPtrToObjectExProxy : public CObject
01973 {
01974 public:
01975 CPtrToObjectExProxy(CObjectEx* ptr);
01976
01977
01978 ~CPtrToObjectExProxy(void);
01979
01980
01981 void Clear(void);
01982
01983
01984
01985
01986 CObjectEx* GetLockedObject(void);
01987
01988
01989
01990 static void ReportIncompatibleType(const type_info& type);
01991
01992 private:
01993 CObjectEx* m_Ptr;
01994 };
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012 class CObjectEx : public CObject
02013 {
02014 public:
02015
02016 CObjectEx(void);
02017
02018
02019 virtual ~CObjectEx(void);
02020
02021
02022 CPtrToObjectExProxy* GetPtrProxy(void) const;
02023
02024 protected:
02025
02026
02027
02028
02029
02030
02031
02032
02033 void CleanWeakRefs(void) const;
02034
02035 private:
02036
02037
02038
02039 bool WeakAddReference(void);
02040
02041 friend class CPtrToObjectExProxy;
02042
02043
02044
02045 mutable CRef<CPtrToObjectExProxy> m_SelfPtrProxy;
02046 };
02047
02048
02049
02050
02051
02052 inline
02053 CPtrToObjectExProxy* CObjectEx::GetPtrProxy(void) const
02054 {
02055 return m_SelfPtrProxy.GetNCPointer();
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066 template <class C>
02067 class CWeakObjectExLocker : public CObjectCounterLocker
02068 {
02069 public:
02070
02071 typedef CPtrToObjectExProxy TPtrProxyType;
02072
02073 typedef CWeakObjectExLocker<C> TThisType;
02074
02075
02076 TPtrProxyType* GetPtrProxy(C* object) const
02077 {
02078 return object->GetPtrProxy();
02079 }
02080
02081
02082
02083 CRef<C, TThisType> GetLockedObject(TPtrProxyType* proxy) const
02084 {
02085 CRef<C, TThisType> ref(
02086 static_cast<C*>(proxy->GetLockedObject()), *this);
02087 if (ref.NotNull()) {
02088 Unlock(ref.GetPointer());
02089 }
02090 return ref;
02091 }
02092 };
02093
02094
02095
02096
02097
02098
02099
02100
02101 template <class Interface>
02102 class CWeakInterfaceLocker : public CInterfaceObjectLocker<Interface>
02103 {
02104 public:
02105
02106 typedef CPtrToObjectExProxy TPtrProxyType;
02107
02108 typedef CWeakInterfaceLocker<Interface> TThisType;
02109
02110
02111 TPtrProxyType* GetPtrProxy(Interface* ptr) const
02112 {
02113 CObjectEx* object = dynamic_cast<CObjectEx*>(ptr);
02114 if (!object) {
02115 CPtrToObjectExProxy::ReportIncompatibleType(typeid(*object));
02116 }
02117 return object->GetPtrProxy();
02118 }
02119
02120
02121
02122 CIRef<Interface, TThisType> GetLockedObject(TPtrProxyType* proxy) const
02123 {
02124
02125
02126
02127
02128 CIRef<Interface, TThisType> ref(
02129 dynamic_cast<Interface*>(proxy->GetLockedObject()), *this);
02130 if (ref.NotNull()) {
02131 Unlock(ref.GetPointer());
02132 }
02133 return ref;
02134 }
02135 };
02136
02137
02138
02139
02140
02141
02142 template <class C>
02143 class CWeakLockerTraits
02144 {
02145 public:
02146 typedef CWeakObjectExLocker<C> TLockerType;
02147 };
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168 template<class C, class Locker = typename CWeakLockerTraits<C>::TLockerType>
02169 class CWeakRef
02170 {
02171 public:
02172 typedef C element_type;
02173 typedef element_type TObjectType;
02174 typedef Locker locker_type;
02175 typedef typename Locker::TPtrProxyType proxy_type;
02176
02177 typedef CRef<C, Locker> TRefType;
02178 typedef CWeakRef<C, Locker> TThisType;
02179
02180
02181
02182 CWeakRef(void)
02183 {
02184 }
02185
02186
02187 CWeakRef(ENull )
02188 {
02189 }
02190
02191
02192 explicit CWeakRef(TObjectType* ptr)
02193 {
02194 Reset(ptr);
02195 }
02196
02197
02198 CWeakRef(TObjectType* ptr, const locker_type& locker_value)
02199 : m_Locker(locker_value)
02200 {
02201 Reset(ptr);
02202 }
02203
02204
02205
02206
02207
02208 const locker_type& GetLocker(void) const
02209 {
02210 return m_Locker;
02211 }
02212
02213
02214
02215 TRefType Lock(void) const
02216 {
02217 if (!m_Proxy)
02218 return null;
02219
02220 return m_Locker.GetLockedObject(m_Proxy.GetNCPointer());
02221 }
02222
02223
02224 void Reset(void)
02225 {
02226 m_Proxy.Reset();
02227 }
02228
02229
02230 void Reset(ENull )
02231 {
02232 m_Proxy.Reset();
02233 }
02234
02235
02236 void Reset(TObjectType* ptr)
02237 {
02238 if (ptr) {
02239 m_Proxy.Reset(m_Locker.GetPtrProxy(ptr));
02240 }
02241 else {
02242 m_Proxy.Reset();
02243 }
02244 }
02245
02246
02247 void Swap(TThisType& ref)
02248 {
02249 m_Proxy.Swap(ref.m_Proxy);
02250 swap(m_Locker, ref.m_Locker);
02251 }
02252
02253
02254 TThisType& operator= (ENull )
02255 {
02256 Reset();
02257 return *this;
02258 }
02259
02260
02261 TThisType& operator= (TObjectType* ptr)
02262 {
02263 Reset(ptr);
02264 return *this;
02265 }
02266
02267
02268 bool operator== (const TThisType& right)
02269 {
02270 return m_Proxy == right.m_Proxy;
02271 }
02272
02273
02274 bool operator!= (const TThisType& right)
02275 {
02276 return !(*this == right);
02277 }
02278
02279 private:
02280 CRef<proxy_type> m_Proxy;
02281 locker_type m_Locker;
02282 };
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301 template<class Interface, class Locker = CWeakInterfaceLocker<Interface> >
02302 class CWeakIRef : public CWeakRef<Interface, Locker>
02303 {
02304 typedef CWeakRef<Interface, Locker> TParent;
02305 public:
02306 typedef typename TParent::TObjectType TObjectType;
02307 typedef typename TParent::locker_type locker_type;
02308 typedef CWeakIRef<Interface, Locker> TThisType;
02309
02310
02311
02312 CWeakIRef(void)
02313 {
02314 }
02315
02316
02317 CWeakIRef(ENull )
02318 {
02319 }
02320
02321
02322 explicit CWeakIRef(TObjectType* ptr)
02323 : TParent(ptr)
02324 {
02325 }
02326
02327
02328 CWeakIRef(TObjectType* ptr, const locker_type& locker_value)
02329 : TParent(ptr, locker_value)
02330 {
02331 }
02332
02333
02334
02335
02336
02337 TThisType& operator= (ENull null)
02338 {
02339 TParent::operator= (null);
02340 return *this;
02341 }
02342
02343
02344 TThisType& operator= (TObjectType* ptr)
02345 {
02346 TParent::operator= (ptr);
02347 return *this;
02348 }
02349 };
02350
02351
02352
02353
02354
02355 END_NCBI_SCOPE
02356
02357 BEGIN_STD_SCOPE
02358
02359 template<class C, class L>
02360 inline
02361 void swap(NCBI_NS_NCBI::CRef<C,L>& ref1,
02362 NCBI_NS_NCBI::CRef<C,L>& ref2)
02363 {
02364 ref1.Swap(ref2);
02365 }
02366
02367
02368 template<class C, class L>
02369 inline
02370 void swap(NCBI_NS_NCBI::CConstRef<C,L>& ref1,
02371 NCBI_NS_NCBI::CConstRef<C,L>& ref2)
02372 {
02373 ref1.Swap(ref2);
02374 }
02375
02376
02377 template<class C, class L>
02378 inline
02379 void swap(NCBI_NS_NCBI::CWeakRef<C,L>& ref1,
02380 NCBI_NS_NCBI::CWeakRef<C,L>& ref2)
02381 {
02382 ref1.Swap(ref2);
02383 }
02384
02385
02386 END_STD_SCOPE
02387
02388 #endif
02389
02390