StrongPtr.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2006 Rich Sposato
00004 // The copyright on this file is protected under the terms of the MIT license.
00005 //
00006 // Permission to use, copy, modify, distribute and sell this software for any 
00007 //     purpose is hereby granted without fee, provided that the above copyright 
00008 //     notice appear in all copies and that both that copyright notice and this 
00009 //     permission notice appear in supporting documentation.
00010 // The author makes no representations about the 
00011 //     suitability of this software for any purpose. It is provided "as is" 
00012 //     without express or implied warranty.
00014 #ifndef LOKI_STRONG_PTR_INC_
00015 #define LOKI_STRONG_PTR_INC_
00016 
00017 // $Id: StrongPtr.h 807 2007-02-25 12:49:19Z syntheticpp $
00018 
00019 
00020 #include <loki/SmartPtr.h>
00021 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
00022     #include <loki/Threads.h>
00023 #endif
00024 
00025 
00111 
00112 
00113 namespace Loki
00114 {
00115 
00116 
00125 
00126 template < class P >
00127 class DeleteUsingFree
00128 {
00129 public:
00130     inline void static Delete( const P * p )
00131     {
00132         if ( 0 != p )
00133         {
00134             p->~P();
00135             ::free( p );
00136         }
00137     }
00138 
00140     inline static P * Default( void )
00141     {
00142         return 0;
00143     }
00144 
00145     inline void Swap( DeleteUsingFree & ) {}
00146 };
00147 
00156 
00157 template < class P >
00158 class DeleteNothing
00159 {
00160 public:
00161     inline static void Delete( const P * )
00162     {
00163         // Do nothing at all!
00164     }
00165 
00166     inline static P * Default( void )
00167     {
00168         return 0;
00169     }
00170 
00171     inline void Swap( DeleteNothing & ) {}
00172 };
00173 
00181 
00182 template < class P >
00183 class DeleteSingle
00184 {
00185 public:
00186     inline static void Delete( const P * p )
00187     {
00193         typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
00194         delete p;
00195     }
00196 
00197     inline static P * Default( void )
00198     {
00199         return 0;
00200     }
00201 
00202     inline void Swap( DeleteSingle & ) {}
00203 };
00204 
00212 
00213 template < class P >
00214 class DeleteArray
00215 {
00216 public:
00217     inline static void Delete( const P * p )
00218     {
00224         typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
00225         delete [] p;
00226     }
00227 
00228     inline static P * Default( void )
00229     {
00230         return 0;
00231     }
00232 
00233     inline void Swap( DeleteArray & ) {}
00234 };
00235 
00244 
00245 template < class P >
00246 struct CantResetWithStrong
00247 {
00248     inline bool OnReleaseAll( bool hasStrongPtr ) const
00249     {
00250         return ! hasStrongPtr;
00251     }
00252 
00253     inline bool OnResetAll( bool hasStrongPtr ) const
00254     {
00255         return ! hasStrongPtr;
00256     }
00257 };
00258 
00266 
00267 template < class P >
00268 struct AllowReset
00269 {
00270     inline bool OnReleaseAll( bool ) const
00271     {
00272         return true;
00273     }
00274     inline bool OnResetAll( bool ) const
00275     {
00276         return true;
00277     }
00278 };
00279 
00287 
00288 template < class P >
00289 struct NeverReset
00290 {
00291     inline bool OnReleaseAll( bool ) const
00292     {
00293         return false;
00294     }
00295     inline bool OnResetAll( bool ) const
00296     {
00297         return false;
00298     }
00299 };
00300 
00301 // ----------------------------------------------------------------------------
00302 
00303 namespace Private
00304 {
00305 
00317 
00318 class LOKI_EXPORT TwoRefCountInfo
00319 {
00320 public:
00321 
00322     inline explicit TwoRefCountInfo( bool strong )
00323         : m_pointer( 0 )
00324         , m_strongCount( strong ? 1 : 0 )
00325         , m_weakCount( strong ? 0 : 1 )
00326     {
00327     }
00328 
00329     inline TwoRefCountInfo( void * p, bool strong )
00330         : m_pointer( p )
00331         , m_strongCount( strong ? 1 : 0 )
00332         , m_weakCount( strong ? 0 : 1 )
00333     {
00334     }
00335 
00336     inline ~TwoRefCountInfo( void )
00337     {
00338         assert( 0 == m_strongCount );
00339         assert( 0 == m_weakCount );
00340     }
00341 
00342     inline bool HasStrongPointer( void ) const
00343     {
00344         return ( 0 < m_strongCount );
00345     }
00346 
00347     inline bool HasWeakPointer( void ) const
00348     {
00349         return ( 0 < m_weakCount );
00350     }
00351 
00352     inline void IncStrongCount( void )
00353     {
00354         ++m_strongCount;
00355     }
00356 
00357     inline void IncWeakCount( void )
00358     {
00359         ++m_weakCount;
00360     }
00361 
00362     inline void DecStrongCount( void )
00363     {
00364         assert( 0 < m_strongCount );
00365         --m_strongCount;
00366     }
00367 
00368     inline void DecWeakCount( void )
00369     {
00370         assert( 0 < m_weakCount );
00371         --m_weakCount;
00372     }
00373 
00374     inline void ZapPointer( void )
00375     {
00376         m_pointer = 0;
00377     }
00378 
00379     void SetPointer( void * p )
00380     {
00381         m_pointer = p;
00382     }
00383 
00384     inline void * GetPointer( void ) const
00385     {
00386         return m_pointer;
00387     }
00388 
00389     inline void * & GetPointerRef( void ) const
00390     {
00391         return const_cast< void * & >( m_pointer );
00392     }
00393 
00394 private:
00396     TwoRefCountInfo( const TwoRefCountInfo & );
00398     TwoRefCountInfo & operator = ( const TwoRefCountInfo & );
00399 
00400     void * m_pointer;
00401     unsigned int m_strongCount;
00402     unsigned int m_weakCount;
00403 };
00404 
00422 
00423 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
00424 
00425 class LOKI_EXPORT LockableTwoRefCountInfo
00426     : private Loki::Private::TwoRefCountInfo
00427 {
00428 public:
00429 
00430     inline explicit LockableTwoRefCountInfo( bool strong )
00431         : TwoRefCountInfo( strong )
00432         , m_Mutex()
00433     {
00434     }
00435 
00436     LockableTwoRefCountInfo( void * p, bool strong )
00437         : TwoRefCountInfo( p, strong )
00438         , m_Mutex()
00439     {
00440     }
00441 
00442     inline ~LockableTwoRefCountInfo( void )
00443     {
00444     }
00445 
00446     inline void Lock( void ) const
00447     {
00448         m_Mutex.Lock();
00449     }
00450 
00451     inline void Unlock( void ) const
00452     {
00453         m_Mutex.Unlock();
00454     }
00455 
00456     inline bool HasStrongPointer( void ) const
00457     {
00458         m_Mutex.Lock();
00459         const bool has = TwoRefCountInfo::HasStrongPointer();
00460         m_Mutex.Unlock();
00461         return has;
00462     }
00463 
00464     inline bool HasWeakPointer( void ) const
00465     {
00466         m_Mutex.Lock();
00467         const bool has = TwoRefCountInfo::HasWeakPointer();
00468         m_Mutex.Unlock();
00469         return has;
00470     }
00471 
00472     inline void IncStrongCount( void )
00473     {
00474         m_Mutex.Lock();
00475         TwoRefCountInfo::IncStrongCount();
00476         m_Mutex.Unlock();
00477     }
00478 
00479     inline void IncWeakCount( void )
00480     {
00481         m_Mutex.Lock();
00482         TwoRefCountInfo::IncWeakCount();
00483         m_Mutex.Unlock();
00484     }
00485 
00486     inline void DecStrongCount( void )
00487     {
00488         m_Mutex.Lock();
00489         TwoRefCountInfo::DecStrongCount();
00490         m_Mutex.Unlock();
00491     }
00492 
00493     inline void DecWeakCount( void )
00494     {
00495         m_Mutex.Lock();
00496         TwoRefCountInfo::DecWeakCount();
00497         m_Mutex.Unlock();
00498     }
00499 
00500     inline void ZapPointer( void )
00501     {
00502         m_Mutex.Lock();
00503         TwoRefCountInfo::ZapPointer();
00504         m_Mutex.Unlock();
00505     }
00506 
00507     void SetPointer( void * p )
00508     {
00509         m_Mutex.Lock();
00510         TwoRefCountInfo::SetPointer( p );
00511         m_Mutex.Unlock();
00512     }
00513 
00514     inline void * GetPointer( void ) const
00515     {
00516         return TwoRefCountInfo::GetPointer();
00517     }
00518 
00519     inline void * & GetPointerRef( void ) const
00520     {
00521         return TwoRefCountInfo::GetPointerRef();
00522     }
00523 
00524 private:
00526     LockableTwoRefCountInfo( void );
00528     LockableTwoRefCountInfo( const LockableTwoRefCountInfo & );
00530     LockableTwoRefCountInfo & operator = ( const LockableTwoRefCountInfo & );
00531 
00532     mutable LOKI_DEFAULT_MUTEX m_Mutex;
00533 };
00534 
00535 #endif // if object-level-locking or class-level-locking
00536 
00537 } // end namespace Private
00538 
00549 
00550 class LOKI_EXPORT TwoRefCounts
00551 {
00552 protected:
00553 
00554     explicit TwoRefCounts( bool strong );
00555 
00556     TwoRefCounts( const void * p, bool strong );
00557 
00558     TwoRefCounts( const TwoRefCounts & rhs, bool strong ) :
00559         m_counts( rhs.m_counts )
00560     {
00561         Increment( strong );
00562     }
00563 
00564     inline bool Release( bool strong )
00565     {
00566         return Decrement( strong );
00567     }
00568 
00569     void Increment( bool strong );
00570 
00571     bool Decrement( bool strong );
00572 
00573     bool HasStrongPointer( void ) const
00574     {
00575         return m_counts->HasStrongPointer();
00576     }
00577 
00578     void Swap( TwoRefCounts & rhs );
00579 
00580     void SetPointer( void * p )
00581     {
00582         m_counts->SetPointer( p );
00583     }
00584 
00585     void ZapPointer( void );
00586 
00587     inline void * & GetPointerRef( void ) const
00588     {
00589         return m_counts->GetPointerRef();
00590     }
00591 
00592     inline void * GetPointer( void ) const
00593     {
00594         return m_counts->GetPointer();
00595     }
00596 
00597 private:
00598     TwoRefCounts( void );
00599     TwoRefCounts & operator = ( const TwoRefCounts & );
00600 
00602     Loki::Private::TwoRefCountInfo * m_counts;
00603 };
00604 
00619 
00620 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
00621 
00622 class LOKI_EXPORT LockableTwoRefCounts
00623 {
00624     typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
00625 
00626 protected:
00627 
00628     explicit LockableTwoRefCounts( bool strong )
00629         : m_counts( NULL )
00630     {
00631         void * temp = ThreadSafePointerAllocator::operator new(
00632             sizeof(Loki::Private::LockableTwoRefCountInfo) );
00633 #ifdef DO_EXTRA_LOKI_TESTS
00634         assert( temp != 0 );
00635 #endif
00636         m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
00637     }
00638 
00639     LockableTwoRefCounts( const void * p, bool strong )
00640         : m_counts( NULL )
00641     {
00642         void * temp = ThreadSafePointerAllocator::operator new(
00643             sizeof(Loki::Private::LockableTwoRefCountInfo) );
00644 #ifdef DO_EXTRA_LOKI_TESTS
00645         assert( temp != 0 );
00646 #endif
00647         void * p2 = const_cast< void * >( p );
00648         m_counts = new ( temp )
00649             Loki::Private::LockableTwoRefCountInfo( p2, strong );
00650     }
00651 
00652     LockableTwoRefCounts( const LockableTwoRefCounts & rhs, bool strong ) :
00653         m_counts( rhs.m_counts )
00654     {
00655         Increment( strong );
00656     }
00657 
00658     inline void Lock( void ) const
00659     {
00660         m_counts->Lock();
00661     }
00662 
00663     inline void Unlock( void ) const
00664     {
00665         m_counts->Unlock();
00666     }
00667 
00668     inline bool Release( bool strong )
00669     {
00670         return Decrement( strong );
00671     }
00672 
00673     void Increment( bool strong )
00674     {
00675         if ( strong )
00676         {
00677             m_counts->IncStrongCount();
00678         }
00679         else
00680         {
00681             m_counts->IncWeakCount();
00682         }
00683     }
00684 
00685     bool Decrement( bool strong )
00686     {
00687         if ( strong )
00688         {
00689             m_counts->DecStrongCount();
00690         }
00691         else
00692         {
00693             m_counts->DecWeakCount();
00694         }
00695         return !m_counts->HasStrongPointer();
00696     }
00697 
00698     bool HasStrongPointer( void ) const
00699     {
00700         return m_counts->HasStrongPointer();
00701     }
00702 
00703     void Swap( LockableTwoRefCounts & rhs )
00704     {
00705         std::swap( m_counts, rhs.m_counts );
00706     }
00707 
00708     void SetPointer( void * p )
00709     {
00710         m_counts->SetPointer( p );
00711     }
00712 
00713     void ZapPointer( void )
00714     {
00715 #ifdef DO_EXTRA_LOKI_TESTS
00716         assert( !m_counts->HasStrongPointer() );
00717 #endif
00718         if ( m_counts->HasWeakPointer() )
00719         {
00720             m_counts->ZapPointer();
00721         }
00722         else
00723         {
00724             ThreadSafePointerAllocator::operator delete ( m_counts,
00725                 sizeof(Loki::Private::LockableTwoRefCountInfo) );
00726             m_counts = NULL;
00727         }
00728     }
00729 
00730     inline void * GetPointer( void ) const
00731     {
00732         return m_counts->GetPointer();
00733     }
00734 
00735     inline void * & GetPointerRef( void ) const
00736     {
00737         return m_counts->GetPointerRef();
00738     }
00739 
00740 private:
00741     LockableTwoRefCounts( void );
00742     LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & );
00743 
00745     Loki::Private::LockableTwoRefCountInfo * m_counts;
00746 };
00747 
00748 #endif // if object-level-locking or class-level-locking
00749 
00759 
00760 class LOKI_EXPORT TwoRefLinks
00761 {
00762 protected:
00763 
00764     inline explicit TwoRefLinks( bool strong )
00765         : m_pointer( 0 )
00766         , m_strong( strong )
00767     {
00768         m_prev = m_next = this;
00769     }
00770 
00771     TwoRefLinks( const void * p, bool strong );
00772 
00773     TwoRefLinks( const TwoRefLinks & rhs, bool strong );
00774 
00775     bool Release( bool strong );
00776 
00777     void Swap( TwoRefLinks & rhs );
00778 
00779     bool Merge( TwoRefLinks & rhs );
00780 
00781     bool HasStrongPointer( void ) const;
00782 
00783     inline void ZapPointer( void )
00784     {
00785         ZapAllNodes();
00786     }
00787 
00788     void SetPointer( void * p );
00789 
00790     inline void * GetPointer( void ) const
00791     {
00792         return m_pointer;
00793     }
00794 
00795     inline void * & GetPointerRef( void ) const
00796     {
00797         return const_cast< void * & >( m_pointer );
00798     }
00799 
00800 private:
00801     static unsigned int CountPrevCycle( const TwoRefLinks * pThis );
00802     static unsigned int CountNextCycle( const TwoRefLinks * pThis );
00803 
00805     TwoRefLinks( void );
00807     TwoRefLinks & operator = ( const TwoRefLinks & );
00808 
00809     bool HasPrevNode( const TwoRefLinks * p ) const;
00810     bool HasNextNode( const TwoRefLinks * p ) const;
00811     bool AllNodesHaveSamePointer( void ) const;
00812     void ZapAllNodes( void );
00813 
00814     void * m_pointer;
00815     mutable TwoRefLinks * m_prev;
00816     mutable TwoRefLinks * m_next;
00817     const bool m_strong;
00818 };
00819 
00833 
00834 template
00835 <
00836     typename T,
00837     bool Strong = true,
00838     class OwnershipPolicy = Loki::TwoRefCounts,
00839     class ConversionPolicy = Loki::DisallowConversion,
00840     template < class > class CheckingPolicy = Loki::AssertCheck,
00841     template < class > class ResetPolicy = Loki::CantResetWithStrong,
00842     template < class > class DeletePolicy = Loki::DeleteSingle,
00843     template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
00844 >
00845 class StrongPtr
00846     : public OwnershipPolicy
00847     , public ConversionPolicy
00848     , public CheckingPolicy< T * >
00849     , public ResetPolicy< T >
00850     , public DeletePolicy< T >
00851 {
00852     typedef ConversionPolicy CP;
00853     typedef CheckingPolicy< T * > KP;
00854     typedef ResetPolicy< T > RP;
00855     typedef DeletePolicy< T > DP;
00856 
00857 public:
00858 
00859     typedef OwnershipPolicy OP;
00860 
00861     typedef T * StoredType;    // the type of the pointer
00862     typedef T * PointerType;   // type returned by operator->
00863     typedef T & ReferenceType; // type returned by operator*
00864 
00865     typedef typename ConstnessPolicy< T >::Type * ConstPointerType;
00866     typedef typename ConstnessPolicy< T >::Type & ConstReferenceType;
00867 
00868 private:
00869     struct NeverMatched {};
00870 
00871 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
00872     typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
00873     typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
00874 #else
00875     typedef const StoredType& ImplicitArg;
00876     typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
00877 #endif
00878 
00879 public:
00880 
00881     StrongPtr( void ) : OP( Strong )
00882     {
00883         KP::OnDefault( GetPointer() );
00884     }
00885 
00886     explicit StrongPtr( ExplicitArg p ) : OP( p, Strong )
00887     {
00888         KP::OnInit( GetPointer() );
00889     }
00890 
00891     StrongPtr( ImplicitArg p ) : OP( p, Strong )
00892     {
00893         KP::OnInit( GetPointer() );
00894     }
00895 
00896     StrongPtr( const StrongPtr & rhs )
00897         : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs )
00898     {
00899     }
00900 
00901     template
00902     <
00903         typename T1,
00904         bool S1,
00905         class OP1,
00906         class CP1,
00907         template < class > class KP1,
00908         template < class > class RP1,
00909         template < class > class DP1,
00910         template < class > class CNP1
00911     >
00912     StrongPtr(
00913         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
00914         : OP( rhs, Strong )
00915     {
00916     }
00917 
00918     template
00919     <
00920         typename T1,
00921         bool S1,
00922         class OP1,
00923         class CP1,
00924         template < class > class KP1,
00925         template < class > class RP1,
00926         template < class > class DP1,
00927         template < class > class CNP1
00928     >
00929     StrongPtr(
00930         StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
00931         : OP( rhs, Strong )
00932     {
00933     }
00934 
00935     StrongPtr( RefToValue< StrongPtr > rhs )
00936         : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs )
00937     {
00938     }
00939 
00940     operator RefToValue< StrongPtr >( void )
00941     {
00942         return RefToValue< StrongPtr >( *this );
00943     }
00944 
00945     StrongPtr & operator = ( const StrongPtr & rhs )
00946     {
00947         if ( GetPointer() != rhs.GetPointer() )
00948         {
00949             StrongPtr temp( rhs );
00950             temp.Swap( *this );
00951         }
00952         return *this;
00953     }
00954 
00955     StrongPtr & operator = ( T * p )
00956     {
00957         if ( GetPointer() != p )
00958         {
00959             StrongPtr temp( p );
00960             Swap( temp );
00961         }
00962         return *this;
00963     }
00964 
00965     template
00966     <
00967         typename T1,
00968         bool S1,
00969         class OP1,
00970         class CP1,
00971         template < class > class KP1,
00972         template < class > class RP1,
00973         template < class > class DP1,
00974         template < class > class CNP1
00975     >
00976     StrongPtr & operator = (
00977         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
00978     {
00979         if ( !rhs.Equals( GetPointer() ) )
00980         {
00981             StrongPtr temp( rhs );
00982             temp.Swap( *this );
00983         }
00984         return *this;
00985     }
00986 
00987     bool IsStrong( void ) const
00988     {
00989         return Strong;
00990     }
00991 
00992     void Swap( StrongPtr & rhs )
00993     {
00994         OP::Swap( rhs );
00995         CP::Swap( rhs );
00996         KP::Swap( rhs );
00997         DP::Swap( rhs );
00998     }
00999 
01000     ~StrongPtr()
01001     {
01002         if ( OP::Release( Strong ) )
01003         {
01004             // Must zap the pointer before deleteing the object. Otherwise a
01005             // cycle of weak pointers will lead to recursion, which leads to
01006             // to deleting the shared object multiple times, which leads to
01007             // undefined behavior.  Therefore, this must get pointer before
01008             // zapping it, and then delete the temp pointer.
01009             T * p = GetPointer();
01010             if ( p != 0 )
01011             {
01012                 OP::ZapPointer();
01013                 DP::Delete( p );
01014             }
01015         }
01016     }
01017 
01018 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
01019 
01020     // old non standard in class definition of friends
01021     friend bool ReleaseAll( StrongPtr & sp,
01022         typename StrongPtr::StoredType & p )
01023     {
01024         if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
01025         {
01026             return false;
01027         }
01028         p = sp.GetPointer();
01029         sp.OP::SetPointer( sp.DP::Default() );
01030         return true;
01031     }
01032 
01033     friend bool ResetAll( StrongPtr & sp,
01034         typename StrongPtr::StoredType p )
01035     {
01036         if ( sp.OP::GetPointer() == p )
01037         {
01038             return true;
01039         }
01040         if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
01041         {
01042             return false;
01043         }
01044         sp.DP::Delete( sp.GetPointer() );
01045         sp.OP::SetPointer( p );
01046         return true;
01047     }
01048 
01049 #else
01050   
01051     template
01052     <
01053         typename T1,
01054         bool S1,
01055         class OP1,
01056         class CP1,
01057         template < class > class KP1,
01058         template < class > class RP1,
01059         template < class > class DP1,
01060         template < class > class CNP1
01061     >
01062     friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
01063         typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType & p );
01064  
01065 
01066     template
01067     <
01068         typename T1,
01069         bool S1,
01070         class OP1,
01071         class CP1,
01072         template < class > class KP1,
01073         template < class > class RP1,
01074         template < class > class DP1,
01075         template < class > class CNP1
01076     >
01077     friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
01078         typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p );
01079 
01080 #endif
01081 
01082 
01087     template
01088     <
01089         typename T1,
01090         bool S1,
01091         class OP1,
01092         class CP1,
01093         template < class > class KP1,
01094         template < class > class RP1,
01095         template < class > class DP1,
01096         template < class > class CNP1
01097     >
01098     bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
01099     {
01100         if ( OP::GetPointer() != rhs.OP::GetPointer() )
01101         {
01102             return false;
01103         }
01104         return OP::Merge( rhs );
01105     }
01106 
01110     void Lock( void )
01111     {
01112         OP::Lock();
01113     }
01114 
01118     void Unlock( void )
01119     {
01120         OP::Unlock();
01121     }
01122 
01123     PointerType operator -> ()
01124     {
01125         KP::OnDereference( GetPointer() );
01126         return GetPointer();
01127     }
01128 
01129     ConstPointerType operator -> () const
01130     {
01131         KP::OnDereference( GetPointer() );
01132         return GetPointer();
01133     }
01134 
01135     ReferenceType operator * ()
01136     {
01137         KP::OnDereference( GetPointer() );
01138         return * GetPointer();
01139     }
01140 
01141     ConstReferenceType operator * () const
01142     {
01143         KP::OnDereference( GetPointer() );
01144         return * GetPointer();
01145     }
01146 
01148     template < class T1 >
01149     bool Equals( const T1 * p ) const
01150     {
01151         return ( GetPointer() == p );
01152     }
01153 
01155     template < class T1 >
01156     bool LessThan( const T1 * p ) const
01157     {
01158         return ( GetPointer() < p );
01159     }
01160 
01162     template < class T1 >
01163     bool GreaterThan( const T1 * p ) const
01164     {
01165         return ( GetPointer() > p );
01166     }
01167 
01169     template
01170     <
01171         typename T1,
01172         bool S1,
01173         class OP1,
01174         class CP1,
01175         template < class > class KP1,
01176         template < class > class RP1,
01177         template < class > class DP1,
01178         template < class > class CNP1
01179     >
01180     bool operator == (
01181         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01182     {
01183         return ( rhs.Equals( GetPointer() ) );
01184     }
01185 
01187     template
01188     <
01189         typename T1,
01190         bool S1,
01191         class OP1,
01192         class CP1,
01193         template < class > class KP1,
01194         template < class > class RP1,
01195         template < class > class DP1,
01196         template < class > class CNP1
01197     >
01198     bool operator != (
01199         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01200     {
01201         return !( rhs.Equals( GetPointer() ) );
01202     }
01203 
01205     template
01206     <
01207         typename T1,
01208         bool S1,
01209         class OP1,
01210         class CP1,
01211         template < class > class KP1,
01212         template < class > class RP1,
01213         template < class > class DP1,
01214         template < class > class CNP1
01215     >
01216     bool operator < (
01217         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01218     {
01219         return ( rhs.GreaterThan( GetPointer() ) );
01220     }
01221 
01223     template
01224     <
01225         typename T1,
01226         bool S1,
01227         class OP1,
01228         class CP1,
01229         template < class > class KP1,
01230         template < class > class RP1,
01231         template < class > class DP1,
01232         template < class > class CNP1
01233     >
01234     inline bool operator > (
01235         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01236     {
01237         return ( rhs.LessThan( GetPointer() ) );
01238     }
01239 
01241     template
01242     <
01243         typename T1,
01244         bool S1,
01245         class OP1,
01246         class CP1,
01247         template < class > class KP1,
01248         template < class > class RP1,
01249         template < class > class DP1,
01250         template < class > class CNP1
01251     >
01252     inline bool operator <= (
01253         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01254     {
01255         return !( rhs.LessThan( GetPointer() ) );
01256     }
01257 
01259     template
01260     <
01261         typename T1,
01262         bool S1,
01263         class OP1,
01264         class CP1,
01265         template < class > class KP1,
01266         template < class > class RP1,
01267         template < class > class DP1,
01268         template < class > class CNP1
01269     >
01270     inline bool operator >= (
01271         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
01272     {
01273         return !( rhs.GreaterThan( GetPointer() ) );
01274     }
01275 
01276     inline bool operator ! () const // Enables "if ( !sp ) ..."
01277     {
01278         return ( 0 == OP::GetPointer() );
01279     }
01280 
01281 protected:
01282 
01283     inline PointerType GetPointer( void )
01284     {
01285         return reinterpret_cast< PointerType >( OP::GetPointer() );
01286     }
01287 
01288     inline ConstPointerType GetPointer( void ) const
01289     {
01290         return reinterpret_cast< ConstPointerType >( OP::GetPointer() );
01291     }
01292 
01293 private:
01294 
01295     inline ReferenceType GetPointerRef( void )
01296     {
01297         return reinterpret_cast< ReferenceType >( OP::GetPointerRef() );
01298     }
01299 
01300     inline ConstReferenceType GetPointerRef( void ) const
01301     {
01302         return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() );
01303     }
01304 
01305     // Helper for enabling 'if (sp)'
01306     struct Tester
01307     {
01308         Tester(int) {}
01309         void dummy() {}
01310     };
01311     
01312     typedef void (Tester::*unspecified_boolean_type_)();
01313 
01314     typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result
01315         unspecified_boolean_type;
01316 
01317 public:
01318     // enable 'if (sp)'
01319     operator unspecified_boolean_type() const
01320     {
01321         return !*this ? 0 : &Tester::dummy;
01322     }
01323 
01324 private:
01325     // Helper for disallowing automatic conversion
01326     struct Insipid
01327     {
01328         Insipid(PointerType) {}
01329     };
01330     
01331     typedef typename Select< CP::allow, PointerType, Insipid >::Result
01332         AutomaticConversionResult;
01333 
01334 public:        
01335     operator AutomaticConversionResult() const
01336     {
01337         return GetPointer();
01338     }
01339 
01340 };
01341 
01342 // ----------------------------------------------------------------------------
01343 
01344 // friend functions
01345 
01346 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
01347 
01348 template
01349 <
01350     typename U,
01351     typename T,
01352     bool S,
01353     class OP,
01354     class CP,
01355     template < class > class KP,
01356     template < class > class RP,
01357     template < class > class DP,
01358     template < class > class CNP
01359 >
01360 bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
01361                  typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p )
01362 {
01363   if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
01364   {
01365     return false;
01366   }
01367   p = sp.GetPointer();
01368   sp.OP::SetPointer( sp.DP<T>::Default() );
01369   return true;
01370 }
01371 
01372 template
01373 <
01374     typename U,
01375     typename T,
01376     bool S,
01377     class OP,
01378     class CP,
01379     template < class > class KP,
01380     template < class > class RP,
01381     template < class > class DP,
01382     template < class > class CNP
01383 >
01384 bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
01385                typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p )
01386 {
01387   if ( sp.OP::GetPointer() == p )
01388   {
01389     return true;
01390   }
01391   if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
01392   {
01393     return false;
01394   }
01395   sp.DP<T>::Delete( sp.GetPointer() );
01396   sp.OP::SetPointer( p );
01397   return true;
01398 }
01399 #endif
01400 
01401 
01402 // free comparison operators for class template StrongPtr
01403 
01406 template
01407 <
01408     typename U,
01409     typename T,
01410     bool S,
01411     class OP,
01412     class CP,
01413     template < class > class KP,
01414     template < class > class RP,
01415     template < class > class DP,
01416     template < class > class CNP
01417 >
01418 inline bool operator == (
01419     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01420 {
01421     return ( lhs.Equals( rhs ) );
01422 }
01423 
01426 template
01427 <
01428     typename U,
01429     typename T,
01430     bool S,
01431     class OP,
01432     class CP,
01433     template < class > class KP,
01434     template < class > class RP,
01435     template < class > class DP,
01436     template < class > class CNP
01437 >
01438 inline bool operator == ( U * lhs,
01439     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01440 {
01441     return ( rhs.Equals( lhs ) );
01442 }
01443 
01446 template
01447 <
01448     typename U,
01449     typename T,
01450     bool S,
01451     class OP,
01452     class CP,
01453     template < class > class KP,
01454     template < class > class RP,
01455     template < class > class DP,
01456     template < class > class CNP
01457 >
01458 inline bool operator != (
01459     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01460 {
01461     return !( lhs.Equals( rhs ) );
01462 }
01463 
01466 template
01467 <
01468     typename U,
01469     typename T,
01470     bool S,
01471     class OP,
01472     class CP,
01473     template < class > class KP,
01474     template < class > class RP,
01475     template < class > class DP,
01476     template < class > class CNP
01477 >
01478 inline bool operator != ( U * lhs,
01479     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01480 {
01481     return !( rhs.Equals( lhs ) );
01482 }
01483 
01486 template
01487 <
01488     typename U,
01489     typename T,
01490     bool S,
01491     class OP,
01492     class CP,
01493     template < class > class KP,
01494     template < class > class RP,
01495     template < class > class DP,
01496     template < class > class CNP
01497 >
01498 inline bool operator < (
01499     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01500 {
01501     return ( lhs.LessThan( rhs ) );
01502 }
01503 
01506 template
01507 <
01508     typename U,
01509     typename T,
01510     bool S,
01511     class OP,
01512     class CP,
01513     template < class > class KP,
01514     template < class > class RP,
01515     template < class > class DP,
01516     template < class > class CNP
01517 >
01518 inline bool operator < ( U * lhs,
01519     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01520 {
01521     return ( rhs.GreaterThan( lhs ) );
01522 }
01523 
01524 //  operator> for lhs = StrongPtr, rhs = raw pointer
01526 template
01527 <
01528     typename U,
01529     typename T,
01530     bool S,
01531     class OP,
01532     class CP,
01533     template < class > class KP,
01534     template < class > class RP,
01535     template < class > class DP,
01536     template < class > class CNP
01537 >
01538 inline bool operator > (
01539     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01540 {
01541     return ( lhs.GreaterThan( rhs ) );
01542 }
01543 
01546 template
01547 <
01548     typename U,
01549     typename T,
01550     bool S,
01551     class OP,
01552     class CP,
01553     template < class > class KP,
01554     template < class > class RP,
01555     template < class > class DP,
01556     template < class > class CNP
01557 >
01558 inline bool operator > ( U * lhs,
01559     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01560 {
01561     return ( rhs.LessThan( lhs ) );
01562 }
01563 
01566 template
01567 <
01568     typename U,
01569     typename T,
01570     bool S,
01571     class OP,
01572     class CP,
01573     template < class > class KP,
01574     template < class > class RP,
01575     template < class > class DP,
01576     template < class > class CNP
01577 >
01578 inline bool operator <= (
01579     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01580 {
01581     return !( lhs.GreaterThan( rhs ) );
01582 }
01583 
01586 template
01587 <
01588     typename U,
01589     typename T,
01590     bool S,
01591     class OP,
01592     class CP,
01593     template < class > class KP,
01594     template < class > class RP,
01595     template < class > class DP,
01596     template < class > class CNP
01597 >
01598 inline bool operator <= ( U * lhs,
01599     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01600 {
01601     return !( rhs.LessThan( lhs ) );
01602 }
01603 
01606 template
01607 <
01608     typename U,
01609     typename T,
01610     bool S,
01611     class OP,
01612     class CP,
01613     template < class > class KP,
01614     template < class > class RP,
01615     template < class > class DP,
01616     template < class > class CNP
01617 >
01618 inline bool operator >= (
01619     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
01620 {
01621     return !( lhs.LessThan( rhs ) );
01622 }
01623 
01626 template
01627 <
01628     typename U,
01629     typename T,
01630     bool S,
01631     class OP,
01632     class CP,
01633     template < class > class KP,
01634     template < class > class RP,
01635     template < class > class DP,
01636     template < class > class CNP
01637 >
01638 inline bool operator >= ( U * lhs,
01639     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
01640 {
01641     return !( rhs.GreaterThan( lhs ) );
01642 }
01643 
01644 } // namespace Loki
01645 
01646 namespace std
01647 {
01652     template
01653     <
01654         typename T,
01655         bool S,
01656         class OP,
01657         class CP,
01658         template < class > class KP,
01659         template < class > class RP,
01660         template < class > class DP,
01661         template < class > class CNP
01662     >
01663     struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
01664         : public binary_function<
01665             Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
01666             Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
01667     {
01668         bool operator () (
01669             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
01670             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
01671         {
01672             return ( lhs < rhs );
01673         }
01674     };
01675 }
01676 
01678 
01679 #endif // end file guardian
01680 

Generated on Sun Feb 25 16:52:28 2007 for Loki by  doxygen 1.5.1-p1