include/corelib/ncbiobj.hpp

Go to the documentation of this file.
00001 #ifndef CORELIB___NCBIOBJ__HPP
00002 #define CORELIB___NCBIOBJ__HPP
00003 
00004 /*  $Id: ncbiobj.hpp 160996 2009-05-21 16:12:13Z ivanovp $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Author:  Eugene Vasilchenko, Pavel Ivanov
00030  *
00031  *
00032  */
00033 
00034 /// @file ncbiobj.hpp
00035 /// Portable reference counted smart and weak pointers using
00036 /// CWeakRef, CRef, CObject and CObjectEx.
00037 
00038 
00039 #include <corelib/ncbicntr.hpp>
00040 #include <corelib/ncbiatomic.hpp>
00041 #include <corelib/ddumpable.hpp>
00042 #include <typeinfo>
00043 
00044 /// this relieves us of some nastiness with Win32's version of GetObject(),
00045 /// which prevents us from using CRef<>::GetObject in lots of places
00046 #if defined(NCBI_OS_MSWIN)
00047 #  include <corelib/ncbi_os_mswin.hpp>
00048 #endif
00049 
00050 
00051 /** @addtogroup Object
00052  *
00053  * @{
00054  */
00055 
00056 
00057 
00058 BEGIN_NCBI_SCOPE
00059 
00060 class CObjectMemoryPool;
00061 class CObject;
00062 class CObjectEx;
00063 
00064 
00065 /// Define "null" pointer value.
00066 enum ENull {
00067     null = 0
00068 };
00069 
00070 
00071 
00072 /////////////////////////////////////////////////////////////////////////////
00073 ///
00074 /// CObjectException --
00075 ///
00076 /// Define exceptions generated by CObject.
00077 ///
00078 /// CObjectException inherits its basic functionality from CCoreException
00079 /// and defines additional error codes.
00080 
00081 class  CObjectException : public CCoreException
00082 {
00083 public:
00084     /// Error types that an application can generate.
00085     enum EErrCode {
00086         eRefDelete,     ///< Attempt to delete valid reference
00087         eDeleted,       ///< Attempt to delete a deleted object
00088         eCorrupted,     ///< Object corrupted error
00089         eRefOverflow,   ///< Reference overflow error
00090         eNoRef,         ///< Attempt to access an object that is unreferenced
00091         eRefUnref       ///< Attempt to make a referenced object an
00092                         ///< unreferenced one
00093     };
00094 
00095     /// Translate from the error code value to its string representation.
00096     virtual const char* GetErrCodeString(void) const;
00097 
00098     // Standard exception boilerplate code.
00099     NCBI_EXCEPTION_DEFAULT(CObjectException, CCoreException);
00100 
00101 protected:
00102     void x_InitErrCode(CException::EErrCode err_code);
00103 };
00104 
00105 
00106 ////////////////////////////////////////////////////////////////////////////
00107 // Default locker class for CRef/CConstRef templates
00108 ////////////////////////////////////////////////////////////////////////////
00109 
00110 class CObjectCounterLocker
00111 {
00112 public:
00113     // Mark object as "locked" from deletion.
00114     void Lock(const CObject* object) const;
00115 
00116     // Mark object as "locked" from deletion if it was already locked by
00117     // another locker object.
00118     // Preconditions: this locker was assigned from the another locker object.
00119     void Relock(const CObject* object) const;
00120 
00121     // Mark object as "unlocked" for deletion,
00122     // delete it if last lock was removed.
00123     void Unlock(const CObject* object) const;
00124 
00125     // Mark object as "unlocked" for deletion, but do not delete it.
00126     void UnlockRelease(const CObject* object) const;
00127 
00128     static
00129     void  ReportIncompatibleType(const type_info& type);
00130 };
00131 
00132 
00133 /////////////////////////////////////////////////////////////////////////////
00134 // Traits for default locker parameter
00135 /////////////////////////////////////////////////////////////////////////////
00136 
00137 template <class C>
00138 class CLockerTraits
00139 {
00140 public:
00141     typedef CObjectCounterLocker TLockerType;
00142 };
00143 
00144 
00145 /////////////////////////////////////////////////////////////////////////////
00146 ///
00147 /// CObject --
00148 ///
00149 /// Define the CObject which stores the reference count and the object.
00150 ///
00151 /// CObject inherits from CDebugDumpable the ability to "dump" diagnostic
00152 /// information useful for debugging.
00153 
00154 class CObject : public CDebugDumpable
00155 {
00156 public:
00157     /// Default locker type for CRef
00158     typedef CObjectCounterLocker TLockerType;
00159     /// Constructor.
00160     
00161     CObject(void);
00162 
00163     /// Copy constructor.
00164     
00165     CObject(const CObject& src);
00166 
00167     /// Destructor.
00168     
00169     virtual ~CObject(void);
00170 
00171     /// Assignment operator.
00172     CObject& operator=(const CObject& src) THROWS_NONE;
00173 
00174     /// Check if object can be deleted.
00175     bool CanBeDeleted(void) const THROWS_NONE;
00176 
00177     /// Check if object is allocated in memory pool (not system heap)
00178     bool IsAllocatedInPool(void) const THROWS_NONE;
00179 
00180     /// Check if object is referenced.
00181     bool Referenced(void) const THROWS_NONE;
00182 
00183     /// Check if object is referenced only once.
00184     bool ReferencedOnlyOnce(void) const THROWS_NONE;
00185 
00186     /// Add reference to object.
00187     void AddReference(void) const;
00188 
00189     /// Remove reference to object.
00190     void RemoveReference(void) const;
00191 
00192     /// Remove reference without deleting object.
00193     
00194     void ReleaseReference(void) const;
00195 
00196     /// Mark this object as not allocated in heap --  do not delete this
00197     /// object.
00198     
00199     virtual void DoNotDeleteThisObject(void);
00200 
00201     /// Mark this object as allocated in heap -- object can be deleted.
00202     
00203     virtual void DoDeleteThisObject(void);
00204 
00205     // operators new/delete for additional checking in debug mode
00206 
00207     /// Define new operator for memory allocation.
00208     
00209     void* operator new(size_t size);
00210 
00211     /// Define new[] operator for 'array' memory allocation.
00212     
00213     void* operator new[](size_t size);
00214 
00215     /// Define delete operator for memory deallocation.
00216     
00217     void operator delete(void* ptr);
00218 
00219     /// Define delete[] operator for memory deallocation.
00220     
00221     void operator delete[](void* ptr);
00222 
00223     /// Define new operator.
00224     
00225     void* operator new(size_t size, void* place);
00226 
00227     /// Define delete operator.
00228     
00229     void operator delete(void* ptr, void* place);
00230 
00231     /// Define new operator using memory pool.
00232     
00233     void* operator new(size_t size, CObjectMemoryPool* place);
00234 
00235     /// Define delete operator.
00236     
00237     void operator delete(void* ptr, CObjectMemoryPool* place);
00238 
00239     /// Define method for dumping debug information.
00240     
00241     virtual void DebugDump(CDebugDumpContext ddc, unsigned int depth) const;
00242 
00243     /// Define method to throw null pointer exception.
00244     ///
00245     /// Static method through which all CRef<> / CConstRef<> null pointer
00246     /// throws travel.  This is done to avoid an inline throw.
00247     
00248     static void ThrowNullPointerException(void);
00249     
00250     static void ThrowNullPointerException(const type_info& type);
00251 
00252 
00253     /// Controll filling of newly allocated memory
00254     /// 
00255     /// Default mode is eAllocFillNone if not changed by configuration.
00256     ///   eAllocFillNone - do not fill at all
00257     ///       this mode is faster and is necessary to avoid interference with
00258     ///       memory checker programs like valgrind.
00259     ///   eAllocFillZero - fill new memory with zeros (old default mode)
00260     ///   eAllocFillPattern - fill with non-zero pattern
00261     enum EAllocFillMode {
00262         eAllocFillNone = 1,
00263         eAllocFillZero,
00264         eAllocFillPattern
00265     };
00266     static EAllocFillMode GetAllocFillMode(void);
00267     static void SetAllocFillMode(EAllocFillMode mode);
00268     /// Set mode from configuration parameter value.
00269     static void SetAllocFillMode(const string& value);
00270 
00271 protected:
00272     /// Virtual method "deleting" this object.
00273     /// Method is called whenever by all other indicators this object should
00274     /// be deleted. These indicators are: last reference to the object is
00275     /// removed, object created on heap and method DoNotDeleteThisObject()
00276     /// was not called. Default implementation actually deletes the object,
00277     /// but derived classes are free to do whatever they want (e.g. if they
00278     /// know that they are allocated at some pool they should return
00279     /// themselves to this pool).
00280     
00281     virtual void DeleteThis(void) const;
00282 
00283 private:
00284     typedef CAtomicCounter   TCounter;  ///< Counter type is CAtomiCounter
00285     typedef TCounter::TValue TCount;    ///< Alias for value type of counter
00286 
00287     /// Define possible object states.
00288     /// 
00289     /// When TCounter is signed, all valid values start with 01;
00290     /// when it is unsigned, they start with 1. In other words, when
00291     /// TCounter is signed, the msb (most significant bit) is 0, and the bit
00292     /// after that is a 1; and if the counter is unsigned, then the msb is 1.
00293     ///
00294     /// Least significant bits are the "memory" bits and the most
00295     /// significant bit (or the one after it) is the "valid" bit.
00296     ///
00297     /// The following bit positions have special significance:
00298     /// - Least significant bit = 0 means object not in heap.
00299     /// - Least significant bit = 1 means object in heap.
00300     /// - Most significant bit (or one after it) = 0 means object not valid
00301     /// - Most significant bit (or one after it) = 1 means object is valid 
00302     ///
00303     /// Possible bit patterns:
00304     /// - [0]0x...xxxx : non valid object -> cannot be referenced.
00305     /// - [0]1c...ccx0 : object not in heap -> cannot be deleted.
00306     /// - [0]1c...cc01 : illegal; should be impossible to achieve.
00307     /// - [0]1c...cc11 : object in heap -> can be deleted.
00308     enum EObjectState {
00309         eStateBitsInHeap        = 1 << 0, ///< Detected as in heap
00310         eStateBitsHeapSignature = 1 << 1, ///< Heap signature was found
00311 
00312         /// Mask for 'in heap' state flags
00313         eStateBitsInHeapMask    = eStateBitsInHeap | eStateBitsHeapSignature,
00314 
00315 #ifdef NCBI_COUNTER_UNSIGNED
00316         /// 1 in the left most of the valid bits -- unsigned case
00317         eStateBitsValid   = (unsigned int)(1 << (sizeof(TCount) * 8 - 1)),
00318 #else
00319         /// 1 in the left most of the valid bits -- signed case
00320         eStateBitsValid   = (unsigned int)(1 << (sizeof(TCount) * 8 - 2)),
00321 #endif
00322         /// Valid object, and object in heap. 
00323         eStateMask        = eStateBitsValid | eStateBitsInHeapMask,
00324 
00325         /// Skip over the "in heap" bits
00326         eCounterStep      = 1 << 2, 
00327 
00328         /// Minimal value for valid objects (reference counter is zero)
00329         eCounterValid     = eStateBitsValid,
00330 
00331         /// Minimal value for referenced valid objects (reference counter = 1)
00332         eCounterValidRef1 = eCounterValid + eCounterStep,
00333 
00334         /// Minimal value for double referenced objects (reference counter = 2)
00335         eCounterValidRef2 = eCounterValid + eCounterStep*2,
00336 
00337         /// Initial counter value for non-heap objects
00338         eInitCounterNotInHeap   = eStateBitsValid,
00339 
00340         /// Initial counter value for in-heap objects
00341         eInitCounterInHeap      = eStateBitsValid | eStateBitsHeapSignature |
00342                                   eStateBitsInHeap,
00343 
00344         /// Initial counter value for objects allocated in memory pool
00345         eInitCounterInPool      = eStateBitsValid | eStateBitsInHeap,
00346 
00347         /// Initial counter value for probably non-heap objects (w/ signature)
00348         eInitCounterInStack     = eStateBitsValid | eStateBitsHeapSignature,
00349 
00350         /// All magic counter values should have all their state bits off.
00351         /// Magic counter value for deleted objects
00352         eMagicCounterDeleted    = 0x5b4d9f34 & ~eStateMask,
00353 
00354         /// Magic counter value for object allocated in heap
00355         eMagicCounterNew        = 0x3423cb13 & ~eStateMask,
00356 
00357         /// Magic counter value for deleted object allocated in memory pool
00358         eMagicCounterPoolDeleted= 0x4229775b & ~eStateMask,
00359 
00360         /// Magic counter value for objects allocated in memory pool
00361         eMagicCounterPoolNew    = 0x54917ec2 & ~eStateMask
00362     };
00363     friend class CObjectMemoryPool;
00364     friend class CObjectEx;
00365 
00366     // special methods for parsing object state number
00367 
00368     /// Check if object state is valid.
00369     static bool ObjectStateValid(TCount count);
00370 
00371     /// Check if object can be deleted.
00372     static bool ObjectStateCanBeDeleted(TCount count);
00373 
00374     /// Check if object is allocated in memory pool.
00375     static bool ObjectStateIsAllocatedInPool(TCount count);
00376 
00377     /// Check if object can be referenced.
00378     static bool ObjectStateUnreferenced(TCount count);
00379 
00380     /// Check if object can be referenced.
00381     static bool ObjectStateReferenced(TCount count);
00382 
00383     /// Check if object can be referenced only once.
00384     static bool ObjectStateReferencedOnlyOnce(TCount count);
00385 
00386     /// Initialize counter. 
00387     void InitCounter(void);
00388 
00389     /// Remove the last reference.
00390     
00391     void RemoveLastReference(TCount count) const;
00392 
00393     // report different kinds of error
00394 
00395     /// Report object is invalid.
00396     ///
00397     /// Example: Attempt to use a deleted object.
00398     void InvalidObject(void) const;
00399 
00400     /// Report that counter has overflowed.
00401     
00402     void CheckReferenceOverflow(TCount count) const;
00403 
00404     mutable TCounter  m_Counter;  ///< The actual reference counter
00405 };
00406 
00407 
00408 ////////////////////////////////////////////////////////////////////////////
00409 // Inline methods of CObject
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); // undo
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 // CObjectCounterLocker inline methods
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 // Locker class for interfaces, later derived from CObject
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 /// CRef --
00587 ///
00588 /// Define a template class that stores a pointer to an object and defines
00589 /// methods for referencing that object.
00590 
00591 template<class C, class Locker = typename CLockerTraits<C>::TLockerType>
00592 class CRef {
00593 public:
00594     typedef C element_type;             ///< Define alias element_type
00595     typedef element_type TObjectType;   ///< Define alias TObjectType
00596     typedef Locker locker_type;         ///< Define alias for locking type
00597     typedef CRef<C, Locker> TThisType;  ///< Alias for this template type
00598 
00599     /// Constructor for null pointer.
00600     inline
00601     CRef(void) THROWS_NONE
00602         {
00603         }
00604 
00605     /// Constructor for ENull pointer.
00606     inline
00607     CRef(ENull /*null*/) THROWS_NONE
00608         {
00609         }
00610 
00611     /// Constructor for explicit type conversion from pointer to object.
00612     explicit CRef(TObjectType* ptr)
00613         {
00614             if ( ptr ) {
00615                 m_Data.first().Lock(ptr);
00616                 m_Data.second() = ptr;
00617             }
00618         }
00619 
00620     /// Constructor for explicit type conversion from pointer to object.
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     /// Copy constructor from an existing CRef object, 
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     /// Destructor.
00642     ~CRef(void)
00643         {
00644             Reset();
00645         }
00646 
00647     /// Get reference to locker object
00648     const locker_type& GetLocker(void) const
00649         {
00650             return m_Data.first();
00651         }
00652 
00653     /// Check if CRef is empty -- not pointing to any object, which means
00654     /// having a null value. 
00655     ///
00656     /// @sa
00657     ///   Empty(), IsNull()
00658     bool operator!(void) const THROWS_NONE
00659         {
00660             return m_Data.second() == 0;
00661         }
00662 
00663     /// Check if CRef is empty -- not pointing to any object, which means
00664     /// having a null value. 
00665     ///
00666     /// @sa
00667     ///   IsNull(), operator!()
00668     bool Empty(void) const THROWS_NONE
00669         {
00670             return m_Data.second() == 0;
00671         }
00672 
00673     /// Check if CRef is not empty -- pointing to an object and has
00674     /// a non-null value. 
00675     bool NotEmpty(void) const THROWS_NONE
00676         {
00677             return m_Data.second() != 0;
00678         }
00679 
00680     /// Check if pointer is null -- same effect as Empty().
00681     ///
00682     /// @sa
00683     ///   Empty(), operator!()
00684     bool IsNull(void) const THROWS_NONE
00685         {
00686             return m_Data.second() == 0;
00687         }
00688 
00689     /// Check if pointer is not null -- same effect as NotEmpty().
00690     ///
00691     /// @sa
00692     ///   NotEmpty()
00693     bool NotNull(void) const THROWS_NONE
00694         {
00695             return m_Data.second() != 0;
00696         }
00697 
00698     /// Swaps the pointer with another reference
00699     ///
00700     /// @sa
00701     ///   Swap(CRef<>&)
00702     inline
00703     void Swap(TThisType& ref)
00704         {
00705             swap(m_Data, ref.m_Data);
00706         }
00707 
00708     /// Reset reference object.
00709     ///
00710     /// This sets the pointer to object to null, and removes reference
00711     /// count to object and deletes the object if this is the last reference
00712     /// to the object.
00713     /// @sa
00714     ///   Reset(TObjectType*)
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     /// Reset reference object to new pointer.
00726     ///
00727     /// This sets the pointer to object to the new pointer, and removes
00728     /// reference count to old object and deletes the old object if this is
00729     /// the last reference to the old object.
00730     /// @sa
00731     ///   Reset()
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     /// Release a reference to the object and return a pointer to the object.
00748     ///
00749     /// Releasing a reference means decreasing the reference count by "1". A
00750     /// pointer to the existing object is returned, unless this pointer is
00751     /// already null(0), in which case a null(0) is returned.
00752     ///
00753     /// Similar to Release(), except that this method returns a null,
00754     /// whereas Release() throws a null pointer exception.
00755     ///
00756     /// @sa
00757     ///   Release()
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(/*typeid(TObjectType*)*/);
00773         }
00774 
00775     /// Release a reference to the object and return a pointer to the object.
00776     ///
00777     /// Releasing a reference means decreasing the reference count by "1". A
00778     /// pointer to the existing object is returned, unless this pointer is
00779     /// already null(0), in which the null pointer exception (eNullPtr) is
00780     /// thrown.
00781     ///
00782     /// Similar to ReleaseOrNull(), except that this method throws an exception
00783     /// whereas ReleaseOrNull() does not.
00784     ///
00785     /// @sa
00786     ///   ReleaseOrNull()
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     /// Reset reference object to new pointer.
00803     ///
00804     /// This sets the pointer to object to the new pointer, and removes
00805     /// reference count to old object and deletes the old object if this is
00806     /// the last reference to the old object.
00807     /// The new pointer is got from ref argument.
00808     /// Operation is atomic on this object, so that AtomicResetFrom() and
00809     /// AtomicReleaseTo() called from different threads will work properly.
00810     /// Operation is not atomic on ref argument.
00811     /// @sa
00812     ///   AtomicReleaseTo(CRef& ref);
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); // for this
00819             TObjectType* old_ptr = AtomicSwap(ptr);
00820             if ( old_ptr )
00821                 m_Data.first().Unlock(old_ptr);
00822         }
00823     /// Release referenced object to another CRef<> object.
00824     ///
00825     /// This copies the pointer to object to the argument ref,
00826     /// and release reference from this object.
00827     /// Old reference object held by argument ref is released and deleted if
00828     /// necessary.
00829     /// Operation is atomic on this object, so that AtomicResetFrom() and
00830     /// AtomicReleaseTo() called from different threads will work properly.
00831     /// Operation is not atomic on ref argument.
00832     /// @sa
00833     ///   AtomicResetFrom(const CRef& ref);
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     /// Assignment operator for references.
00848     TThisType& operator=(const TThisType& ref)
00849         {
00850             Reset(ref.m_Data.second());
00851             return *this;
00852         }
00853 
00854     /// Assignment operator for references with right hand side set to
00855     /// a pointer.
00856     TThisType& operator=(TObjectType* ptr)
00857         {
00858             Reset(ptr);
00859             return *this;
00860         }
00861 
00862     /// Assignment operator with right hand side set to ENull.
00863     TThisType& operator=(ENull /*null*/)
00864         {
00865             Reset();
00866             return *this;
00867         }
00868 
00869     /// Get pointer value and throw a null pointer exception if pointer
00870     /// is null.
00871     ///
00872     /// Similar to GetPointerOrNull() except that this method throws a null
00873     /// pointer exception if pointer is null, whereas GetPointerOrNull()
00874     /// returns a null value.
00875     ///
00876     /// @sa
00877     ///   GetPointerOrNull(), GetPointer(), GetObject()
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     /// Get pointer value.
00889     ///
00890     /// Similar to GetNonNullPointer() except that this method returns a null
00891     /// if the pointer is null, whereas GetNonNullPointer() throws a null
00892     /// pointer exception.
00893     ///
00894     /// @sa
00895     ///   GetNonNullPointer()
00896     inline
00897     TObjectType* GetPointerOrNull(void) THROWS_NONE
00898         {
00899             return m_Data.second();
00900         }
00901 
00902     /// Get pointer,
00903     ///
00904     /// Same as GetPointerOrNull().
00905     ///
00906     /// @sa
00907     ///   GetPointerOrNull()
00908     inline
00909     TObjectType* GetPointer(void) THROWS_NONE
00910         {
00911             return GetPointerOrNull();
00912         }
00913 
00914     /// Get object.
00915     ///
00916     /// Similar to GetNonNullPointer(), except that this method returns the
00917     /// object whereas GetNonNullPointer() returns a pointer to the object.
00918     /// 
00919     /// @sa
00920     ///   GetNonNullPointer()
00921     inline
00922     TObjectType& GetObject(void)
00923         {
00924             return *GetNonNullPointer();
00925         }
00926 
00927     /// Dereference operator returning object.
00928     ///
00929     /// @sa
00930     ///   GetObject()
00931     inline
00932     TObjectType& operator*(void)
00933         {
00934             return *GetNonNullPointer();
00935         }
00936 
00937     /// Reference operator.
00938     ///
00939     /// @sa
00940     ///   GetPointer()
00941     inline
00942     TObjectType* operator->(void)
00943         {
00944             return GetNonNullPointer();
00945         }
00946 
00947     // Const getters.
00948 
00949     /// Get pointer value and throw a null pointer exception if pointer
00950     /// is null -- constant version.
00951     ///
00952     /// Similar to GetPointerOrNull() except that this method throws a null
00953     /// pointer exception if pointer is null, whereas GetPointerOrNull()
00954     /// returns a null value.
00955     ///
00956     /// @sa
00957     ///   GetPointerOrNull(), GetPointer(), GetObject()
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     /// Get pointer value -- constant version.
00968     ///
00969     /// Similar to GetNonNullPointer() except that this method returns a null
00970     /// if the pointer is null, whereas GetNonNullPointer() throws a null
00971     /// pointer exception.
00972     ///
00973     /// @sa
00974     ///   GetNonNullPointer()
00975     const TObjectType* GetPointerOrNull(void) const THROWS_NONE
00976         {
00977             return m_Data.second();
00978         }
00979 
00980     /// Get pointer -- constant version,
00981     ///
00982     /// Same as GetPointerOrNull().
00983     ///
00984     /// @sa
00985     ///   GetPointerOrNull()
00986     inline
00987     const TObjectType* GetPointer(void) const THROWS_NONE
00988         {
00989             return GetPointerOrNull();
00990         }
00991 
00992     /// Get object -- constant version.
00993     ///
00994     /// Similar to GetNonNullPointer(), except that this method returns the
00995     /// object whereas GetNonNullPointer() returns a pointer to the object.
00996     /// 
00997     /// @sa
00998     ///   GetNonNullPointer()
00999     inline
01000     const TObjectType& GetObject(void) const
01001         {
01002             return *GetNonNullPointer();
01003         }
01004 
01005     /// Dereference operator returning object -- constant version.
01006     ///
01007     /// @sa
01008     ///   GetObject()
01009     inline
01010     const TObjectType& operator*(void) const
01011         {
01012             return *GetNonNullPointer();
01013         }
01014 
01015     /// Reference operator -- constant version.
01016     ///
01017     /// @sa
01018     ///   GetPointer()
01019     inline
01020     const TObjectType* operator->(void) const
01021         {
01022             return GetNonNullPointer();
01023         }
01024 
01025     /// Dereference operator returning pointer.
01026     ///
01027     /// @sa
01028     ///   GetPointer()
01029     inline
01030     operator TObjectType*(void)
01031         {
01032             return GetPointerOrNull();
01033         }
01034     
01035     /// Dereference operator returning pointer -- constant version.
01036     ///
01037     /// @sa
01038     ///   GetPointer()
01039     inline
01040     operator const TObjectType*(void) const
01041         {
01042             return GetPointerOrNull();
01043         }
01044     
01045     /// Get pointer value and throw a null pointer exception if pointer
01046     /// is null.
01047     ///
01048     /// Similar to GetPointerOrNull() except that this method throws a null
01049     /// pointer exception if pointer is null, whereas GetPointerOrNull()
01050     /// returns a null value.
01051     ///
01052     /// @sa
01053     ///   GetPointerOrNull(), GetPointer(), GetObject()
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     /// Get pointer value.
01065     ///
01066     /// Similar to GetNonNullPointer() except that this method returns a null
01067     /// if the pointer is null, whereas GetNonNullPointer() throws a null
01068     /// pointer exception.
01069     ///
01070     /// @sa
01071     ///   GetNonNullPointer()
01072     inline
01073     TObjectType* GetNCPointerOrNull(void) const THROWS_NONE
01074         {
01075             return m_Data.second();
01076         }
01077 
01078     /// Get pointer,
01079     ///
01080     /// Same as GetPointerOrNull().
01081     ///
01082     /// @sa
01083     ///   GetPointerOrNull()
01084     inline
01085     TObjectType* GetNCPointer(void) const THROWS_NONE
01086         {
01087             return GetNCPointerOrNull();
01088         }
01089 
01090     /// Get object.
01091     ///
01092     /// Similar to GetNonNullPointer(), except that this method returns the
01093     /// object whereas GetNonNullPointer() returns a pointer to the object.
01094     /// 
01095     /// @sa
01096     ///   GetNonNullPointer()
01097     inline
01098     TObjectType& GetNCObject(void) const
01099         {
01100             return *GetNonNullNCPointer();
01101         }
01102 
01103 private:
01104     TObjectType* AtomicSwap(TObjectType* ptr)
01105         {
01106             // MIPSpro won't accept static_cast for some reason.
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; ///< Pointer to object
01114     
01115 private:
01116 // Hide incorrect operators
01117     void operator-(TObjectType*) const;
01118     void operator-(int) const;
01119     void operator+(int) const;
01120 };
01121 
01122 
01123 /////////////////////////////////////////////////////////////////////////////
01124 ///
01125 /// CConstRef --
01126 ///
01127 /// Define a template class that stores a pointer to an object and defines
01128 /// methods for constant referencing of object. 
01129 
01130 template<class C, class Locker = CObjectCounterLocker>
01131 class CConstRef {
01132 public:
01133     typedef C element_type;                 ///< Define alias element_type
01134     typedef const element_type TObjectType; ///< Define alias TObjectType
01135     typedef Locker locker_type;             ///< Define alias for locking type
01136     typedef CConstRef<C, Locker> TThisType; ///< Alias for this template type
01137 
01138     /// Constructor for null pointer.
01139     inline
01140     CConstRef(void) THROWS_NONE
01141         {
01142         }
01143 
01144     /// Constructor for ENull pointer.
01145     inline
01146     CConstRef(ENull /*null*/) THROWS_NONE
01147         {
01148         }
01149 
01150     /// Constructor for explicit type conversion from pointer to object.
01151     explicit CConstRef(TObjectType* ptr)
01152         {
01153             if ( ptr ) {
01154                 m_Data.first().Lock(ptr);
01155                 m_Data.second() = ptr;
01156             }
01157         }
01158 
01159     /// Constructor for explicit type conversion from pointer to object.
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     /// Constructor from an existing CConstRef object, 
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     /// Constructor from an existing CRef object, 
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     /// Destructor.
01192     ~CConstRef(void)
01193         {
01194             Reset();
01195         }
01196     
01197     /// Get reference to locker object
01198     const locker_type& GetLocker(void) const
01199         {
01200             return m_Data.first();
01201         }
01202 
01203     /// Check if CConstRef is empty -- not pointing to any object, which means
01204     /// having a null value. 
01205     ///
01206     /// @sa
01207     ///   Empty(), IsNull()
01208     bool operator!(void) const THROWS_NONE
01209         {
01210             return m_Data.second() == 0;
01211         }
01212     
01213     /// Check if CConstRef is empty -- not pointing to any object which means
01214     /// having a null value. 
01215     ///
01216     /// @sa
01217     ///   IsNull(), operator!()
01218     bool Empty(void) const THROWS_NONE
01219         {
01220             return m_Data.second() == 0;
01221         }
01222 
01223     /// Check if CConstRef is not empty -- pointing to an object and has
01224     /// a non-null value. 
01225     bool NotEmpty(void) const THROWS_NONE
01226         {
01227             return m_Data.second() != 0;
01228         }
01229 
01230     /// Check if pointer is null -- same effect as Empty().
01231     ///
01232     /// @sa
01233     ///   Empty(), operator!()
01234     bool IsNull(void) const THROWS_NONE
01235         {
01236             return m_Data.second() == 0;
01237         }
01238 
01239     /// Check if pointer is not null -- same effect as NotEmpty().
01240     ///
01241     /// @sa
01242     ///   NotEmpty()
01243     bool NotNull(void) const THROWS_NONE
01244         {
01245             return m_Data.second() != 0;
01246         }
01247 
01248     /// Swaps the pointer with another reference
01249     ///
01250     /// @sa
01251     ///   Swap(ConstRef<>&)
01252     inline
01253     void Swap(TThisType& ref)
01254         {
01255             swap(m_Data, ref.m_Data);
01256         }
01257 
01258     /// Reset reference object.
01259     ///
01260     /// This sets the pointer to object to null, and removes reference
01261     /// count to object and deletes the object if this is the last reference
01262     /// to the object.
01263     /// @sa
01264     ///   Reset(TObjectType*)
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     /// Reset reference object to new pointer.
01276     ///
01277     /// This sets the pointer to object to the new pointer, and removes
01278     /// reference count to old object and deletes the old object if this is
01279     /// the last reference to the old object.
01280     /// @sa
01281     ///   Reset()
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     /// Release a reference to the object and return a pointer to the object.
01298     ///
01299     /// Releasing a reference means decreasing the reference count by "1". A
01300     /// pointer to the existing object is returned, unless this pointer is
01301     /// already null(0), in which case a null(0) is returned.
01302     ///
01303     /// Similar to Release(), except that this method returns a null,
01304     /// whereas Release() throws a null pointer exception.
01305     ///
01306     /// @sa
01307     ///   Release()
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(/*typeid(TObjectType*)*/);
01323         }
01324 
01325     /// Release a reference to the object and return a pointer to the object.
01326     ///
01327     /// Releasing a reference means decreasing the reference count by "1". A
01328     /// pointer to the existing object is returned, unless this pointer is
01329     /// already null(0), in which the null pointer exception (eNullPtr) is
01330     /// thrown.
01331     ///
01332     /// Similar to ReleaseOrNull(), except that this method throws an exception
01333     /// whereas ReleaseOrNull() does not.
01334     ///
01335     /// @sa
01336     ///   ReleaseOrNull()
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     /// Reset reference object to new pointer.
01353     ///
01354     /// This sets the pointer to object to the new pointer, and removes
01355     /// reference count to old object and deletes the old object if this is
01356     /// the last reference to the old object.
01357     /// The new pointer is got from ref argument.
01358     /// Operation is atomic on this object, so that AtomicResetFrom() and
01359     /// AtomicReleaseTo() called from different threads will work properly.
01360     /// Operation is not atomic on ref argument.
01361     /// @sa
01362     ///   AtomicReleaseTo(CConstRef& ref);
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); // for this
01369             TObjectType* old_ptr = AtomicSwap(ptr);
01370             if ( old_ptr )
01371                 m_Data.first().Unlock(old_ptr);
01372         }
01373     /// Release referenced object to another CConstRef<> object.
01374     ///
01375     /// This copies the pointer to object to the argument ref,
01376     /// and release reference from this object.
01377     /// Old reference object held by argument ref is released and deleted if
01378     /// necessary.
01379     /// Operation is atomic on this object, so that AtomicResetFrom() and
01380     /// AtomicReleaseTo() called from different threads will work properly.
01381     /// Operation is not atomic on ref argument.
01382     /// @sa
01383     ///   AtomicResetFrom(const CConstRef& ref);
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     /// Assignment operator for const references.
01398     TThisType& operator=(const TThisType& ref)
01399         {
01400             Reset(ref.m_Data.second());
01401             return *this;
01402         }
01403 
01404     /// Assignment operator for assigning a reference to a const reference.
01405     TThisType& operator=(const CRef<C, Locker>& ref)
01406         {
01407             Reset(ref.GetPointerOrNull());
01408             return *this;
01409         }
01410 
01411     /// Assignment operator for const references with right hand side set to
01412     /// a pointer.
01413     TThisType& operator=(TObjectType* ptr)
01414         {
01415             Reset(ptr);
01416             return *this;
01417         }
01418 
01419     /// Assignment operator with right hand side set to ENull.
01420     TThisType& operator=(ENull /*null*/)
01421         {
01422             Reset();
01423             return *this;
01424         }
01425 
01426     /// Get pointer value and throw a null pointer exception if pointer
01427     /// is null.
01428     ///
01429     /// Similar to GetPointerOrNull() except that this method throws a null
01430     /// pointer exception if pointer is null, whereas GetPointerOrNull()
01431     /// returns a null value.
01432     ///
01433     /// @sa
01434     ///   GetPointerOrNull(), GetPointer(), GetObject()
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     /// Get pointer value.
01446     ///
01447     /// Similar to GetNonNullPointer() except that this method returns a null
01448     /// if the pointer is null, whereas GetNonNullPointer() throws a null
01449     /// pointer exception.
01450     ///
01451     /// @sa
01452     ///   GetNonNullPointer()
01453     inline
01454     TObjectType* GetPointerOrNull(void) const THROWS_NONE
01455         {
01456             return m_Data.second();
01457         }
01458 
01459     /// Get pointer,
01460     ///
01461     /// Same as GetPointerOrNull().
01462     ///
01463     /// @sa
01464     ///   GetPointerOrNull()
01465     inline
01466     TObjectType* GetPointer(void) const THROWS_NONE
01467         {
01468             return GetPointerOrNull();
01469         }
01470 
01471     /// Get object.
01472     ///
01473     /// Similar to GetNonNullPointer(), except that this method returns the
01474     /// object whereas GetNonNullPointer() returns a pointer to the object.
01475     /// 
01476     /// @sa
01477     ///   GetNonNullPointer()
01478     inline
01479     TObjectType& GetObject(void) const
01480         {
01481             return *GetNonNullPointer();
01482         }
01483 
01484     /// Dereference operator returning object.
01485     ///
01486     /// @sa
01487     ///   GetObject()
01488     inline
01489     TObjectType& operator*(void) const
01490         {
01491             return *GetNonNullPointer();
01492         }
01493 
01494     /// Reference operator.
01495     ///
01496     /// @sa
01497     ///   GetPointer()
01498     inline
01499     TObjectType* operator->(void) const
01500         {
01501             return GetNonNullPointer();
01502         }
01503 
01504     /// Dereference operator returning pointer.
01505     ///
01506     /// @sa
01507     ///   GetPointer()
01508     inline
01509     operator TObjectType*(void) const
01510         {
01511             return GetPointerOrNull();
01512         }
01513 
01514 private:
01515     TObjectType* AtomicSwap(TObjectType* ptr)
01516         {
01517             // MIPSpro won't accept static_cast for some reason.
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; ///< Pointer to object
01526     
01527 private:
01528 // Hide incorrect operators
01529     void operator-(TObjectType*) const;
01530     void operator-(int) const;
01531     void operator+(int) const;
01532 };
01533 
01534 
01535 /////////////////////////////////////////////////////////////////////////////
01536 /// Comparison operators for CRef<> and CConstRef<> with ENull
01537 
01538 /// Template operator == function for CRef objects -- rhs is null.
01539 template<class T, class L>
01540 inline
01541 bool operator== (const CRef<T,L>& r1, ENull /*null*/)
01542 {
01543     return r1.IsNull();
01544 }
01545 
01546 /// Template operator == function for CRef objects -- lhs is null.
01547 template<class T, class L>
01548 inline
01549 bool operator== (ENull /*null*/, const CRef<T,L>& r1)
01550 {
01551     return r1.IsNull();
01552 }
01553 
01554 /// Template operator != function for CRef objects -- rhs is null.
01555 template<class T, class L>
01556 inline
01557 bool operator!= (const CRef<T,L>& r1, ENull /*null*/)
01558 {
01559     return !r1.IsNull();
01560 }
01561 
01562 /// Template operator != function for CRef objects -- lhs is null.
01563 template<class T, class L>
01564 inline
01565 bool operator!= (ENull /*null*/, const CRef<T,L>& r1)
01566 {
01567     return !r1.IsNull();
01568 }
01569 
01570 /// Template operator == function for CConstRef objects -- rhs is null.
01571 template<class T, class L>
01572 inline
01573 bool operator== (const CConstRef<T,L>& r1, ENull /*null*/)
01574 {
01575     return r1.IsNull();
01576 }
01577 
01578 /// Template operator == function for CConstRef objects -- lhs is null.
01579 template<class T, class L>
01580 inline
01581 bool operator== (ENull /*null*/, const CConstRef<T,L>& r1)
01582 {
01583     return r1.IsNull();
01584 }
01585 
01586 /// Template operator != function for CConstRef objects -- rhs is null.
01587 template<class T, class L>
01588 inline
01589 bool operator!= (const CConstRef<T,L>& r1, ENull /*null*/)
01590 {
01591     return !r1.IsNull();
01592 }
01593 
01594 /// Template operator != function for CConstRef objects -- lhs is null.
01595 template<class T, class L>
01596 inline
01597 bool operator!= (ENull /*null*/, const CConstRef<T,L>& r1)
01598 {
01599     return !r1.IsNull();
01600 }
01601 
01602 
01603 #if defined(NCBI_COMPILER_WORKSHOP)
01604 /// WorkShop fails to compare CRef/CConstRef via operator pointer sometimes.
01605 /////////////////////////////////////////////////////////////////////////////
01606 /// Comparison operators for CRef<>
01607 
01608 /// Template operator < function for CRef objects.
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 /// Template operator > function for CRef objects.
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 /// Template operator < function for CRef objects.
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 /// Template operator > function for CRef objects.
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 /// Template operator == function for CRef objects.
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 /// Template operator == function for CRef and CRef objects.
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 /// Comparison operators for CConstRef<>
01658 
01659 /// Template operator < function for CConstRef objects.
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 /// Template operator > function for CConstRef objects.
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 /// Template operator < function for CConstRef objects.
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 /// Template operator > function for CConstRef objects.
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 /// Template operator == function for CConstRef objects.
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 /// Template operator != function for CConstRef objects.
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 /// Mixed comparison operators
01710 
01711 /// Template operator == function for CConstRef and CRef objects.
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 /// Template operator == function for CRef and CConstRef objects.
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 /// Template operator != function for CConstRef and CRef objects.
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 /// Template operator != function for CRef and CConstRef objects.
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 /// Helper functions to get CRef<> and CConstRef<> objects
01747 
01748 /// Template function for conversion of object pointer to CRef
01749 template<class C>
01750 inline
01751 CRef<C> Ref(C* object)
01752 {
01753     return CRef<C>(object);
01754 }
01755 
01756 
01757 /// Template function for conversion of const object pointer to CConstRef
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     // We have to redefine all constructors and assignment operators
01776 
01777     /// Constructor for null pointer.
01778     CIRef(void) THROWS_NONE
01779         {
01780         }
01781 
01782     /// Constructor for ENull pointer.
01783     CIRef(ENull /*null*/) THROWS_NONE
01784         {
01785         }
01786 
01787     /// Constructor for explicit type conversion from pointer to object.
01788     explicit CIRef(TObjectType* ptr)
01789         : TParent(ptr)
01790         {
01791         }
01792 
01793     /// Constructor for explicit type conversion from pointer to object.
01794     CIRef(TObjectType* ptr, const locker_type& locker_value)
01795         : TParent(ptr, locker_value)
01796         {
01797         }
01798 
01799     /// Assignment operator for references.
01800     TThisType& operator=(const TThisType& ref)
01801         {
01802             TParent::operator=(ref);
01803             return *this;
01804         }
01805 
01806     /// Assignment operator for references with right hand side set to
01807     /// a pointer.
01808     TThisType& operator=(TObjectType* ptr)
01809         {
01810             TParent::operator=(ptr);
01811             return *this;
01812         }
01813 
01814     /// Assignment operator with right hand side set to ENull.
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     // We have to redefine all constructors and assignment operators
01832 
01833     /// Constructor for null pointer.
01834     CConstIRef(void) THROWS_NONE
01835         {
01836         }
01837 
01838     /// Constructor for ENull pointer.
01839     CConstIRef(ENull /*null*/) THROWS_NONE
01840         {
01841         }
01842 
01843     /// Constructor for explicit type conversion from pointer to object.
01844     explicit CConstIRef(TObjectType* ptr)
01845         : TParent(ptr)
01846         {
01847         }
01848 
01849     /// Constructor for explicit type conversion from pointer to object.
01850     CConstIRef(TObjectType* ptr, const locker_type& locker_value)
01851         : TParent(ptr, locker_value)
01852         {
01853         }
01854 
01855     /// Constructor from an existing CRef object, 
01856     CConstIRef(const CIRef<Interface, Locker>& ref)
01857         : TParent(ref)
01858         {
01859         }
01860 
01861     /// Assignment operator for references.
01862     TThisType& operator=(const TThisType& ref)
01863         {
01864             TParent::operator=(ref);
01865             return *this;
01866         }
01867 
01868     /// Assignment operator for assigning a reference to a const reference.
01869     TThisType& operator=(const CIRef<Interface, Locker>& ref)
01870         {
01871             TParent::operator=(ref);
01872             return *this;
01873         }
01874 
01875     /// Assignment operator for references with right hand side set to
01876     /// a pointer.
01877     TThisType& operator=(TObjectType* ptr)
01878         {
01879             TParent::operator=(ptr);
01880             return *this;
01881         }
01882 
01883     /// Assignment operator with right hand side set to ENull.
01884     TThisType& operator=(ENull null)
01885         {
01886             TParent::operator=(null);
01887             return *this;
01888         }
01889 };
01890 
01891 
01892 /////////////////////////////////////////////////////////////////////////////
01893 ///
01894 /// CObjectFor --
01895 ///
01896 /// Define a template class whose template parameter is a standard data type 
01897 /// that will be pointed to.
01898 ///
01899 /// The template class defines a private data member of the same type as the
01900 /// template parameter, and accessor methods GetData() to retrieve the value
01901 /// of this private data member. The class is derived from CObject and
01902 /// therefore inherits the reference counter defined in that class. In essence,
01903 /// this class serves as a "wrapper" class for standard data types allowing
01904 /// reference counted smart pointers to be used for standard data types. 
01905 
01906 template<typename T>
01907 class CObjectFor : public CObject
01908 {
01909 public:
01910     typedef T TObjectType;          ///< Define alias for template parameter
01911 
01912     CObjectFor(void)
01913         {
01914         }
01915 
01916     explicit CObjectFor(const TObjectType& data)
01917         : m_Data(data)
01918         {
01919         }
01920 
01921     /// Get data as a reference.
01922     T& GetData(void)
01923         {
01924             return m_Data;
01925         }
01926 
01927     /// Get data as a reference -- const version.
01928     const T& GetData(void) const
01929         {
01930             return m_Data;
01931         }
01932 
01933     /// Operator () to get data -- same as GetData().
01934     ///
01935     /// @sa
01936     ///   GetData()
01937     operator T& (void)
01938         {
01939             return GetData();
01940         }
01941 
01942     /// Operator () to get data -- const version, same as GetData().
01943     ///
01944     /// @sa
01945     ///   GetData()
01946     operator const T& (void) const
01947         {
01948             return GetData();
01949         }
01950 
01951     /// Assignment operator.
01952     T& operator=(const T& data)
01953         {
01954             m_Data = data;
01955             return *this;
01956         }
01957 
01958 private:
01959     T m_Data;               ///< Data member of template parameter type
01960 };
01961 
01962 
01963 /////////////////////////////////////////////////////////////////////////////
01964 ///
01965 /// CPtrToObjectExProxy --
01966 ///
01967 /// Proxy class used for building CObjectEx and CWeakPtr.
01968 ///
01969 /// Contains pointer to CObjectEx instance and NULL after this instance is
01970 /// destroyed.
01971 
01972 class CPtrToObjectExProxy : public CObject
01973 {
01974 public:
01975     CPtrToObjectExProxy(CObjectEx* ptr);
01976 
01977     
01978     ~CPtrToObjectExProxy(void);
01979 
01980     /// Set pointer to NULL from object's destructor.
01981     void Clear(void);
01982 
01983     /// Lock the object and return pointer to it.
01984     /// If object is already destroyed then return NULL.
01985     
01986     CObjectEx* GetLockedObject(void);
01987 
01988     /// Report about trying to convert incompatible interface fo CObjectEx
01989     
01990     static void ReportIncompatibleType(const type_info& type);
01991 
01992 private:
01993     CObjectEx* m_Ptr;
01994 };
01995 
01996 
01997 /////////////////////////////////////////////////////////////////////////////
01998 ///
01999 /// CObjectEx --
02000 ///
02001 /// The extended CObject class not only counting references to it but
02002 /// containing additional information to allow weak references to it.
02003 ///
02004 /// NOTE: If your class is derived from CObjectEx, you override DelteThis()
02005 ///       method, you do not actually delete the object in your implementation
02006 ///       of DeleteThis() and you do not want all existing CWeakRefs to
02007 ///       reference to this object any longer then you must call method
02008 ///       CleanWeakRefs().
02009 ///
02010 /// @sa CWeakRef<>
02011 
02012 class CObjectEx : public CObject
02013 {
02014 public:
02015     
02016     CObjectEx(void);
02017 
02018     
02019     virtual ~CObjectEx(void);
02020 
02021     /// Get pointer to proxy object containing pointer to this object
02022     CPtrToObjectExProxy* GetPtrProxy(void) const;
02023 
02024 protected:
02025     /// Method cleaning all CWeakRefs referencing at this moment to the object
02026     /// After calling to this method all existing CWeakRefs referencing to the
02027     /// object will return NULL, so it effectively will be equal to deleting
02028     /// the object. This method should be called from DeleteThis() if it is
02029     /// overridden, if it does not actually deletes the object and if you want
02030     /// it to behave the same way as default DeleteThis() does in relation to
02031     /// CWeakRefs.
02032     
02033     void CleanWeakRefs(void) const;
02034 
02035 private:
02036     /// Add reference to the object in "weak" manner
02037     /// If reference was added successfully returns TRUE.
02038     /// If the object is already destroying then returns FALSE.
02039     bool WeakAddReference(void);
02040 
02041     friend class CPtrToObjectExProxy;
02042 
02043 
02044     /// Proxy object with pointer to this instance
02045     mutable CRef<CPtrToObjectExProxy> m_SelfPtrProxy;
02046 };
02047 
02048 ////////////////////////////////////////////////////////////////////////////
02049 // CObjectCounterLocker inline methods
02050 ////////////////////////////////////////////////////////////////////////////
02051 
02052 inline
02053 CPtrToObjectExProxy* CObjectEx::GetPtrProxy(void) const
02054 {
02055     return m_SelfPtrProxy.GetNCPointer();
02056 }
02057 
02058 
02059 
02060 /////////////////////////////////////////////////////////////////////////////
02061 ///
02062 /// CWeakObjectExLocker --
02063 ///
02064 /// Default locker class for CWeakRef template
02065 
02066 template <class C>
02067 class CWeakObjectExLocker : public CObjectCounterLocker
02068 {
02069 public:
02070     /// Type working as proxy storage for pointer to object
02071     typedef CPtrToObjectExProxy     TPtrProxyType;
02072     /// Alias for this type
02073     typedef CWeakObjectExLocker<C>  TThisType;
02074 
02075     /// Get proxy storage for pointer to object
02076     TPtrProxyType* GetPtrProxy(C* object) const
02077     {
02078         return object->GetPtrProxy();
02079     }
02080 
02081     /// Lock the object and return pointer to it stored in the proxy.
02082     /// If object is already destroyed then return NULL CRef.
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 /// CWeakInterfaceLocker --
02098 ///
02099 /// Default locker class for CWeakIRef template
02100 
02101 template <class Interface>
02102 class CWeakInterfaceLocker : public CInterfaceObjectLocker<Interface>
02103 {
02104 public:
02105     /// Type working as proxy storage for pointer to object
02106     typedef CPtrToObjectExProxy              TPtrProxyType;
02107     /// Alias for this type
02108     typedef CWeakInterfaceLocker<Interface>  TThisType;
02109 
02110     /// Get proxy storage for pointer to object
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     /// Lock the object and return pointer to it stored in the proxy.
02121     /// If object is already destroyed then return NULL.
02122     CIRef<Interface, TThisType> GetLockedObject(TPtrProxyType* proxy) const
02123     {
02124         // We are not checking that result of dynamic_cast is not null
02125         // because type compatibility is already checked in GetPtrProxy()
02126         // which always called first. Now we can be sure that this
02127         // cast will not return null.
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 // Traits for default locker parameter in CWeakRef
02140 /////////////////////////////////////////////////////////////////////////////
02141 
02142 template <class C>
02143 class CWeakLockerTraits
02144 {
02145 public:
02146     typedef CWeakObjectExLocker<C>  TLockerType;
02147 };
02148 
02149 
02150 
02151 /////////////////////////////////////////////////////////////////////////////
02152 ///
02153 /// CWeakRef --
02154 ///
02155 /// Template for "weak" pointer to the object.
02156 ///
02157 /// Contains the pointer to the CObjectEx but do not control the lifetime of
02158 /// the object. Access to the object can be obtained only via method Lock()
02159 /// which will return CRef to the object which will guarantee that object is
02160 /// not destroyed yet and until received CRef is not destroyed. If contained
02161 /// object is already destroyed at the time of calling Lock() then method will
02162 /// return empty reference.
02163 ///
02164 /// Parameter class C should be derrived from CObjectEx class.
02165 ///
02166 /// @sa CObjectEx
02167 
02168 template<class C, class Locker = typename CWeakLockerTraits<C>::TLockerType>
02169 class CWeakRef
02170 {
02171 public:
02172     typedef C element_type;                 ///< Define alias element_type
02173     typedef element_type TObjectType;       ///< Define alias TObjectType
02174     typedef Locker locker_type;             ///< Define alias for locking type
02175     typedef typename Locker::TPtrProxyType proxy_type;
02176                                             ///< Alias for pointer proxy type
02177     typedef CRef<C, Locker> TRefType;       ///< Alias for the CRef type
02178     typedef CWeakRef<C, Locker> TThisType;  ///< Alias for this type
02179 
02180 
02181     /// Constructor for null pointer
02182     CWeakRef(void)
02183     {
02184     }
02185 
02186     /// Constructor for ENull pointer
02187     CWeakRef(ENull /*null*/)
02188     {
02189     }
02190 
02191     /// Constructor for pointer to a particular object
02192     explicit CWeakRef(TObjectType* ptr)
02193     {
02194         Reset(ptr);
02195     }
02196 
02197     /// Constructor for explicit type conversion from pointer to object.
02198     CWeakRef(TObjectType* ptr, const locker_type& locker_value)
02199         : m_Locker(locker_value)
02200     {
02201         Reset(ptr);
02202     }
02203 
02204     // Default copy constructor and copy assignment are ok
02205 
02206 
02207     /// Get reference to locker object
02208     const locker_type& GetLocker(void) const
02209     {
02210         return m_Locker;
02211     }
02212 
02213     /// Lock the object and return reference to it.
02214     /// If object is already deleted then null reference is returned.
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     /// Reset the containing pointer to null
02224     void Reset(void)
02225     {
02226         m_Proxy.Reset();
02227     }
02228 
02229     /// Reset the containing pointer to null
02230     void Reset(ENull /*null*/)
02231     {
02232         m_Proxy.Reset();
02233     }
02234 
02235     /// Reset the containing pointer to another object
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     /// Swap values of this reference with another
02247     void Swap(TThisType& ref)
02248     {
02249         m_Proxy.Swap(ref.m_Proxy);
02250         swap(m_Locker, ref.m_Locker);
02251     }
02252 
02253     /// Assignment from ENull pointer
02254     TThisType& operator= (ENull /*null*/)
02255     {
02256         Reset();
02257         return *this;
02258     }
02259 
02260     /// Assignment from pointer to other object
02261     TThisType& operator= (TObjectType* ptr)
02262     {
02263         Reset(ptr);
02264         return *this;
02265     }
02266 
02267     /// operator== to compare with another CWeakRef
02268     bool operator== (const TThisType& right)
02269     {
02270         return m_Proxy == right.m_Proxy;
02271     }
02272 
02273     /// operator!= to compare with another CWeakRef
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 /// CWeakIRef --
02288 ///
02289 /// Template for "weak" pointer to the interface.
02290 ///
02291 /// Contains the pointer to interface. Final object pointed by this reference
02292 /// should have ability of dynamic cast to CObjectEx. Reference do not control
02293 /// the lifetime of the object. Access to the interface can be obtained only
02294 /// via method Lock() which will return CIRef to the object which will
02295 /// guarantee that object is not destroyed yet and until received CIRef is not
02296 /// destroyed. If contained interface is already destroyed at the time
02297 /// of calling Lock() then method will return empty reference.
02298 ///
02299 /// @sa CObjectEx, CWeakRef<>
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     /// Constructor for null pointer
02312     CWeakIRef(void)
02313     {
02314     }
02315 
02316     /// Constructor for ENull pointer
02317     CWeakIRef(ENull /*null*/)
02318     {
02319     }
02320 
02321     /// Constructor for pointer to the interface
02322     explicit CWeakIRef(TObjectType* ptr)
02323         : TParent(ptr)
02324     {
02325     }
02326 
02327     /// Constructor for explicit type conversion from pointer to object.
02328     CWeakIRef(TObjectType* ptr, const locker_type& locker_value)
02329         : TParent(ptr, locker_value)
02330     {
02331     }
02332 
02333     // Default copy constructor and copy assignment are ok
02334 
02335 
02336     /// Assignment from ENull pointer
02337     TThisType& operator= (ENull null)
02338     {
02339         TParent::operator= (null);
02340         return *this;
02341     }
02342 
02343     /// Assignment from pointer to another interface
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 /* NCBIOBJ__HPP */
02389 
02390 

Generated on Wed Dec 9 03:06:43 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:17:29 2009 by modify_doxy.py rev. 173732