From: <ric...@us...> - 2008-11-10 06:00:03
|
Revision: 904 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=904&view=rev Author: rich_sposato Date: 2008-11-10 05:59:59 +0000 (Mon, 10 Nov 2008) Log Message: ----------- Fixed variation of bug 2022935 by changing when functions check if strong-count is zero. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2008-11-10 05:55:12 UTC (rev 903) +++ trunk/include/loki/StrongPtr.h 2008-11-10 05:59:59 UTC (rev 904) @@ -3,12 +3,12 @@ // 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 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" +// 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_ @@ -117,7 +117,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class DeleteUsingFree /// -/// \ingroup StrongPointerDeleteGroup +/// \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. @@ -148,7 +148,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class DeleteNothing /// -/// \ingroup StrongPointerDeleteGroup +/// \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. @@ -174,7 +174,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class DeleteSingle /// -/// \ingroup StrongPointerDeleteGroup +/// \ingroup StrongPointerDeleteGroup /// Implementation of the DeletePolicy used by StrongPtr. This deletes just /// one shared object. This is the default class for the DeletePolicy. //////////////////////////////////////////////////////////////////////////////// @@ -205,7 +205,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class DeleteArray /// -/// \ingroup StrongPointerDeleteGroup +/// \ingroup StrongPointerDeleteGroup /// Implementation of the DeletePolicy used by StrongPtr. This deletes an /// array of shared objects. //////////////////////////////////////////////////////////////////////////////// @@ -236,7 +236,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class CantResetWithStrong /// -/// \ingroup StrongPointerResetGroup +/// \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. @@ -259,7 +259,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class AllowReset /// -/// \ingroup StrongPointerResetGroup +/// \ingroup StrongPointerResetGroup /// Implementation of the ResetPolicy used by StrongPtr. It allows reset and /// release under any circumstance. //////////////////////////////////////////////////////////////////////////////// @@ -280,7 +280,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class NeverReset /// -/// \ingroup StrongPointerResetGroup +/// \ingroup StrongPointerResetGroup /// Implementation of the ResetPolicy used by StrongPtr. It forbids reset and /// release under any circumstance. //////////////////////////////////////////////////////////////////////////////// @@ -359,10 +359,12 @@ ++m_weakCount; } - inline void DecStrongCount( void ) + inline bool DecStrongCount( void ) { assert( 0 < m_strongCount ); --m_strongCount; + const bool isZero = ( 0 == m_strongCount ); + return isZero; } inline void DecWeakCount( void ) @@ -483,11 +485,12 @@ m_Mutex.Unlock(); } - inline void DecStrongCount( void ) + inline bool DecStrongCount( void ) { m_Mutex.Lock(); - TwoRefCountInfo::DecStrongCount(); + const bool isZero = TwoRefCountInfo::DecStrongCount(); m_Mutex.Unlock(); + return isZero; } inline void DecWeakCount( void ) @@ -572,10 +575,6 @@ return Decrement( strong ); } - void Increment( bool strong ); - - bool Decrement( bool strong ); - bool HasStrongPointer( void ) const { return m_counts->HasStrongPointer(); @@ -604,6 +603,10 @@ TwoRefCounts( void ); TwoRefCounts & operator = ( const TwoRefCounts & ); + void Increment( bool strong ); + + bool Decrement( bool strong ); + /// Pointer to all shared data. Loki::Private::TwoRefCountInfo * m_counts; }; @@ -696,15 +699,17 @@ bool Decrement( bool strong ) { + bool noStrongPointers = false; if ( strong ) { - m_counts->DecStrongCount(); + noStrongPointers = m_counts->DecStrongCount(); } else { m_counts->DecWeakCount(); + noStrongPointers = !m_counts->HasStrongPointer(); } - return !m_counts->HasStrongPointer(); + return noStrongPointers; } bool HasStrongPointer( void ) const @@ -832,7 +837,7 @@ //////////////////////////////////////////////////////////////////////////////// /// \class StrongPtr /// -/// \ingroup SmartPointerGroup +/// \ingroup SmartPointerGroup /// /// \param Strong default = true, /// \param OwnershipPolicy default = TwoRefCounts, @@ -855,7 +860,7 @@ template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS > class StrongPtr - : public OwnershipPolicy + : protected OwnershipPolicy , public ConversionPolicy , public CheckingPolicy< T * > , public ResetPolicy< T > @@ -1059,7 +1064,7 @@ } #else - + template < typename T1, @@ -1073,8 +1078,8 @@ > 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, @@ -1320,7 +1325,7 @@ Tester(int) {} void dummy() {} }; - + typedef void (Tester::*unspecified_boolean_type_)(); typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result @@ -1339,11 +1344,11 @@ { Insipid(PointerType) {} }; - + typedef typename Select< CP::allow, PointerType, Insipid >::Result AutomaticConversionResult; -public: +public: operator AutomaticConversionResult() const { return GetPointer(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2008-12-19 00:39:31
|
Revision: 914 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=914&view=rev Author: rich_sposato Date: 2008-12-19 00:39:29 +0000 (Fri, 19 Dec 2008) Log Message: ----------- Corrected inheritance for ownership policy. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2008-12-15 22:23:44 UTC (rev 913) +++ trunk/include/loki/StrongPtr.h 2008-12-19 00:39:29 UTC (rev 914) @@ -860,7 +860,7 @@ template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS > class StrongPtr - : protected OwnershipPolicy + : public OwnershipPolicy , public ConversionPolicy , public CheckingPolicy< T * > , public ResetPolicy< T > This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <syn...@us...> - 2009-11-21 10:31:54
|
Revision: 1058 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1058&view=rev Author: syntheticpp Date: 2009-11-21 10:31:47 +0000 (Sat, 21 Nov 2009) Log Message: ----------- seems this was removed by accident Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2009-11-20 06:37:12 UTC (rev 1057) +++ trunk/include/loki/StrongPtr.h 2009-11-21 10:31:47 UTC (rev 1058) @@ -1,4 +1,4 @@ -//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2006 Rich Sposato // The copyright on this file is protected under the terms of the MIT license. @@ -1778,4 +1778,36 @@ namespace std { //////////////////////////////////////////////////////////////////////////////// - /// specialization of std::less for StroeTracker@Private@Loki@@@std@@@std@@QBEXABV123@@Z |
From: <ric...@us...> - 2010-09-16 17:28:59
|
Revision: 1077 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1077&view=rev Author: rich_sposato Date: 2010-09-16 17:28:52 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Used initialization instead of assignment within constructor. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2010-09-16 17:26:29 UTC (rev 1076) +++ trunk/include/loki/StrongPtr.h 2010-09-16 17:28:52 UTC (rev 1077) @@ -22,7 +22,12 @@ #include <loki/Threads.h> #endif +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable: 4355 ) +#endif + //////////////////////////////////////////////////////////////////////////////// /// /// \par Terminology @@ -801,8 +806,9 @@ inline explicit TwoRefLinks( bool strong ) : m_pointer( 0 ) , m_strong( strong ) + , m_prev( this ) + , m_next( this ) { - m_prev = m_next = this; } TwoRefLinks( const void * p, bool strong ); @@ -1808,5 +1814,8 @@ //////////////////////////////////////////////////////////////////////////////// +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + #endif // end file guardian - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-10-30 03:09:32
|
Revision: 1079 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1079&view=rev Author: rich_sposato Date: 2010-10-30 03:09:25 +0000 (Sat, 30 Oct 2010) Log Message: ----------- Added 3 new policy classes to support single-owner smart pointers. Changed how ResetPolicy classes get called. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2010-09-16 17:32:24 UTC (rev 1078) +++ trunk/include/loki/StrongPtr.h 2010-10-30 03:09:25 UTC (rev 1079) @@ -58,9 +58,9 @@ /// -# explicit YourPolicy( bool strong ) /// -# YourPolicy( void * p, bool strong ) /// -# YourPolicy( const YourPolicy & rhs, bool strong ) +/// -# YourPolicy( const YourPolicy & rhs, bool isNull, bool strong ) +/// -# ~YourPolicy( void ) /// -# bool Release( bool strong ) -/// -# void Increment( bool strong ) -/// -# bool Decrement( bool strong ) /// -# bool HasStrongPointer( void ) const /// -# void Swap( YourPolicy & rhs ) /// -# void SetPointer( void * p ) @@ -100,11 +100,11 @@ /// /// \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. +/// -# bool OnReleaseAll( bool, bool ) const +/// -# bool OnResetAll( bool, bool ) const +/// The first bool parameter is true if the pointer which called the function +/// is strong. The second parameter is true if any copointer is strong. The +/// return value means the pointer can be reset or released. /// /// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies /// \ingroup SmartPointerGroup @@ -118,7 +118,10 @@ namespace Loki { +static const char * const StrongPtr_Single_Owner_Exception_Message = + "Object has more than one Owner - which violates the single owner policy for StrongPtr!"; + //////////////////////////////////////////////////////////////////////////////// /// \class DeleteUsingFree /// @@ -250,18 +253,45 @@ template < class P > struct CantResetWithStrong { - inline bool OnReleaseAll( bool hasStrongPtr ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { - return ! hasStrongPtr; + (void)isThisStrong; + return ! isAnyStrong; } - inline bool OnResetAll( bool hasStrongPtr ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { - return ! hasStrongPtr; + (void)isThisStrong; + return ! isAnyStrong; } }; //////////////////////////////////////////////////////////////////////////////// +/// \class OnlyStrongMayReset +/// +/// \ingroup StrongPointerResetGroup +/// Implementation of the ResetPolicy used by StrongPtr. It only allows a +/// a strong co-pointer to reset or release. This policy was made for use with +/// the single-owner policies. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +struct OnlyStrongMayReset +{ + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const + { + (void)isAnyStrong; + return isThisStrong; + } + + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const + { + (void)isAnyStrong; + return isThisStrong; + } +}; + +//////////////////////////////////////////////////////////////////////////////// /// \class AllowReset /// /// \ingroup StrongPointerResetGroup @@ -272,12 +302,16 @@ template < class P > struct AllowReset { - inline bool OnReleaseAll( bool ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return true; } - inline bool OnResetAll( bool ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return true; } }; @@ -293,18 +327,26 @@ template < class P > struct NeverReset { - inline bool OnReleaseAll( bool ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return false; } - inline bool OnResetAll( bool ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return false; } }; // ---------------------------------------------------------------------------- +// Forward declaration needed for pointer to single-owner strong pointer. +class SingleOwnerRefCount; +class Lockable1OwnerRefCount; + namespace Private { @@ -399,6 +441,8 @@ } private: + /// Default constructor not implemented. + TwoRefCountInfo( void ); /// Copy-constructor not implemented. TwoRefCountInfo( const TwoRefCountInfo & ); /// Copy-assignment operator not implemented. @@ -410,6 +454,105 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class OneOwnerRefCountInfo +/// +/// \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 OneOwnerRefCountInfo +{ +public: + + explicit OneOwnerRefCountInfo( SingleOwnerRefCount * ptr ); + + OneOwnerRefCountInfo( const void * p, SingleOwnerRefCount * ptr ); + + inline ~OneOwnerRefCountInfo( void ) + { + assert( NULL == m_strongPtr ); + assert( 0 == m_weakCount ); + } + + inline bool HasStrongPointer( void ) const + { + return ( NULL != m_strongPtr ); + } + + inline const SingleOwnerRefCount * GetStrongCoPointer( void ) const + { + return m_strongPtr; + } + + inline SingleOwnerRefCount * GetStrongCoPointer( void ) + { + return m_strongPtr; + } + + void SetStrongCoPtr( SingleOwnerRefCount * ptr ); + + inline bool HasWeakPointer( void ) const + { + return ( 0 < m_weakCount ); + } + + inline unsigned int GetWeakCount( void ) const + { + return m_weakCount; + } + + inline void IncWeakCount( void ) + { + ++m_weakCount; + } + + inline void DecWeakCount( void ) + { + assert( 0 < m_weakCount ); + --m_weakCount; + } + + inline void ZapPointer( void ) + { + m_pointer = NULL; + } + + void SetPointer( void * p ) + { + m_pointer = p; + } + + inline void * GetPointer( void ) const + { + return const_cast< void * >( m_pointer ); + } + + inline void * & GetPointerRef( void ) const + { + return const_cast< void * & >( m_pointer ); + } + +private: + /// Default constructor not implemented. + OneOwnerRefCountInfo( void ); + /// Copy constructor not implemented. + OneOwnerRefCountInfo( const OneOwnerRefCountInfo & ); + /// Copy-assignment operator not implemented. + OneOwnerRefCountInfo & operator = ( const OneOwnerRefCountInfo & ); + + const void * m_pointer; + SingleOwnerRefCount * m_strongPtr; + unsigned int m_weakCount; +}; + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +//////////////////////////////////////////////////////////////////////////////// /// \class LockableTwoRefCountInfo /// /// \ingroup StrongPointerOwnershipGroup @@ -427,8 +570,6 @@ /// do run properly. //////////////////////////////////////////////////////////////////////////////// -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - class LOKI_EXPORT LockableTwoRefCountInfo : private Loki::Private::TwoRefCountInfo { @@ -540,6 +681,154 @@ mutable LOKI_DEFAULT_MUTEX m_Mutex; }; +//////////////////////////////////////////////////////////////////////////////// +/// \class Lockable1OwnerRefCountInfo +/// +/// \ingroup StrongPointerOwnershipGroup +/// Implementation detail for thread-safe reference counting for 1 strong and +/// multiple weak pointers. It uses OneOwnerRefCountInfo to manage the pointers +/// and count. 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. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT Lockable1OwnerRefCountInfo + : private Loki::Private::OneOwnerRefCountInfo +{ +public: + + explicit Lockable1OwnerRefCountInfo( Lockable1OwnerRefCount * ptr ) + : OneOwnerRefCountInfo( reinterpret_cast< SingleOwnerRefCount * >( ptr ) ) + , m_Mutex() + { + } + + Lockable1OwnerRefCountInfo( const void * p, Lockable1OwnerRefCount * ptr ) + : OneOwnerRefCountInfo( p, + reinterpret_cast< SingleOwnerRefCount * >( ptr ) ) + , m_Mutex() + { + } + + inline ~Lockable1OwnerRefCountInfo( void ) + { + } + + inline void Lock( void ) const + { + m_Mutex.Lock(); + } + + inline void Unlock( void ) const + { + m_Mutex.Unlock(); + } + + inline const Lockable1OwnerRefCount * GetStrongCoPointer( void ) const + { + m_Mutex.Lock(); + const SingleOwnerRefCount * ptr = + OneOwnerRefCountInfo::GetStrongCoPointer(); + m_Mutex.Unlock(); + return reinterpret_cast< const Lockable1OwnerRefCount * >( ptr ); + } + + inline Lockable1OwnerRefCount * GetStrongCoPointer( void ) + { + m_Mutex.Lock(); + SingleOwnerRefCount * ptr = OneOwnerRefCountInfo::GetStrongCoPointer(); + m_Mutex.Unlock(); + return reinterpret_cast< Lockable1OwnerRefCount * >( ptr ); + } + + inline void SetStrongCoPtr( Lockable1OwnerRefCount * ptr ) + { + m_Mutex.Lock(); + SingleOwnerRefCount * p = reinterpret_cast< SingleOwnerRefCount * >( ptr ); + OneOwnerRefCountInfo::SetStrongCoPtr( p ); + m_Mutex.Unlock(); + } + + inline bool HasStrongPointer( void ) const + { + m_Mutex.Lock(); + const bool has = OneOwnerRefCountInfo::HasStrongPointer(); + m_Mutex.Unlock(); + return has; + } + + inline unsigned int GetWeakCount( void ) const + { + m_Mutex.Lock(); + const unsigned int weakCount = OneOwnerRefCountInfo::HasWeakPointer(); + m_Mutex.Unlock(); + return weakCount; + } + + inline bool HasWeakPointer( void ) const + { + m_Mutex.Lock(); + const bool has = OneOwnerRefCountInfo::HasWeakPointer(); + m_Mutex.Unlock(); + return has; + } + + inline void IncWeakCount( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::IncWeakCount(); + m_Mutex.Unlock(); + } + + inline void DecWeakCount( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::DecWeakCount(); + m_Mutex.Unlock(); + } + + inline void ZapPointer( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::ZapPointer(); + m_Mutex.Unlock(); + } + + void SetPointer( void * p ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::SetPointer( p ); + m_Mutex.Unlock(); + } + + inline void * GetPointer( void ) const + { + return OneOwnerRefCountInfo::GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return OneOwnerRefCountInfo::GetPointerRef(); + } + +private: + /// Default constructor is not available. + Lockable1OwnerRefCountInfo( void ); + /// Copy constructor is not available. + Lockable1OwnerRefCountInfo( const Lockable1OwnerRefCountInfo & ); + /// Copy-assignment operator is not available. + Lockable1OwnerRefCountInfo & operator = ( const Lockable1OwnerRefCountInfo & ); + + mutable LOKI_DEFAULT_MUTEX m_Mutex; +}; + #endif // if object-level-locking or class-level-locking } // end namespace Private @@ -582,7 +871,7 @@ return Decrement( strong ); } - bool HasStrongPointer( void ) const + inline bool HasStrongPointer( void ) const { return m_counts->HasStrongPointer(); } @@ -607,7 +896,12 @@ } private: + + /// Default constructor is not implemented. TwoRefCounts( void ); + /// Copy constructor is not implemented. + TwoRefCounts( const TwoRefCounts & ); + /// Copy-assignment operator is not implemented. TwoRefCounts & operator = ( const TwoRefCounts & ); void Increment( bool strong ); @@ -619,6 +913,93 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class SingleOwnerRefCount +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, TwoRefCounts, to enforce that only one StrongPtr may "own" a +/// resource. The resource is destroyed only when its sole owner dies even if +/// weak pointers access it. The constructors enforce the single-owner policy +/// by throwing a bad_logic exception if more than one strong pointer claims to +/// own the resource. Use this policy when you want the code to specify that +/// only one object owns a resource. +/// +/// \note This class is not designed for use with a multi-threaded model. +/// Tests using a multi-threaded model may not run properly. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT SingleOwnerRefCount +{ +protected: + + explicit SingleOwnerRefCount( bool strong ); + + SingleOwnerRefCount( const void * p, bool strong ); + + SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool strong ); + + SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool isNull, bool strong ); + + /** The destructor should not anything since the call to ZapPointer inside + StrongPtr::~StrongPtr will do the cleanup which this dtor would have done. + By the time the dtor is called, the underlying pointer, m_info, is NULL. + */ + inline ~SingleOwnerRefCount( void ) {} + + bool Release( bool strong ); + + inline bool HasStrongPointer( void ) const + { + return ( NULL != m_info->GetStrongCoPointer() ); + } + + void Swap( SingleOwnerRefCount & rhs ); + + void SetPointer( void * p ); + + void ZapPointer( void ); + + inline void * GetPointer( void ) const + { + return m_info->GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return m_info->GetPointerRef(); + } + +private: + /// Default constructor is not implemented. + SingleOwnerRefCount( void ); + /// Copy constructor is not implemented. + SingleOwnerRefCount( const SingleOwnerRefCount & ); + /// Copy-assignment operator is not implemented. + SingleOwnerRefCount & operator = ( const SingleOwnerRefCount & ); + + inline bool IsStrong( void ) const + { + return ( this == m_info->GetStrongCoPointer() ); + } + + ::Loki::Private::OneOwnerRefCountInfo * m_info; + +}; + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +//////////////////////////////////////////////////////////////////////////////// /// \class LockableTwoRefCounts /// /// \ingroup StrongPointerOwnershipGroup @@ -633,8 +1014,6 @@ /// do run properly. //////////////////////////////////////////////////////////////////////////////// -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - class LOKI_EXPORT LockableTwoRefCounts { typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; @@ -744,7 +1123,7 @@ void Swap( LockableTwoRefCounts & rhs ) { - std::swap( m_counts, rhs.m_counts ); + ::std::swap( m_counts, rhs.m_counts ); } void SetPointer( void * p ) @@ -780,13 +1159,250 @@ } private: + /// Default constructor is not implemented. LockableTwoRefCounts( void ); + /// Copy constructor is not implemented. + LockableTwoRefCounts( const LockableTwoRefCounts & ); + /// Copy-assignment operator is not implemented. LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & ); /// Pointer to all shared data. Loki::Private::LockableTwoRefCountInfo * m_counts; }; +//////////////////////////////////////////////////////////////////////////////// +/// \class Lockable1OwnerRefCount +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, LockableTwoRefCounts, to enforce that only one StrongPtr +/// may "own" a resource. The resource is destroyed only when its sole owner +/// dies regardless of how many weak pointers access it. The constructors +/// enforce the single-owner policy by throwing a bad_logic exception if more +/// than one strong pointer claims to own the resource. Use this policy when +/// you want the code to specify that only one object owns a resource. +/// +/// \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. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT Lockable1OwnerRefCount +{ + typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; + +protected: + + explicit Lockable1OwnerRefCount( bool strong ) + : m_info( NULL ) + { + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( ptr ); + } + + Lockable1OwnerRefCount( const void * p, bool strong ) + : m_info( NULL ) + { + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( p, ptr ); + } + + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & rhs, bool strong ) : + m_info( rhs.m_info ) + { + assert( NULL != this ); + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } + } + + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & rhs, + bool isNull, bool strong ) : + m_info( ( isNull ) ? NULL : rhs.m_info ) + { + assert( NULL != this ); + + if ( isNull ) + { + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( ptr ); + return; + } + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } + } + + /** 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 ~Lockable1OwnerRefCount( void ) {} + + inline void Lock( void ) const + { + m_info->Lock(); + } + + inline void Unlock( void ) const + { + m_info->Unlock(); + } + + inline bool Release( bool strong ) + { + assert( NULL != this ); + assert( strong == IsStrong() ); + + if ( strong ) + { + m_info->SetStrongCoPtr( NULL ); + return true; + } + + m_info->Lock(); + assert( 0 < m_info->GetWeakCount() ); + m_info->DecWeakCount(); + const bool noOwner = ( !m_info->HasStrongPointer() ); + const bool doRelease = ( ( 0 == m_info->GetWeakCount() ) && noOwner ); + m_info->Unlock(); + return doRelease; + } + + bool HasStrongPointer( void ) const + { + return m_info->HasStrongPointer(); + } + + void Swap( Lockable1OwnerRefCount & rhs ) + { + assert( NULL != this ); + m_info->Lock(); + rhs.m_info->Lock(); + + if ( IsStrong() && rhs.IsStrong() ) + { + // These two strong pointers are trading resources. + rhs.m_info->SetStrongCoPtr( this ); + m_info->SetStrongCoPtr( &rhs ); + } + ::std::swap( m_info, rhs.m_info ); + m_info->Unlock(); + rhs.m_info->Unlock(); + } + + void SetPointer( void * p ) + { + assert( NULL != this ); + if ( IsStrong() || ( 1 == m_info->GetWeakCount() ) ) + { + // Only a strong pointer or the last weak pointer may change a resource. + m_info->SetPointer( p ); + } + } + + void ZapPointer( void ) + { + assert( !m_info->HasStrongPointer() ); + if ( m_info->HasWeakPointer() ) + { + m_info->ZapPointer(); + } + else + { + SmallObject<>::operator delete ( m_info, + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); + m_info = NULL; + } + } + + inline void * GetPointer( void ) const + { + return m_info->GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return m_info->GetPointerRef(); + } + +private: + /// Default constructor is not implemented. + Lockable1OwnerRefCount( void ); + /// Copy constructor is not implemented. + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & ); + /// Copy-assignment operator is not implemented. + Lockable1OwnerRefCount & operator = ( const Lockable1OwnerRefCount & ); + + inline bool IsStrong( void ) const + { + return ( this == m_info->GetStrongCoPointer() ); + } + + /// Pointer to shared info about resource. + ::Loki::Private::Lockable1OwnerRefCountInfo * m_info; + +}; + #endif // if object-level-locking or class-level-locking //////////////////////////////////////////////////////////////////////////////// @@ -817,14 +1433,21 @@ TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong ); + ~TwoRefLinks( void ); + bool Release( bool strong ); void Swap( TwoRefLinks & rhs ); bool Merge( TwoRefLinks & rhs ); + /// Returns pointer to next link in cycle is a strong pointer. + const TwoRefLinks * GetNextStrongPointer( void ) const; + bool HasStrongPointer( void ) const; + unsigned int GetStrongPointerCount( void ) const; + inline void ZapPointer( void ) { ZapAllNodes(); @@ -842,13 +1465,20 @@ return const_cast< void * & >( m_pointer ); } + inline bool IsStrong( void ) const + { + return m_strong; + } + private: static unsigned int CountPrevCycle( const TwoRefLinks * pThis ); static unsigned int CountNextCycle( const TwoRefLinks * pThis ); - /// Not implemented. + /// Default constructor is not implemented. TwoRefLinks( void ); - /// Not implemented. + /// Copy constructor is not implemented. + TwoRefLinks( const TwoRefLinks & ); + /// Copy-assignment operator is not implemented. TwoRefLinks & operator = ( const TwoRefLinks & ); bool HasPrevNode( const TwoRefLinks * p ) const; @@ -856,6 +1486,8 @@ bool AllNodesHaveSamePointer( void ) const; void ZapAllNodes( void ); + bool IsValid( void ) const; + void * m_pointer; mutable TwoRefLinks * m_prev; mutable TwoRefLinks * m_next; @@ -863,6 +1495,61 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class SingleOwnerRefLinks +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, TwoRefLinks, to enforce that only one StrongPtr may "own" a +/// resource. The resource is destroyed only when its sole owner dies even if +/// weak pointers access it. The constructors enforce the single-owner policy +/// by throwing a bad_logic exception if more than one strong pointer claims to +/// own the resource. Use this policy when you want the code to specify that +/// only one object owns a resource. +/// +/// \note This class is not designed for use with a multi-threaded model. +/// Tests using a multi-threaded model may not run properly. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT SingleOwnerRefLinks : public TwoRefLinks +{ +protected: + + explicit SingleOwnerRefLinks( bool strong ); + + SingleOwnerRefLinks( const void * p, bool strong ); + + SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, bool strong ); + + SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, bool isNull, bool strong ); + + ~SingleOwnerRefLinks( void ); + + void Swap( SingleOwnerRefLinks & rhs ); + + bool Merge( SingleOwnerRefLinks & rhs ); + + bool Release( bool strong ); + +private: + + /// Default constructor is not implemented. + SingleOwnerRefLinks( void ); + /// Copy constructor is not implemented. + SingleOwnerRefLinks( const SingleOwnerRefLinks & ); + /// Copy-assignment operator is not implemented. + SingleOwnerRefLinks & operator = ( const SingleOwnerRefLinks & ); +}; + +//////////////////////////////////////////////////////////////////////////////// /// \class StrongPtr /// /// \ingroup SmartPointerGroup @@ -880,11 +1567,11 @@ < 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, + 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 @@ -1072,7 +1759,7 @@ return *this; } - bool IsStrong( void ) const + inline bool IsStrong( void ) const { return Strong; } @@ -1159,7 +1846,7 @@ friend bool ReleaseAll( StrongPtr & sp, typename StrongPtr::StoredType & p ) { - if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP::OnReleaseAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1175,7 +1862,7 @@ { return true; } - if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1498,7 +2185,7 @@ 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() ) ) + if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1526,7 +2213,7 @@ { return true; } - if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP<T>::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-09-20 17:51:32
|
Revision: 1104 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1104&view=rev Author: rich_sposato Date: 2011-09-20 17:51:26 +0000 (Tue, 20 Sep 2011) Log Message: ----------- Added ability for StrongPtr to handle arrays. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2011-09-17 02:25:43 UTC (rev 1103) +++ trunk/include/loki/StrongPtr.h 2011-09-20 17:51:26 UTC (rev 1104) @@ -134,7 +134,15 @@ template < class P > class DeleteUsingFree { -public: +protected: + + inline DeleteUsingFree( void ) {} + + inline DeleteUsingFree( const DeleteUsingFree & ) {} + + template < class P1 > + inline DeleteUsingFree( const DeleteUsingFree< P1 > & ) {} + inline void static Delete( const P * p ) { if ( 0 != p ) @@ -165,7 +173,15 @@ template < class P > class DeleteNothing { -public: +protected: + + inline DeleteNothing( void ) {} + + inline DeleteNothing( const DeleteNothing & ) {} + + template < class P1 > + inline DeleteNothing( const DeleteNothing< P1 > & ) {} + inline static void Delete( const P * ) { // Do nothing at all! @@ -177,6 +193,7 @@ } inline void Swap( DeleteNothing & ) {} + }; //////////////////////////////////////////////////////////////////////////////// @@ -190,7 +207,15 @@ template < class P > class DeleteSingle { -public: +protected: + + inline DeleteSingle( void ) {} + + inline DeleteSingle( const DeleteSingle & ) {} + + template < class P1 > + inline DeleteSingle( const DeleteSingle< P1 > & ) {} + inline static void Delete( const P * p ) { /** @note If you see an error message about a negative subscript, that @@ -210,7 +235,46 @@ inline void Swap( DeleteSingle & ) {} }; +namespace Private +{ + //////////////////////////////////////////////////////////////////////////////// +/// \class DeleteArrayBase +/// +/// \ingroup StrongPointerDeleteGroup +/// Base class used only by the DeleteArray policy class. This stores the +/// number of elements in an array of shared objects. +//////////////////////////////////////////////////////////////////////////////// + +class DeleteArrayBase +{ +public: + + inline size_t GetArrayCount( void ) const { return m_itemCount; } + +protected: + + DeleteArrayBase( void ) : m_itemCount( 0 ) {} + + explicit DeleteArrayBase( size_t itemCount ) : m_itemCount( itemCount ) {} + + DeleteArrayBase( const DeleteArrayBase & that ) : m_itemCount( that.m_itemCount ) {} + + void Swap( DeleteArrayBase & rhs ); + + void OnInit( const void * p ) const; + + void OnCheckRange( size_t index ) const; + +private: + + size_t m_itemCount; + +}; + +} + +//////////////////////////////////////////////////////////////////////////////// /// \class DeleteArray /// /// \ingroup StrongPointerDeleteGroup @@ -219,9 +283,19 @@ //////////////////////////////////////////////////////////////////////////////// template < class P > -class DeleteArray +class DeleteArray : public ::Loki::Private::DeleteArrayBase { public: + + DeleteArray( void ) : DeleteArrayBase() {} + + explicit DeleteArray( size_t itemCount ) : DeleteArrayBase( itemCount ) {} + + DeleteArray( const DeleteArray & that ) : DeleteArrayBase( that ) {} + + template < class P1 > + inline DeleteArray( const DeleteArray< P1 > & that ) : DeleteArrayBase( that ) {} + inline static void Delete( const P * p ) { /** @note If you see an error message about a negative subscript, that @@ -238,7 +312,6 @@ return 0; } - inline void Swap( DeleteArray & ) {} }; //////////////////////////////////////////////////////////////////////////////// @@ -1653,21 +1726,32 @@ public: - StrongPtr( void ) : OP( Strong ) + StrongPtr( void ) : OP( Strong ), DP() { KP::OnDefault( GetPointer() ); } - explicit StrongPtr( ExplicitArg p ) : OP( p, Strong ) + explicit StrongPtr( ExplicitArg p ) : OP( p, Strong ), DP() { KP::OnInit( GetPointer() ); } - StrongPtr( ImplicitArg p ) : OP( p, Strong ) + StrongPtr( ImplicitArg p ) : OP( p, Strong ), DP() { KP::OnInit( GetPointer() ); } + /** This constructor was designed to only work with the DeleteArray policy. Using it with any + other Delete policies will cause compiler errors. Call it with this syntax: + "ThingyPtr sp2( new Thingy[ 4 ], 4 );" so the StrongPtr knows how many elements are in the + array for range checking. + */ + StrongPtr( ImplicitArg p, size_t itemCount ) : OP( p, Strong ), DP( itemCount ) + { + KP::OnInit( GetPointer() ); + DP::OnInit( GetPointer() ); + } + StrongPtr( const StrongPtr & rhs ) : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs ) { @@ -1686,7 +1770,7 @@ > StrongPtr( const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - : OP( rhs, Strong ) + : OP( rhs, Strong ), CP( rhs ), DP( rhs ) { } @@ -1703,7 +1787,7 @@ > StrongPtr( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) - : OP( rhs, Strong ) + : OP( rhs, Strong ), CP( rhs ), DP( rhs ) { } @@ -1737,6 +1821,21 @@ return *this; } + /** This function is equivalent to an assignment operator for StrongPtr's that use the + DeleteArray policy where the programmer needs to write the equivalent of "sp = new P;". + With DeleteArray, the programmer should write "sp.Assign( new [5] Thingy, 5 );" so the + StrongPtr knows how many elements are in the array. + */ + StrongPtr & Assign( T * p, size_t itemCount ) + { + if ( GetPointer() != p ) + { + StrongPtr temp( p, itemCount ); + Swap( temp ); + } + return *this; + } + template < typename T1, @@ -1969,6 +2068,22 @@ return * GetPointer(); } + ReferenceType operator [] ( size_t index ) + { + KP::OnDereference( GetPointer() ); + DP::OnCheckRange( index ); + PointerType p = GetPointer(); + return p[ index ]; + } + + ConstReferenceType operator [] ( size_t index ) const + { + KP::OnDereference( GetPointer() ); + DP::OnCheckRange( index ); + ConstPointerType p = GetPointer(); + return p[ index ]; + } + /// Helper function which can be called to avoid exposing GetPointer function. template < class T1 > bool Equals( const T1 * p ) const This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |