diff options
Diffstat (limited to 'shared/loki/StrongPtr.h')
-rw-r--r-- | shared/loki/StrongPtr.h | 1697 |
1 files changed, 0 insertions, 1697 deletions
diff --git a/shared/loki/StrongPtr.h b/shared/loki/StrongPtr.h deleted file mode 100644 index 868eb48f..00000000 --- a/shared/loki/StrongPtr.h +++ /dev/null @@ -1,1697 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// The Loki Library -// Copyright (c) 2006 Rich Sposato -// The copyright on this file is protected under the terms of the MIT license. -// -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this -// permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" -// without express or implied warranty. -//////////////////////////////////////////////////////////////////////////////// -#ifndef LOKI_STRONG_PTR_INC_ -#define LOKI_STRONG_PTR_INC_ - -// $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $ - - -#include <loki/SmartPtr.h> -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) -#include <loki/Threads.h> -#endif - - -//////////////////////////////////////////////////////////////////////////////// -/// -/// \par Terminology -/// These terms are used within this file's comments. -/// -# StrongPtr : Class used to implement both strong and weak pointers. The -/// second template parameter determines if a StrongPtr is weak or strong. -/// -# Strong pointer : A pointer that claims ownership of a shared object. -/// When the last strong copointer dies, the object is destroyed even if -/// there are weak copointers. -/// -# Weak pointer : A pointer that does not own the shared object it points -/// to. It only destroys the shared object if there no strong copointers -/// exist when it dies. -/// -# Copointers : All the pointers that refer to the same shared object. -/// The copointers must have the same ownership policy, but the other -/// policies may be different. -/// -# Pointee : The shared object. -/// -/// \par OwnershipPolicy -/// The ownership policy has the pointer to the actual object, and it also -/// keeps track of the strong and weak copointers so that it can know if any -/// strong copointers remain. The plain pointer it maintains is stored as a -/// void pointer, which allows the ownership policy classes to be monolithic -/// classes instead of template classes. As monolithic classes, they reduce -/// amount of code-bloat. -/// -/// \par Writing Your Own OwnershipPolicy -/// If you write your own policy, you must implement these 12 functions: -/// -# explicit YourPolicy( bool strong ) -/// -# YourPolicy( void * p, bool strong ) -/// -# YourPolicy( const YourPolicy & rhs, bool strong ) -/// -# bool Release( bool strong ) -/// -# void Increment( bool strong ) -/// -# bool Decrement( bool strong ) -/// -# bool HasStrongPointer( void ) const -/// -# void Swap( YourPolicy & rhs ) -/// -# void SetPointer( void * p ) -/// -# void ZapPointer( void ) -/// -# void * GetPointer( void ) const -/// -# void * & GetPointerRef( void ) const -/// It is strongly recommended that all 12 of these functions be protected -/// instead of public. These two functions are optional for single-threaded -/// policies, but required for multi-threaded policies: -/// -# void Lock( void ) const -/// -# void Unlock( void ) const -/// This function is entirely optional: -/// -# bool Merge( TwoRefLinks & rhs ) -/// -/// \par DeletePolicy -/// The delete policy provides a mechanism to destroy an object and a default -/// value for an uninitialized pointer. You can override this policy with -/// your own when using the Singleton, NullObject, or Prototype design -/// patterns. -/// -/// \par Writing Your Own DeletePolicy -/// If you write your own policy, you must implement these 3 functions: -/// -# void static Delete( const P * p ) -/// -# static P * Default( void ) -/// -# void Swap( YourResetPolicy & ) -/// -/// \par ResetPolicy -/// A reset policy tells the ReleaseAll and ResetAll functions whether they -/// should release or reset the StrongPtr copointers. These functions do -/// not affect just one StrongPtr, but all copointers. That is unlike -/// SmartPtr where the Release and Reset functions only affect 1 SmartPtr, -/// and leave all copointers untouched. A useful trick you can do with the -/// ResetPolicy is to not allow reset when a strong pointer exists, and then -/// use the NoCheck policy for all strong pointers. The reset policy -/// guarantees the strong pointers always have a valid pointee, so checking -/// is not required; but weak pointers may still require checking. -/// -/// \par Writing Your Own ResetPolicy -/// If you write your own policy, you must implement these 2 functions: -/// -# bool OnReleaseAll( bool ) const -/// -# bool OnResetAll( bool ) const -/// The bool parameter means that this was called with a strong pointer or -/// one of its copointers is strong. The return value means the pointer -/// can be reset or released. -/// -/// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies -/// \ingroup SmartPointerGroup -/// \defgroup StrongPointerDeleteGroup Delete policies -/// \ingroup SmartPointerGroup -/// \defgroup StrongPointerResetGroup Reset policies -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - - -namespace Loki -{ - - -//////////////////////////////////////////////////////////////////////////////// -/// \class DeleteUsingFree -/// -/// \ingroup StrongPointerDeleteGroup -/// Implementation of the DeletePolicy used by StrongPtr. Uses explicit call -/// to T's destructor followed by call to free. This policy is useful for -/// managing the lifetime of pointers to structs returned by C functions. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -class DeleteUsingFree -{ -public: - inline void static Delete( const P* p ) - { - if ( 0 != p ) - { - p->~P(); - ::free( p ); - } - } - - /// Provides default value to initialize the pointer - inline static P* Default( void ) - { - return 0; - } - - inline void Swap( DeleteUsingFree& ) {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class DeleteNothing -/// -/// \ingroup StrongPointerDeleteGroup -/// Implementation of the DeletePolicy used by StrongPtr. This will never -/// delete anything. You can use this policy with pointers to an undefined -/// type or a pure interface class with a protected destructor. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -class DeleteNothing -{ -public: - inline static void Delete( const P* ) - { - // Do nothing at all! - } - - inline static P* Default( void ) - { - return 0; - } - - inline void Swap( DeleteNothing& ) {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class DeleteSingle -/// -/// \ingroup StrongPointerDeleteGroup -/// Implementation of the DeletePolicy used by StrongPtr. This deletes just -/// one shared object. This is the default class for the DeletePolicy. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -class DeleteSingle -{ -public: - inline static void Delete( const P* p ) - { - /** @note If you see an error message about a negative subscript, that - means your are attempting to use Loki to delete an incomplete type. - Please don't use this policy with incomplete types; you may want to - use DeleteNothing instead. - */ - typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ]; - delete p; - } - - inline static P* Default( void ) - { - return 0; - } - - inline void Swap( DeleteSingle& ) {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class DeleteArray -/// -/// \ingroup StrongPointerDeleteGroup -/// Implementation of the DeletePolicy used by StrongPtr. This deletes an -/// array of shared objects. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -class DeleteArray -{ -public: - inline static void Delete( const P* p ) - { - /** @note If you see an error message about a negative subscript, that - means your are attempting to use Loki to delete an incomplete type. - Please don't use this policy with incomplete types; you may want to - use DeleteNothing instead. - */ - typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ]; - delete [] p; - } - - inline static P* Default( void ) - { - return 0; - } - - inline void Swap( DeleteArray& ) {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class CantResetWithStrong -/// -/// \ingroup StrongPointerResetGroup -/// Implementation of the ResetPolicy used by StrongPtr. This is the default -/// ResetPolicy for StrongPtr. It forbids reset and release only if a strong -/// copointer exists. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -struct CantResetWithStrong -{ - inline bool OnReleaseAll( bool hasStrongPtr ) const - { - return ! hasStrongPtr; - } - - inline bool OnResetAll( bool hasStrongPtr ) const - { - return ! hasStrongPtr; - } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class AllowReset -/// -/// \ingroup StrongPointerResetGroup -/// Implementation of the ResetPolicy used by StrongPtr. It allows reset and -/// release under any circumstance. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -struct AllowReset -{ - inline bool OnReleaseAll( bool ) const - { - return true; - } - inline bool OnResetAll( bool ) const - { - return true; - } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class NeverReset -/// -/// \ingroup StrongPointerResetGroup -/// Implementation of the ResetPolicy used by StrongPtr. It forbids reset and -/// release under any circumstance. -//////////////////////////////////////////////////////////////////////////////// - -template < class P > -struct NeverReset -{ - inline bool OnReleaseAll( bool ) const - { - return false; - } - inline bool OnResetAll( bool ) const - { - return false; - } -}; - -// ---------------------------------------------------------------------------- - -namespace Private -{ - -//////////////////////////////////////////////////////////////////////////////// -/// \class TwoRefCountInfo -/// -/// \ingroup StrongPointerOwnershipGroup -/// Implementation detail for reference counting strong and weak pointers. -/// It maintains a void pointer and 2 reference counts. Since it is just a -/// class for managing implementation details, it is not intended to be used -/// directly - which is why it is in a private namespace. Each instance is a -/// shared resource for all copointers, and there should be only one of these -/// for each set of copointers. This class is small, trivial, and inline. -//////////////////////////////////////////////////////////////////////////////// - -class LOKI_EXPORT TwoRefCountInfo -{ -public: - - inline explicit TwoRefCountInfo( bool strong ) - : m_pointer( 0 ) - , m_strongCount( strong ? 1 : 0 ) - , m_weakCount( strong ? 0 : 1 ) - { - } - - inline TwoRefCountInfo( void* p, bool strong ) - : m_pointer( p ) - , m_strongCount( strong ? 1 : 0 ) - , m_weakCount( strong ? 0 : 1 ) - { - } - - inline ~TwoRefCountInfo( void ) - { - assert( 0 == m_strongCount ); - assert( 0 == m_weakCount ); - } - - inline bool HasStrongPointer( void ) const - { - return ( 0 < m_strongCount ); - } - - inline bool HasWeakPointer( void ) const - { - return ( 0 < m_weakCount ); - } - - inline void IncStrongCount( void ) - { - ++m_strongCount; - } - - inline void IncWeakCount( void ) - { - ++m_weakCount; - } - - inline bool DecStrongCount( void ) - { - assert( 0 < m_strongCount ); - --m_strongCount; - const bool isZero = ( 0 == m_strongCount ); - return isZero; - } - - inline void DecWeakCount( void ) - { - assert( 0 < m_weakCount ); - --m_weakCount; - } - - inline void ZapPointer( void ) - { - m_pointer = 0; - } - - void SetPointer( void* p ) - { - m_pointer = p; - } - - inline void* GetPointer( void ) const - { - return m_pointer; - } - - inline void*& GetPointerRef( void ) const - { - return const_cast< void *& >( m_pointer ); - } - -private: - /// Copy-constructor not implemented. - TwoRefCountInfo( const TwoRefCountInfo& ); - /// Copy-assignment operator not implemented. - TwoRefCountInfo& operator = ( const TwoRefCountInfo& ); - - void* m_pointer; - unsigned int m_strongCount; - unsigned int m_weakCount; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class LockableTwoRefCountInfo -/// -/// \ingroup StrongPointerOwnershipGroup -/// Implementation detail for thread-safe reference counting for strong and -/// weak pointers. It uses TwoRefCountInfo to manage the pointer and counts. -/// All this does is provide a thread safety mechanism. Since it is just a -/// class for managing implementation details, it is not intended to be used -/// directly - which is why it is in a private namespace. Each instance is a -/// shared resource for all copointers, and there should be only one of these -/// for each set of copointers. This class is small, trivial, and inline. -/// -/// \note This class is not designed for use with a single-threaded model. -/// Tests using a single-threaded model will not run properly, but tests in a -/// multi-threaded model with either class-level-locking or object-level-locking -/// do run properly. -//////////////////////////////////////////////////////////////////////////////// - -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - -class LOKI_EXPORT LockableTwoRefCountInfo - : private Loki::Private::TwoRefCountInfo -{ -public: - - inline explicit LockableTwoRefCountInfo( bool strong ) - : TwoRefCountInfo( strong ) - , m_Mutex() - { - } - - LockableTwoRefCountInfo( void* p, bool strong ) - : TwoRefCountInfo( p, strong ) - , m_Mutex() - { - } - - inline ~LockableTwoRefCountInfo( void ) - { - } - - inline void Lock( void ) const - { - m_Mutex.Lock(); - } - - inline void Unlock( void ) const - { - m_Mutex.Unlock(); - } - - inline bool HasStrongPointer( void ) const - { - m_Mutex.Lock(); - const bool has = TwoRefCountInfo::HasStrongPointer(); - m_Mutex.Unlock(); - return has; - } - - inline bool HasWeakPointer( void ) const - { - m_Mutex.Lock(); - const bool has = TwoRefCountInfo::HasWeakPointer(); - m_Mutex.Unlock(); - return has; - } - - inline void IncStrongCount( void ) - { - m_Mutex.Lock(); - TwoRefCountInfo::IncStrongCount(); - m_Mutex.Unlock(); - } - - inline void IncWeakCount( void ) - { - m_Mutex.Lock(); - TwoRefCountInfo::IncWeakCount(); - m_Mutex.Unlock(); - } - - inline bool DecStrongCount( void ) - { - m_Mutex.Lock(); - const bool isZero = TwoRefCountInfo::DecStrongCount(); - m_Mutex.Unlock(); - return isZero; - } - - inline void DecWeakCount( void ) - { - m_Mutex.Lock(); - TwoRefCountInfo::DecWeakCount(); - m_Mutex.Unlock(); - } - - inline void ZapPointer( void ) - { - m_Mutex.Lock(); - TwoRefCountInfo::ZapPointer(); - m_Mutex.Unlock(); - } - - void SetPointer( void* p ) - { - m_Mutex.Lock(); - TwoRefCountInfo::SetPointer( p ); - m_Mutex.Unlock(); - } - - inline void* GetPointer( void ) const - { - return TwoRefCountInfo::GetPointer(); - } - - inline void*& GetPointerRef( void ) const - { - return TwoRefCountInfo::GetPointerRef(); - } - -private: - /// Default constructor is not available. - LockableTwoRefCountInfo( void ); - /// Copy constructor is not available. - LockableTwoRefCountInfo( const LockableTwoRefCountInfo& ); - /// Copy-assignment operator is not available. - LockableTwoRefCountInfo& operator = ( const LockableTwoRefCountInfo& ); - - mutable LOKI_DEFAULT_MUTEX m_Mutex; -}; - -#endif // if object-level-locking or class-level-locking - -} // end namespace Private - -//////////////////////////////////////////////////////////////////////////////// -/// \class TwoRefCounts -/// -/// \ingroup StrongPointerOwnershipGroup -/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a -/// shared instance of TwoRefCountInfo. This is the default policy for -/// OwnershipPolicy. Some functions are trivial enough to be inline, while -/// others are implemented elsewhere. It is not thread safe, and is intended -/// for single-threaded environments. -//////////////////////////////////////////////////////////////////////////////// - -class LOKI_EXPORT TwoRefCounts -{ -protected: - - explicit TwoRefCounts( bool strong ); - - TwoRefCounts( const void* p, bool strong ); - - TwoRefCounts( const TwoRefCounts& rhs, bool strong ) : - m_counts( rhs.m_counts ) - { - Increment( strong ); - } - - /** The destructor does not need to do anything since the call to - ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which - this dtor would have done. - */ - inline ~TwoRefCounts( void ) {} - - inline bool Release( bool strong ) - { - return Decrement( strong ); - } - - bool HasStrongPointer( void ) const - { - return m_counts->HasStrongPointer(); - } - - void Swap( TwoRefCounts& rhs ); - - void SetPointer( void* p ) - { - m_counts->SetPointer( p ); - } - - void ZapPointer( void ); - - inline void*& GetPointerRef( void ) const - { - return m_counts->GetPointerRef(); - } - - inline void* GetPointer( void ) const - { - return m_counts->GetPointer(); - } - -private: - TwoRefCounts( void ); - TwoRefCounts& operator = ( const TwoRefCounts& ); - - void Increment( bool strong ); - - bool Decrement( bool strong ); - - /// Pointer to all shared data. - Loki::Private::TwoRefCountInfo* m_counts; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class LockableTwoRefCounts -/// -/// \ingroup StrongPointerOwnershipGroup -/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a -/// shared instance of LockableTwoRefCountInfo. It behaves very similarly to -/// TwoRefCounts, except that it provides thread-safety. Some functions are -/// trivial enough to be inline, while others are implemented elsewhere. -/// -/// \note This class is not designed for use with a single-threaded model. -/// Tests using a single-threaded model will not run properly, but tests in a -/// multi-threaded model with either class-level-locking or object-level-locking -/// do run properly. -//////////////////////////////////////////////////////////////////////////////// - -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - -class LOKI_EXPORT LockableTwoRefCounts -{ - typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; - -protected: - - explicit LockableTwoRefCounts( bool strong ) - : m_counts( NULL ) - { - void* temp = ThreadSafePointerAllocator::operator new( - sizeof(Loki::Private::LockableTwoRefCountInfo) ); -#ifdef DO_EXTRA_LOKI_TESTS - assert( temp != 0 ); -#endif - m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong ); - } - - LockableTwoRefCounts( const void* p, bool strong ) - : m_counts( NULL ) - { - void* temp = ThreadSafePointerAllocator::operator new( - sizeof(Loki::Private::LockableTwoRefCountInfo) ); -#ifdef DO_EXTRA_LOKI_TESTS - assert( temp != 0 ); -#endif - void* p2 = const_cast< void* >( p ); - m_counts = new ( temp ) - Loki::Private::LockableTwoRefCountInfo( p2, strong ); - } - - LockableTwoRefCounts( const LockableTwoRefCounts& rhs, bool strong ) : - m_counts( rhs.m_counts ) - { - Increment( strong ); - } - - /** The destructor does not need to do anything since the call to - ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which - this dtor would have done. - */ - inline ~LockableTwoRefCounts( void ) {} - - inline void Lock( void ) const - { - m_counts->Lock(); - } - - inline void Unlock( void ) const - { - m_counts->Unlock(); - } - - inline bool Release( bool strong ) - { - return Decrement( strong ); - } - - void Increment( bool strong ) - { - if ( strong ) - { - m_counts->IncStrongCount(); - } - else - { - m_counts->IncWeakCount(); - } - } - - bool Decrement( bool strong ) - { - bool noStrongPointers = false; - if ( strong ) - { - noStrongPointers = m_counts->DecStrongCount(); - } - else - { - m_counts->DecWeakCount(); - noStrongPointers = !m_counts->HasStrongPointer(); - } - return noStrongPointers; - } - - bool HasStrongPointer( void ) const - { - return m_counts->HasStrongPointer(); - } - - void Swap( LockableTwoRefCounts& rhs ) - { - std::swap( m_counts, rhs.m_counts ); - } - - void SetPointer( void* p ) - { - m_counts->SetPointer( p ); - } - - void ZapPointer( void ) - { -#ifdef DO_EXTRA_LOKI_TESTS - assert( !m_counts->HasStrongPointer() ); -#endif - if ( m_counts->HasWeakPointer() ) - { - m_counts->ZapPointer(); - } - else - { - ThreadSafePointerAllocator::operator delete ( m_counts, - sizeof(Loki::Private::LockableTwoRefCountInfo) ); - m_counts = NULL; - } - } - - inline void* GetPointer( void ) const - { - return m_counts->GetPointer(); - } - - inline void*& GetPointerRef( void ) const - { - return m_counts->GetPointerRef(); - } - -private: - LockableTwoRefCounts( void ); - LockableTwoRefCounts& operator = ( const LockableTwoRefCounts& ); - - /// Pointer to all shared data. - Loki::Private::LockableTwoRefCountInfo* m_counts; -}; - -#endif // if object-level-locking or class-level-locking - -//////////////////////////////////////////////////////////////////////////////// -/// \class TwoRefLinks -/// -/// \ingroup StrongPointerOwnershipGroup -/// This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked -/// cycle of copointers to a shared object. Some functions are trivial enough -/// to be inline, while others are implemented in elsewhere. It is not thread -/// safe, and is intended for single-threaded environments. -//////////////////////////////////////////////////////////////////////////////// - -class LOKI_EXPORT TwoRefLinks -{ -protected: - - inline explicit TwoRefLinks( bool strong ) - : m_pointer( 0 ) - , m_strong( strong ) - { - m_prev = m_next = this; - } - - TwoRefLinks( const void* p, bool strong ); - - TwoRefLinks( const TwoRefLinks& rhs, bool strong ); - - bool Release( bool strong ); - - void Swap( TwoRefLinks& rhs ); - - bool Merge( TwoRefLinks& rhs ); - - bool HasStrongPointer( void ) const; - - inline void ZapPointer( void ) - { - ZapAllNodes(); - } - - void SetPointer( void* p ); - - inline void* GetPointer( void ) const - { - return m_pointer; - } - - inline void*& GetPointerRef( void ) const - { - return const_cast< void *& >( m_pointer ); - } - -private: - static unsigned int CountPrevCycle( const TwoRefLinks* pThis ); - static unsigned int CountNextCycle( const TwoRefLinks* pThis ); - - /// Not implemented. - TwoRefLinks( void ); - /// Not implemented. - TwoRefLinks& operator = ( const TwoRefLinks& ); - - bool HasPrevNode( const TwoRefLinks* p ) const; - bool HasNextNode( const TwoRefLinks* p ) const; - bool AllNodesHaveSamePointer( void ) const; - void ZapAllNodes( void ); - - void* m_pointer; - mutable TwoRefLinks* m_prev; - mutable TwoRefLinks* m_next; - const bool m_strong; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class StrongPtr -/// -/// \ingroup SmartPointerGroup -/// -/// \param Strong default = true, -/// \param OwnershipPolicy default = TwoRefCounts, -/// \param ConversionPolicy default = DisallowConversion, -/// \param CheckingPolicy default = AssertCheck, -/// \param ResetPolicy default = CantResetWithStrong, -/// \param DeletePolicy default = DeleteSingle -/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - bool Strong = true, - class OwnershipPolicy = Loki::TwoRefCounts, - class ConversionPolicy = Loki::DisallowConversion, - template < class > class CheckingPolicy = Loki::AssertCheck, - template < class > class ResetPolicy = Loki::CantResetWithStrong, - template < class > class DeletePolicy = Loki::DeleteSingle, - template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS - > -class StrongPtr - : public OwnershipPolicy - , public ConversionPolicy - , public CheckingPolicy< T* > - , public ResetPolicy< T > - , public DeletePolicy< T > -{ - typedef ConversionPolicy CP; - typedef CheckingPolicy< T* > KP; - typedef ResetPolicy< T > RP; - typedef DeletePolicy< T > DP; - -public: - - typedef OwnershipPolicy OP; - - typedef T* StoredType; // the type of the pointer - typedef T* PointerType; // type returned by operator-> - typedef T& ReferenceType; // type returned by operator* - - typedef typename ConstnessPolicy< T >::Type* ConstPointerType; - typedef typename ConstnessPolicy< T >::Type& ConstReferenceType; - -private: - struct NeverMatched {}; - -#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY - typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg; - typedef typename Select < !CP::allow, const StoredType&, NeverMatched >::Result ExplicitArg; -#else - typedef const StoredType& ImplicitArg; - typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg; -#endif - -public: - - StrongPtr( void ) : OP( Strong ) - { - KP::OnDefault( GetPointer() ); - } - - explicit StrongPtr( ExplicitArg p ) : OP( p, Strong ) - { - KP::OnInit( GetPointer() ); - } - - StrongPtr( ImplicitArg p ) : OP( p, Strong ) - { - KP::OnInit( GetPointer() ); - } - - StrongPtr( const StrongPtr& rhs ) - : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs ) - { - } - - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - StrongPtr( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - : OP( rhs, Strong ) - { - } - - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - StrongPtr( - StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - : OP( rhs, Strong ) - { - } - - StrongPtr( RefToValue< StrongPtr > rhs ) - : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs ) - { - } - - operator RefToValue< StrongPtr >( void ) - { - return RefToValue< StrongPtr >( *this ); - } - - StrongPtr& operator = ( const StrongPtr& rhs ) - { - if ( GetPointer() != rhs.GetPointer() ) - { - StrongPtr temp( rhs ); - temp.Swap( *this ); - } - return *this; - } - - StrongPtr& operator = ( T* p ) - { - if ( GetPointer() != p ) - { - StrongPtr temp( p ); - Swap( temp ); - } - return *this; - } - - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - StrongPtr& operator = ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - { - if ( !rhs.Equals( GetPointer() ) ) - { - StrongPtr temp( rhs ); - temp.Swap( *this ); - } - return *this; - } - - bool IsStrong( void ) const - { - return Strong; - } - - void Swap( StrongPtr& rhs ) - { - OP::Swap( rhs ); - CP::Swap( rhs ); - KP::Swap( rhs ); - DP::Swap( rhs ); - } - - ~StrongPtr() - { - if ( OP::Release( Strong ) ) - { - // Must zap the pointer before deleteing the object. Otherwise a - // cycle of weak pointers will lead to recursion, which leads to - // to deleting the shared object multiple times, which leads to - // undefined behavior. Therefore, this must get pointer before - // zapping it, and then delete the temp pointer. - T* p = GetPointer(); - OP::ZapPointer(); - if ( p != 0 ) - { - DP::Delete( p ); - } - } - } - -#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND - - // old non standard in class definition of friends - friend bool ReleaseAll( StrongPtr& sp, - typename StrongPtr::StoredType& p ) - { - if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) - { - return false; - } - p = sp.GetPointer(); - sp.OP::SetPointer( sp.DP::Default() ); - return true; - } - - friend bool ResetAll( StrongPtr& sp, - typename StrongPtr::StoredType p ) - { - if ( sp.OP::GetPointer() == p ) - { - return true; - } - if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) - { - return false; - } - sp.DP::Delete( sp.GetPointer() ); - sp.OP::SetPointer( p ); - return true; - } - -#else - - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp, - typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType& p ); - - - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp, - typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p ); - -#endif - - - /** Merges ownership of two StrongPtr's that point to same shared object - but are not copointers. Requires Merge function in OwnershipPolicy. - \return True for success, false if not pointer to same object. - */ - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - { - if ( OP::GetPointer() != rhs.OP::GetPointer() ) - { - return false; - } - return OP::Merge( rhs ); - } - - /** Locks StrongPtr so other threads can't affect pointer. Requires the - OwnershipPolicy to have Lock function. - */ - void Lock( void ) - { - OP::Lock(); - } - - /** Unlocks StrongPtr so other threads can affect pointer. Requires the - OwnershipPolicy to have Unlock function. - */ - void Unlock( void ) - { - OP::Unlock(); - } - - PointerType operator -> () - { - KP::OnDereference( GetPointer() ); - return GetPointer(); - } - - ConstPointerType operator -> () const - { - KP::OnDereference( GetPointer() ); - return GetPointer(); - } - - ReferenceType operator * () - { - KP::OnDereference( GetPointer() ); - return * GetPointer(); - } - - ConstReferenceType operator * () const - { - KP::OnDereference( GetPointer() ); - return * GetPointer(); - } - - /// Helper function which can be called to avoid exposing GetPointer function. - template < class T1 > - bool Equals( const T1* p ) const - { - return ( GetPointer() == p ); - } - - /// Helper function which can be called to avoid exposing GetPointer function. - template < class T1 > - bool LessThan( const T1* p ) const - { - return ( GetPointer() < p ); - } - - /// Helper function which can be called to avoid exposing GetPointer function. - template < class T1 > - bool GreaterThan( const T1* p ) const - { - return ( GetPointer() > p ); - } - - /// Equality comparison operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - bool operator == ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return ( rhs.Equals( GetPointer() ) ); - } - - /// Inequality comparison operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - bool operator != ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return !( rhs.Equals( GetPointer() ) ); - } - - /// Less-than comparison operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - bool operator < ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return ( rhs.GreaterThan( GetPointer() ) ); - } - - /// Greater-than comparison operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - inline bool operator > ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return ( rhs.LessThan( GetPointer() ) ); - } - - /// Less-than-or-equal-to operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - inline bool operator <= ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return !( rhs.LessThan( GetPointer() ) ); - } - - /// Greater-than-or-equal-to operator is templated to handle ambiguity. - template - < - typename T1, - bool S1, - class OP1, - class CP1, - template < class > class KP1, - template < class > class RP1, - template < class > class DP1, - template < class > class CNP1 - > - inline bool operator >= ( - const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const - { - return !( rhs.GreaterThan( GetPointer() ) ); - } - - inline bool operator ! () const // Enables "if ( !sp ) ..." - { - return ( 0 == OP::GetPointer() ); - } - -protected: - - inline PointerType GetPointer( void ) - { - return reinterpret_cast< PointerType >( OP::GetPointer() ); - } - - inline ConstPointerType GetPointer( void ) const - { - return reinterpret_cast< ConstPointerType >( OP::GetPointer() ); - } - -private: - - inline ReferenceType GetPointerRef( void ) - { - return reinterpret_cast< ReferenceType >( OP::GetPointerRef() ); - } - - inline ConstReferenceType GetPointerRef( void ) const - { - return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() ); - } - - // Helper for enabling 'if (sp)' - struct Tester - { - Tester(int) {} - void dummy() {} - }; - - typedef void (Tester::*unspecified_boolean_type_)(); - - typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result - unspecified_boolean_type; - -public: - // enable 'if (sp)' - operator unspecified_boolean_type() const - { - return !*this ? 0 : &Tester::dummy; - } - -private: - // Helper for disallowing automatic conversion - struct Insipid - { - Insipid(PointerType) {} - }; - - typedef typename Select< CP::allow, PointerType, Insipid >::Result - AutomaticConversionResult; - -public: - operator AutomaticConversionResult() const - { - return GetPointer(); - } - -}; - -// ---------------------------------------------------------------------------- - -// friend functions - -#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND - -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp, - typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType& p ) -{ - if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) - { - return false; - } - p = sp.GetPointer(); - sp.OP::SetPointer( sp.DP<T>::Default() ); - return true; -} - -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp, - typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p ) -{ - if ( sp.OP::GetPointer() == p ) - { - return true; - } - if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) - { - return false; - } - sp.DP<T>::Delete( sp.GetPointer() ); - sp.OP::SetPointer( p ); - return true; -} -#endif - - -// free comparison operators for class template StrongPtr - -/// operator== for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator == ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return ( lhs.Equals( rhs ) ); -} - -/// operator== for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator == ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return ( rhs.Equals( lhs ) ); -} - -/// operator!= for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator != ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return !( lhs.Equals( rhs ) ); -} - -/// operator!= for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator != ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return !( rhs.Equals( lhs ) ); -} - -/// operator< for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator < ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return ( lhs.LessThan( rhs ) ); -} - -/// operator< for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator < ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return ( rhs.GreaterThan( lhs ) ); -} - -// operator> for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator > ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return ( lhs.GreaterThan( rhs ) ); -} - -/// operator> for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator > ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return ( rhs.LessThan( lhs ) ); -} - -/// operator<= for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator <= ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return !( lhs.GreaterThan( rhs ) ); -} - -/// operator<= for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator <= ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return !( rhs.LessThan( lhs ) ); -} - -/// operator>= for lhs = StrongPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator >= ( - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U* rhs ) -{ - return !( lhs.LessThan( rhs ) ); -} - -/// operator>= for lhs = raw pointer, rhs = StrongPtr -/// \ingroup SmartPointerGroup -template -< -typename U, - typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -inline bool operator >= ( U* lhs, - const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) -{ - return !( rhs.GreaterThan( lhs ) ); -} - -} // namespace Loki - -namespace std -{ -//////////////////////////////////////////////////////////////////////////////// -/// specialization of std::less for StrongPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// -template -< -typename T, - bool S, - class OP, - class CP, - template < class > class KP, - template < class > class RP, - template < class > class DP, - template < class > class CNP - > -struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > > - : public binary_function < - Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, - Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool > -{ - bool operator () ( - const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, - const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const - { - return ( lhs < rhs ); - } -}; -} - -//////////////////////////////////////////////////////////////////////////////// - -#endif // end file guardian - |