1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2006 Rich Sposato
4 // The copyright on this file is protected under the terms of the MIT license.
6 // Permission to use, copy, modify, distribute and sell this software for any
7 // purpose is hereby granted without fee, provided that the above copyright
8 // notice appear in all copies and that both that copyright notice and this
9 // permission notice appear in supporting documentation.
10 // The author makes no representations about the
11 // suitability of this software for any purpose. It is provided "as is"
12 // without express or implied warranty.
13 ////////////////////////////////////////////////////////////////////////////////
14 #ifndef LOKI_STRONG_PTR_INC_
15 #define LOKI_STRONG_PTR_INC_
17 // $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $
20 #include <loki/SmartPtr.h>
21 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
22 #include <loki/Threads.h>
26 ////////////////////////////////////////////////////////////////////////////////
29 /// These terms are used within this file's comments.
30 /// -# StrongPtr : Class used to implement both strong and weak pointers. The
31 /// second template parameter determines if a StrongPtr is weak or strong.
32 /// -# Strong pointer : A pointer that claims ownership of a shared object.
33 /// When the last strong copointer dies, the object is destroyed even if
34 /// there are weak copointers.
35 /// -# Weak pointer : A pointer that does not own the shared object it points
36 /// to. It only destroys the shared object if there no strong copointers
37 /// exist when it dies.
38 /// -# Copointers : All the pointers that refer to the same shared object.
39 /// The copointers must have the same ownership policy, but the other
40 /// policies may be different.
41 /// -# Pointee : The shared object.
43 /// \par OwnershipPolicy
44 /// The ownership policy has the pointer to the actual object, and it also
45 /// keeps track of the strong and weak copointers so that it can know if any
46 /// strong copointers remain. The plain pointer it maintains is stored as a
47 /// void pointer, which allows the ownership policy classes to be monolithic
48 /// classes instead of template classes. As monolithic classes, they reduce
49 /// amount of code-bloat.
51 /// \par Writing Your Own OwnershipPolicy
52 /// If you write your own policy, you must implement these 12 functions:
53 /// -# explicit YourPolicy( bool strong )
54 /// -# YourPolicy( void * p, bool strong )
55 /// -# YourPolicy( const YourPolicy & rhs, bool strong )
56 /// -# bool Release( bool strong )
57 /// -# void Increment( bool strong )
58 /// -# bool Decrement( bool strong )
59 /// -# bool HasStrongPointer( void ) const
60 /// -# void Swap( YourPolicy & rhs )
61 /// -# void SetPointer( void * p )
62 /// -# void ZapPointer( void )
63 /// -# void * GetPointer( void ) const
64 /// -# void * & GetPointerRef( void ) const
65 /// It is strongly recommended that all 12 of these functions be protected
66 /// instead of public. These two functions are optional for single-threaded
67 /// policies, but required for multi-threaded policies:
68 /// -# void Lock( void ) const
69 /// -# void Unlock( void ) const
70 /// This function is entirely optional:
71 /// -# bool Merge( TwoRefLinks & rhs )
74 /// The delete policy provides a mechanism to destroy an object and a default
75 /// value for an uninitialized pointer. You can override this policy with
76 /// your own when using the Singleton, NullObject, or Prototype design
79 /// \par Writing Your Own DeletePolicy
80 /// If you write your own policy, you must implement these 3 functions:
81 /// -# void static Delete( const P * p )
82 /// -# static P * Default( void )
83 /// -# void Swap( YourResetPolicy & )
86 /// A reset policy tells the ReleaseAll and ResetAll functions whether they
87 /// should release or reset the StrongPtr copointers. These functions do
88 /// not affect just one StrongPtr, but all copointers. That is unlike
89 /// SmartPtr where the Release and Reset functions only affect 1 SmartPtr,
90 /// and leave all copointers untouched. A useful trick you can do with the
91 /// ResetPolicy is to not allow reset when a strong pointer exists, and then
92 /// use the NoCheck policy for all strong pointers. The reset policy
93 /// guarantees the strong pointers always have a valid pointee, so checking
94 /// is not required; but weak pointers may still require checking.
96 /// \par Writing Your Own ResetPolicy
97 /// If you write your own policy, you must implement these 2 functions:
98 /// -# bool OnReleaseAll( bool ) const
99 /// -# bool OnResetAll( bool ) const
100 /// The bool parameter means that this was called with a strong pointer or
101 /// one of its copointers is strong. The return value means the pointer
102 /// can be reset or released.
104 /// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies
105 /// \ingroup SmartPointerGroup
106 /// \defgroup StrongPointerDeleteGroup Delete policies
107 /// \ingroup SmartPointerGroup
108 /// \defgroup StrongPointerResetGroup Reset policies
109 /// \ingroup SmartPointerGroup
110 ////////////////////////////////////////////////////////////////////////////////
117 ////////////////////////////////////////////////////////////////////////////////
118 /// \class DeleteUsingFree
120 /// \ingroup StrongPointerDeleteGroup
121 /// Implementation of the DeletePolicy used by StrongPtr. Uses explicit call
122 /// to T's destructor followed by call to free. This policy is useful for
123 /// managing the lifetime of pointers to structs returned by C functions.
124 ////////////////////////////////////////////////////////////////////////////////
127 class DeleteUsingFree
130 inline void static Delete( const P *p )
139 /// Provides default value to initialize the pointer
140 inline static P *Default( void )
145 inline void Swap( DeleteUsingFree & ) {}
148 ////////////////////////////////////////////////////////////////////////////////
149 /// \class DeleteNothing
151 /// \ingroup StrongPointerDeleteGroup
152 /// Implementation of the DeletePolicy used by StrongPtr. This will never
153 /// delete anything. You can use this policy with pointers to an undefined
154 /// type or a pure interface class with a protected destructor.
155 ////////////////////////////////////////////////////////////////////////////////
161 inline static void Delete( const P * )
163 // Do nothing at all!
166 inline static P *Default( void )
171 inline void Swap( DeleteNothing & ) {}
174 ////////////////////////////////////////////////////////////////////////////////
175 /// \class DeleteSingle
177 /// \ingroup StrongPointerDeleteGroup
178 /// Implementation of the DeletePolicy used by StrongPtr. This deletes just
179 /// one shared object. This is the default class for the DeletePolicy.
180 ////////////////////////////////////////////////////////////////////////////////
186 inline static void Delete( const P *p )
188 /** @note If you see an error message about a negative subscript, that
189 means your are attempting to use Loki to delete an incomplete type.
190 Please don't use this policy with incomplete types; you may want to
191 use DeleteNothing instead.
193 typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
197 inline static P *Default( void )
202 inline void Swap( DeleteSingle & ) {}
205 ////////////////////////////////////////////////////////////////////////////////
206 /// \class DeleteArray
208 /// \ingroup StrongPointerDeleteGroup
209 /// Implementation of the DeletePolicy used by StrongPtr. This deletes an
210 /// array of shared objects.
211 ////////////////////////////////////////////////////////////////////////////////
217 inline static void Delete( const P *p )
219 /** @note If you see an error message about a negative subscript, that
220 means your are attempting to use Loki to delete an incomplete type.
221 Please don't use this policy with incomplete types; you may want to
222 use DeleteNothing instead.
224 typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
228 inline static P *Default( void )
233 inline void Swap( DeleteArray & ) {}
236 ////////////////////////////////////////////////////////////////////////////////
237 /// \class CantResetWithStrong
239 /// \ingroup StrongPointerResetGroup
240 /// Implementation of the ResetPolicy used by StrongPtr. This is the default
241 /// ResetPolicy for StrongPtr. It forbids reset and release only if a strong
242 /// copointer exists.
243 ////////////////////////////////////////////////////////////////////////////////
246 struct CantResetWithStrong
248 inline bool OnReleaseAll( bool hasStrongPtr ) const
250 return ! hasStrongPtr;
253 inline bool OnResetAll( bool hasStrongPtr ) const
255 return ! hasStrongPtr;
259 ////////////////////////////////////////////////////////////////////////////////
260 /// \class AllowReset
262 /// \ingroup StrongPointerResetGroup
263 /// Implementation of the ResetPolicy used by StrongPtr. It allows reset and
264 /// release under any circumstance.
265 ////////////////////////////////////////////////////////////////////////////////
270 inline bool OnReleaseAll( bool ) const
274 inline bool OnResetAll( bool ) const
280 ////////////////////////////////////////////////////////////////////////////////
281 /// \class NeverReset
283 /// \ingroup StrongPointerResetGroup
284 /// Implementation of the ResetPolicy used by StrongPtr. It forbids reset and
285 /// release under any circumstance.
286 ////////////////////////////////////////////////////////////////////////////////
291 inline bool OnReleaseAll( bool ) const
295 inline bool OnResetAll( bool ) const
301 // ----------------------------------------------------------------------------
306 ////////////////////////////////////////////////////////////////////////////////
307 /// \class TwoRefCountInfo
309 /// \ingroup StrongPointerOwnershipGroup
310 /// Implementation detail for reference counting strong and weak pointers.
311 /// It maintains a void pointer and 2 reference counts. Since it is just a
312 /// class for managing implementation details, it is not intended to be used
313 /// directly - which is why it is in a private namespace. Each instance is a
314 /// shared resource for all copointers, and there should be only one of these
315 /// for each set of copointers. This class is small, trivial, and inline.
316 ////////////////////////////////////////////////////////////////////////////////
318 class LOKI_EXPORT TwoRefCountInfo
322 inline explicit TwoRefCountInfo( bool strong )
324 , m_strongCount( strong ? 1 : 0 )
325 , m_weakCount( strong ? 0 : 1 )
329 inline TwoRefCountInfo( void *p, bool strong )
331 , m_strongCount( strong ? 1 : 0 )
332 , m_weakCount( strong ? 0 : 1 )
336 inline ~TwoRefCountInfo( void )
338 assert( 0 == m_strongCount );
339 assert( 0 == m_weakCount );
342 inline bool HasStrongPointer( void ) const
344 return ( 0 < m_strongCount );
347 inline bool HasWeakPointer( void ) const
349 return ( 0 < m_weakCount );
352 inline void IncStrongCount( void )
357 inline void IncWeakCount( void )
362 inline bool DecStrongCount( void )
364 assert( 0 < m_strongCount );
366 const bool isZero = ( 0 == m_strongCount );
370 inline void DecWeakCount( void )
372 assert( 0 < m_weakCount );
376 inline void ZapPointer( void )
381 void SetPointer( void *p )
386 inline void *GetPointer( void ) const
391 inline void * &GetPointerRef( void ) const
393 return const_cast< void * & >( m_pointer );
397 /// Copy-constructor not implemented.
398 TwoRefCountInfo( const TwoRefCountInfo & );
399 /// Copy-assignment operator not implemented.
400 TwoRefCountInfo &operator = ( const TwoRefCountInfo & );
403 unsigned int m_strongCount;
404 unsigned int m_weakCount;
407 ////////////////////////////////////////////////////////////////////////////////
408 /// \class LockableTwoRefCountInfo
410 /// \ingroup StrongPointerOwnershipGroup
411 /// Implementation detail for thread-safe reference counting for strong and
412 /// weak pointers. It uses TwoRefCountInfo to manage the pointer and counts.
413 /// All this does is provide a thread safety mechanism. Since it is just a
414 /// class for managing implementation details, it is not intended to be used
415 /// directly - which is why it is in a private namespace. Each instance is a
416 /// shared resource for all copointers, and there should be only one of these
417 /// for each set of copointers. This class is small, trivial, and inline.
419 /// \note This class is not designed for use with a single-threaded model.
420 /// Tests using a single-threaded model will not run properly, but tests in a
421 /// multi-threaded model with either class-level-locking or object-level-locking
423 ////////////////////////////////////////////////////////////////////////////////
425 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
427 class LOKI_EXPORT LockableTwoRefCountInfo
428 : private Loki::Private::TwoRefCountInfo
432 inline explicit LockableTwoRefCountInfo( bool strong )
433 : TwoRefCountInfo( strong )
438 LockableTwoRefCountInfo( void *p, bool strong )
439 : TwoRefCountInfo( p, strong )
444 inline ~LockableTwoRefCountInfo( void )
448 inline void Lock( void ) const
453 inline void Unlock( void ) const
458 inline bool HasStrongPointer( void ) const
461 const bool has = TwoRefCountInfo::HasStrongPointer();
466 inline bool HasWeakPointer( void ) const
469 const bool has = TwoRefCountInfo::HasWeakPointer();
474 inline void IncStrongCount( void )
477 TwoRefCountInfo::IncStrongCount();
481 inline void IncWeakCount( void )
484 TwoRefCountInfo::IncWeakCount();
488 inline bool DecStrongCount( void )
491 const bool isZero = TwoRefCountInfo::DecStrongCount();
496 inline void DecWeakCount( void )
499 TwoRefCountInfo::DecWeakCount();
503 inline void ZapPointer( void )
506 TwoRefCountInfo::ZapPointer();
510 void SetPointer( void *p )
513 TwoRefCountInfo::SetPointer( p );
517 inline void *GetPointer( void ) const
519 return TwoRefCountInfo::GetPointer();
522 inline void * &GetPointerRef( void ) const
524 return TwoRefCountInfo::GetPointerRef();
528 /// Default constructor is not available.
529 LockableTwoRefCountInfo( void );
530 /// Copy constructor is not available.
531 LockableTwoRefCountInfo( const LockableTwoRefCountInfo & );
532 /// Copy-assignment operator is not available.
533 LockableTwoRefCountInfo &operator = ( const LockableTwoRefCountInfo & );
535 mutable LOKI_DEFAULT_MUTEX m_Mutex;
538 #endif // if object-level-locking or class-level-locking
540 } // end namespace Private
542 ////////////////////////////////////////////////////////////////////////////////
543 /// \class TwoRefCounts
545 /// \ingroup StrongPointerOwnershipGroup
546 /// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
547 /// shared instance of TwoRefCountInfo. This is the default policy for
548 /// OwnershipPolicy. Some functions are trivial enough to be inline, while
549 /// others are implemented elsewhere. It is not thread safe, and is intended
550 /// for single-threaded environments.
551 ////////////////////////////////////////////////////////////////////////////////
553 class LOKI_EXPORT TwoRefCounts
557 explicit TwoRefCounts( bool strong );
559 TwoRefCounts( const void *p, bool strong );
561 TwoRefCounts( const TwoRefCounts &rhs, bool strong ) :
562 m_counts( rhs.m_counts )
567 /** The destructor does not need to do anything since the call to
568 ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
569 this dtor would have done.
571 inline ~TwoRefCounts( void ) {}
573 inline bool Release( bool strong )
575 return Decrement( strong );
578 bool HasStrongPointer( void ) const
580 return m_counts->HasStrongPointer();
583 void Swap( TwoRefCounts &rhs );
585 void SetPointer( void *p )
587 m_counts->SetPointer( p );
590 void ZapPointer( void );
592 inline void * &GetPointerRef( void ) const
594 return m_counts->GetPointerRef();
597 inline void *GetPointer( void ) const
599 return m_counts->GetPointer();
603 TwoRefCounts( void );
604 TwoRefCounts &operator = ( const TwoRefCounts & );
606 void Increment( bool strong );
608 bool Decrement( bool strong );
610 /// Pointer to all shared data.
611 Loki::Private::TwoRefCountInfo *m_counts;
614 ////////////////////////////////////////////////////////////////////////////////
615 /// \class LockableTwoRefCounts
617 /// \ingroup StrongPointerOwnershipGroup
618 /// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
619 /// shared instance of LockableTwoRefCountInfo. It behaves very similarly to
620 /// TwoRefCounts, except that it provides thread-safety. Some functions are
621 /// trivial enough to be inline, while others are implemented elsewhere.
623 /// \note This class is not designed for use with a single-threaded model.
624 /// Tests using a single-threaded model will not run properly, but tests in a
625 /// multi-threaded model with either class-level-locking or object-level-locking
627 ////////////////////////////////////////////////////////////////////////////////
629 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
631 class LOKI_EXPORT LockableTwoRefCounts
633 typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
637 explicit LockableTwoRefCounts( bool strong )
640 void *temp = ThreadSafePointerAllocator::operator new(
641 sizeof(Loki::Private::LockableTwoRefCountInfo) );
642 #ifdef DO_EXTRA_LOKI_TESTS
645 m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
648 LockableTwoRefCounts( const void *p, bool strong )
651 void *temp = ThreadSafePointerAllocator::operator new(
652 sizeof(Loki::Private::LockableTwoRefCountInfo) );
653 #ifdef DO_EXTRA_LOKI_TESTS
656 void *p2 = const_cast< void * >( p );
657 m_counts = new ( temp )
658 Loki::Private::LockableTwoRefCountInfo( p2, strong );
661 LockableTwoRefCounts( const LockableTwoRefCounts &rhs, bool strong ) :
662 m_counts( rhs.m_counts )
667 /** The destructor does not need to do anything since the call to
668 ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
669 this dtor would have done.
671 inline ~LockableTwoRefCounts( void ) {}
673 inline void Lock( void ) const
678 inline void Unlock( void ) const
683 inline bool Release( bool strong )
685 return Decrement( strong );
688 void Increment( bool strong )
692 m_counts->IncStrongCount();
696 m_counts->IncWeakCount();
700 bool Decrement( bool strong )
702 bool noStrongPointers = false;
705 noStrongPointers = m_counts->DecStrongCount();
709 m_counts->DecWeakCount();
710 noStrongPointers = !m_counts->HasStrongPointer();
712 return noStrongPointers;
715 bool HasStrongPointer( void ) const
717 return m_counts->HasStrongPointer();
720 void Swap( LockableTwoRefCounts &rhs )
722 std::swap( m_counts, rhs.m_counts );
725 void SetPointer( void *p )
727 m_counts->SetPointer( p );
730 void ZapPointer( void )
732 #ifdef DO_EXTRA_LOKI_TESTS
733 assert( !m_counts->HasStrongPointer() );
735 if ( m_counts->HasWeakPointer() )
737 m_counts->ZapPointer();
741 ThreadSafePointerAllocator::operator delete ( m_counts,
742 sizeof(Loki::Private::LockableTwoRefCountInfo) );
747 inline void *GetPointer( void ) const
749 return m_counts->GetPointer();
752 inline void * &GetPointerRef( void ) const
754 return m_counts->GetPointerRef();
758 LockableTwoRefCounts( void );
759 LockableTwoRefCounts &operator = ( const LockableTwoRefCounts & );
761 /// Pointer to all shared data.
762 Loki::Private::LockableTwoRefCountInfo *m_counts;
765 #endif // if object-level-locking or class-level-locking
767 ////////////////////////////////////////////////////////////////////////////////
768 /// \class TwoRefLinks
770 /// \ingroup StrongPointerOwnershipGroup
771 /// This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked
772 /// cycle of copointers to a shared object. Some functions are trivial enough
773 /// to be inline, while others are implemented in elsewhere. It is not thread
774 /// safe, and is intended for single-threaded environments.
775 ////////////////////////////////////////////////////////////////////////////////
777 class LOKI_EXPORT TwoRefLinks
781 inline explicit TwoRefLinks( bool strong )
785 m_prev = m_next = this;
788 TwoRefLinks( const void *p, bool strong );
790 TwoRefLinks( const TwoRefLinks &rhs, bool strong );
792 bool Release( bool strong );
794 void Swap( TwoRefLinks &rhs );
796 bool Merge( TwoRefLinks &rhs );
798 bool HasStrongPointer( void ) const;
800 inline void ZapPointer( void )
805 void SetPointer( void *p );
807 inline void *GetPointer( void ) const
812 inline void * &GetPointerRef( void ) const
814 return const_cast< void * & >( m_pointer );
818 static unsigned int CountPrevCycle( const TwoRefLinks *pThis );
819 static unsigned int CountNextCycle( const TwoRefLinks *pThis );
824 TwoRefLinks &operator = ( const TwoRefLinks & );
826 bool HasPrevNode( const TwoRefLinks *p ) const;
827 bool HasNextNode( const TwoRefLinks *p ) const;
828 bool AllNodesHaveSamePointer( void ) const;
829 void ZapAllNodes( void );
832 mutable TwoRefLinks *m_prev;
833 mutable TwoRefLinks *m_next;
837 ////////////////////////////////////////////////////////////////////////////////
840 /// \ingroup SmartPointerGroup
842 /// \param Strong default = true,
843 /// \param OwnershipPolicy default = TwoRefCounts,
844 /// \param ConversionPolicy default = DisallowConversion,
845 /// \param CheckingPolicy default = AssertCheck,
846 /// \param ResetPolicy default = CantResetWithStrong,
847 /// \param DeletePolicy default = DeleteSingle
848 /// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
849 ////////////////////////////////////////////////////////////////////////////////
855 class OwnershipPolicy = Loki::TwoRefCounts,
856 class ConversionPolicy = Loki::DisallowConversion,
857 template < class > class CheckingPolicy = Loki::AssertCheck,
858 template < class > class ResetPolicy = Loki::CantResetWithStrong,
859 template < class > class DeletePolicy = Loki::DeleteSingle,
860 template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
863 : public OwnershipPolicy
864 , public ConversionPolicy
865 , public CheckingPolicy< T * >
866 , public ResetPolicy< T >
867 , public DeletePolicy< T >
869 typedef ConversionPolicy CP;
870 typedef CheckingPolicy< T * > KP;
871 typedef ResetPolicy< T > RP;
872 typedef DeletePolicy< T > DP;
876 typedef OwnershipPolicy OP;
878 typedef T *StoredType; // the type of the pointer
879 typedef T *PointerType; // type returned by operator->
880 typedef T &ReferenceType; // type returned by operator*
882 typedef typename ConstnessPolicy< T >::Type *ConstPointerType;
883 typedef typename ConstnessPolicy< T >::Type &ConstReferenceType;
886 struct NeverMatched {};
888 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
889 typedef typename Select< CP::allow, const StoredType &, NeverMatched>::Result ImplicitArg;
890 typedef typename Select<!CP::allow, const StoredType &, NeverMatched>::Result ExplicitArg;
892 typedef const StoredType &ImplicitArg;
893 typedef typename Select<false, const StoredType &, NeverMatched>::Result ExplicitArg;
898 StrongPtr( void ) : OP( Strong )
900 KP::OnDefault( GetPointer() );
903 explicit StrongPtr( ExplicitArg p ) : OP( p, Strong )
905 KP::OnInit( GetPointer() );
908 StrongPtr( ImplicitArg p ) : OP( p, Strong )
910 KP::OnInit( GetPointer() );
913 StrongPtr( const StrongPtr &rhs )
914 : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs )
924 template < class > class KP1,
925 template < class > class RP1,
926 template < class > class DP1,
927 template < class > class CNP1
930 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
941 template < class > class KP1,
942 template < class > class RP1,
943 template < class > class DP1,
944 template < class > class CNP1
947 StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
952 StrongPtr( RefToValue< StrongPtr > rhs )
953 : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs )
957 operator RefToValue< StrongPtr >( void )
959 return RefToValue< StrongPtr >( *this );
962 StrongPtr &operator = ( const StrongPtr &rhs )
964 if ( GetPointer() != rhs.GetPointer() )
966 StrongPtr temp( rhs );
972 StrongPtr &operator = ( T *p )
974 if ( GetPointer() != p )
988 template < class > class KP1,
989 template < class > class RP1,
990 template < class > class DP1,
991 template < class > class CNP1
993 StrongPtr &operator = (
994 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
996 if ( !rhs.Equals( GetPointer() ) )
998 StrongPtr temp( rhs );
1004 bool IsStrong( void ) const
1009 void Swap( StrongPtr &rhs )
1019 if ( OP::Release( Strong ) )
1021 // Must zap the pointer before deleteing the object. Otherwise a
1022 // cycle of weak pointers will lead to recursion, which leads to
1023 // to deleting the shared object multiple times, which leads to
1024 // undefined behavior. Therefore, this must get pointer before
1025 // zapping it, and then delete the temp pointer.
1026 T *p = GetPointer();
1035 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1037 // old non standard in class definition of friends
1038 friend bool ReleaseAll( StrongPtr &sp,
1039 typename StrongPtr::StoredType &p )
1041 if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1045 p = sp.GetPointer();
1046 sp.OP::SetPointer( sp.DP::Default() );
1050 friend bool ResetAll( StrongPtr &sp,
1051 typename StrongPtr::StoredType p )
1053 if ( sp.OP::GetPointer() == p )
1057 if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1061 sp.DP::Delete( sp.GetPointer() );
1062 sp.OP::SetPointer( p );
1074 template < class > class KP1,
1075 template < class > class RP1,
1076 template < class > class DP1,
1077 template < class > class CNP1
1079 friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1080 typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType &p );
1089 template < class > class KP1,
1090 template < class > class RP1,
1091 template < class > class DP1,
1092 template < class > class CNP1
1094 friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1095 typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p );
1100 /** Merges ownership of two StrongPtr's that point to same shared object
1101 but are not copointers. Requires Merge function in OwnershipPolicy.
1102 \return True for success, false if not pointer to same object.
1110 template < class > class KP1,
1111 template < class > class RP1,
1112 template < class > class DP1,
1113 template < class > class CNP1
1115 bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
1117 if ( OP::GetPointer() != rhs.OP::GetPointer() )
1121 return OP::Merge( rhs );
1124 /** Locks StrongPtr so other threads can't affect pointer. Requires the
1125 OwnershipPolicy to have Lock function.
1132 /** Unlocks StrongPtr so other threads can affect pointer. Requires the
1133 OwnershipPolicy to have Unlock function.
1140 PointerType operator -> ()
1142 KP::OnDereference( GetPointer() );
1143 return GetPointer();
1146 ConstPointerType operator -> () const
1148 KP::OnDereference( GetPointer() );
1149 return GetPointer();
1152 ReferenceType operator * ()
1154 KP::OnDereference( GetPointer() );
1155 return * GetPointer();
1158 ConstReferenceType operator * () const
1160 KP::OnDereference( GetPointer() );
1161 return * GetPointer();
1164 /// Helper function which can be called to avoid exposing GetPointer function.
1165 template < class T1 >
1166 bool Equals( const T1 *p ) const
1168 return ( GetPointer() == p );
1171 /// Helper function which can be called to avoid exposing GetPointer function.
1172 template < class T1 >
1173 bool LessThan( const T1 *p ) const
1175 return ( GetPointer() < p );
1178 /// Helper function which can be called to avoid exposing GetPointer function.
1179 template < class T1 >
1180 bool GreaterThan( const T1 *p ) const
1182 return ( GetPointer() > p );
1185 /// Equality comparison operator is templated to handle ambiguity.
1192 template < class > class KP1,
1193 template < class > class RP1,
1194 template < class > class DP1,
1195 template < class > class CNP1
1198 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1200 return ( rhs.Equals( GetPointer() ) );
1203 /// Inequality comparison operator is templated to handle ambiguity.
1210 template < class > class KP1,
1211 template < class > class RP1,
1212 template < class > class DP1,
1213 template < class > class CNP1
1216 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1218 return !( rhs.Equals( GetPointer() ) );
1221 /// Less-than comparison operator is templated to handle ambiguity.
1228 template < class > class KP1,
1229 template < class > class RP1,
1230 template < class > class DP1,
1231 template < class > class CNP1
1234 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1236 return ( rhs.GreaterThan( GetPointer() ) );
1239 /// Greater-than comparison operator is templated to handle ambiguity.
1246 template < class > class KP1,
1247 template < class > class RP1,
1248 template < class > class DP1,
1249 template < class > class CNP1
1251 inline bool operator > (
1252 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1254 return ( rhs.LessThan( GetPointer() ) );
1257 /// Less-than-or-equal-to operator is templated to handle ambiguity.
1264 template < class > class KP1,
1265 template < class > class RP1,
1266 template < class > class DP1,
1267 template < class > class CNP1
1269 inline bool operator <= (
1270 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1272 return !( rhs.LessThan( GetPointer() ) );
1275 /// Greater-than-or-equal-to operator is templated to handle ambiguity.
1282 template < class > class KP1,
1283 template < class > class RP1,
1284 template < class > class DP1,
1285 template < class > class CNP1
1287 inline bool operator >= (
1288 const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1290 return !( rhs.GreaterThan( GetPointer() ) );
1293 inline bool operator ! () const // Enables "if ( !sp ) ..."
1295 return ( 0 == OP::GetPointer() );
1300 inline PointerType GetPointer( void )
1302 return reinterpret_cast< PointerType >( OP::GetPointer() );
1305 inline ConstPointerType GetPointer( void ) const
1307 return reinterpret_cast< ConstPointerType >( OP::GetPointer() );
1312 inline ReferenceType GetPointerRef( void )
1314 return reinterpret_cast< ReferenceType >( OP::GetPointerRef() );
1317 inline ConstReferenceType GetPointerRef( void ) const
1319 return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() );
1322 // Helper for enabling 'if (sp)'
1329 typedef void (Tester::*unspecified_boolean_type_)();
1331 typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result
1332 unspecified_boolean_type;
1336 operator unspecified_boolean_type() const
1338 return !*this ? 0 : &Tester::dummy;
1342 // Helper for disallowing automatic conversion
1345 Insipid(PointerType) {}
1348 typedef typename Select< CP::allow, PointerType, Insipid >::Result
1349 AutomaticConversionResult;
1352 operator AutomaticConversionResult() const
1354 return GetPointer();
1359 // ----------------------------------------------------------------------------
1363 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1372 template < class > class KP,
1373 template < class > class RP,
1374 template < class > class DP,
1375 template < class > class CNP
1377 bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1378 typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType &p )
1380 if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1384 p = sp.GetPointer();
1385 sp.OP::SetPointer( sp.DP<T>::Default() );
1396 template < class > class KP,
1397 template < class > class RP,
1398 template < class > class DP,
1399 template < class > class CNP
1401 bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1402 typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p )
1404 if ( sp.OP::GetPointer() == p )
1408 if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1412 sp.DP<T>::Delete( sp.GetPointer() );
1413 sp.OP::SetPointer( p );
1419 // free comparison operators for class template StrongPtr
1421 /// operator== for lhs = StrongPtr, rhs = raw pointer
1422 /// \ingroup SmartPointerGroup
1430 template < class > class KP,
1431 template < class > class RP,
1432 template < class > class DP,
1433 template < class > class CNP
1435 inline bool operator == (
1436 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1438 return ( lhs.Equals( rhs ) );
1441 /// operator== for lhs = raw pointer, rhs = StrongPtr
1442 /// \ingroup SmartPointerGroup
1450 template < class > class KP,
1451 template < class > class RP,
1452 template < class > class DP,
1453 template < class > class CNP
1455 inline bool operator == ( U *lhs,
1456 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1458 return ( rhs.Equals( lhs ) );
1461 /// operator!= for lhs = StrongPtr, rhs = raw pointer
1462 /// \ingroup SmartPointerGroup
1470 template < class > class KP,
1471 template < class > class RP,
1472 template < class > class DP,
1473 template < class > class CNP
1475 inline bool operator != (
1476 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1478 return !( lhs.Equals( rhs ) );
1481 /// operator!= for lhs = raw pointer, rhs = StrongPtr
1482 /// \ingroup SmartPointerGroup
1490 template < class > class KP,
1491 template < class > class RP,
1492 template < class > class DP,
1493 template < class > class CNP
1495 inline bool operator != ( U *lhs,
1496 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1498 return !( rhs.Equals( lhs ) );
1501 /// operator< for lhs = StrongPtr, rhs = raw pointer
1502 /// \ingroup SmartPointerGroup
1510 template < class > class KP,
1511 template < class > class RP,
1512 template < class > class DP,
1513 template < class > class CNP
1515 inline bool operator < (
1516 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1518 return ( lhs.LessThan( rhs ) );
1521 /// operator< for lhs = raw pointer, rhs = StrongPtr
1522 /// \ingroup SmartPointerGroup
1530 template < class > class KP,
1531 template < class > class RP,
1532 template < class > class DP,
1533 template < class > class CNP
1535 inline bool operator < ( U *lhs,
1536 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1538 return ( rhs.GreaterThan( lhs ) );
1541 // operator> for lhs = StrongPtr, rhs = raw pointer
1542 /// \ingroup SmartPointerGroup
1550 template < class > class KP,
1551 template < class > class RP,
1552 template < class > class DP,
1553 template < class > class CNP
1555 inline bool operator > (
1556 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1558 return ( lhs.GreaterThan( rhs ) );
1561 /// operator> for lhs = raw pointer, rhs = StrongPtr
1562 /// \ingroup SmartPointerGroup
1570 template < class > class KP,
1571 template < class > class RP,
1572 template < class > class DP,
1573 template < class > class CNP
1575 inline bool operator > ( U *lhs,
1576 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1578 return ( rhs.LessThan( lhs ) );
1581 /// operator<= for lhs = StrongPtr, rhs = raw pointer
1582 /// \ingroup SmartPointerGroup
1590 template < class > class KP,
1591 template < class > class RP,
1592 template < class > class DP,
1593 template < class > class CNP
1595 inline bool operator <= (
1596 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1598 return !( lhs.GreaterThan( rhs ) );
1601 /// operator<= for lhs = raw pointer, rhs = StrongPtr
1602 /// \ingroup SmartPointerGroup
1610 template < class > class KP,
1611 template < class > class RP,
1612 template < class > class DP,
1613 template < class > class CNP
1615 inline bool operator <= ( U *lhs,
1616 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1618 return !( rhs.LessThan( lhs ) );
1621 /// operator>= for lhs = StrongPtr, rhs = raw pointer
1622 /// \ingroup SmartPointerGroup
1630 template < class > class KP,
1631 template < class > class RP,
1632 template < class > class DP,
1633 template < class > class CNP
1635 inline bool operator >= (
1636 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1638 return !( lhs.LessThan( rhs ) );
1641 /// operator>= for lhs = raw pointer, rhs = StrongPtr
1642 /// \ingroup SmartPointerGroup
1650 template < class > class KP,
1651 template < class > class RP,
1652 template < class > class DP,
1653 template < class > class CNP
1655 inline bool operator >= ( U *lhs,
1656 const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1658 return !( rhs.GreaterThan( lhs ) );
1665 ////////////////////////////////////////////////////////////////////////////////
1666 /// specialization of std::less for StrongPtr
1667 /// \ingroup SmartPointerGroup
1668 ////////////////////////////////////////////////////////////////////////////////
1675 template < class > class KP,
1676 template < class > class RP,
1677 template < class > class DP,
1678 template < class > class CNP
1680 struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
1681 : public binary_function<
1682 Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
1683 Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
1686 const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
1687 const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
1689 return ( lhs < rhs );
1694 ////////////////////////////////////////////////////////////////////////////////
1696 #endif // end file guardian