Added 3 new policy classes to support single-owner smart
pointers. Changed how ResetPolicy classes get called. git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1079 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
75ce7d41ba
commit
21f46072bd
1 changed files with 720 additions and 33 deletions
|
@ -58,9 +58,9 @@
|
||||||
/// -# explicit YourPolicy( bool strong )
|
/// -# explicit YourPolicy( bool strong )
|
||||||
/// -# YourPolicy( void * p, bool strong )
|
/// -# YourPolicy( void * p, bool strong )
|
||||||
/// -# YourPolicy( const YourPolicy & rhs, bool strong )
|
/// -# YourPolicy( const YourPolicy & rhs, bool strong )
|
||||||
|
/// -# YourPolicy( const YourPolicy & rhs, bool isNull, bool strong )
|
||||||
|
/// -# ~YourPolicy( void )
|
||||||
/// -# bool Release( bool strong )
|
/// -# bool Release( bool strong )
|
||||||
/// -# void Increment( bool strong )
|
|
||||||
/// -# bool Decrement( bool strong )
|
|
||||||
/// -# bool HasStrongPointer( void ) const
|
/// -# bool HasStrongPointer( void ) const
|
||||||
/// -# void Swap( YourPolicy & rhs )
|
/// -# void Swap( YourPolicy & rhs )
|
||||||
/// -# void SetPointer( void * p )
|
/// -# void SetPointer( void * p )
|
||||||
|
@ -100,11 +100,11 @@
|
||||||
///
|
///
|
||||||
/// \par Writing Your Own ResetPolicy
|
/// \par Writing Your Own ResetPolicy
|
||||||
/// If you write your own policy, you must implement these 2 functions:
|
/// If you write your own policy, you must implement these 2 functions:
|
||||||
/// -# bool OnReleaseAll( bool ) const
|
/// -# bool OnReleaseAll( bool, bool ) const
|
||||||
/// -# bool OnResetAll( bool ) const
|
/// -# bool OnResetAll( bool, bool ) const
|
||||||
/// The bool parameter means that this was called with a strong pointer or
|
/// The first bool parameter is true if the pointer which called the function
|
||||||
/// one of its copointers is strong. The return value means the pointer
|
/// is strong. The second parameter is true if any copointer is strong. The
|
||||||
/// can be reset or released.
|
/// return value means the pointer can be reset or released.
|
||||||
///
|
///
|
||||||
/// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies
|
/// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies
|
||||||
/// \ingroup SmartPointerGroup
|
/// \ingroup SmartPointerGroup
|
||||||
|
@ -118,6 +118,9 @@
|
||||||
namespace Loki
|
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
|
/// \class DeleteUsingFree
|
||||||
|
@ -250,14 +253,41 @@ public:
|
||||||
template < class P >
|
template < class P >
|
||||||
struct CantResetWithStrong
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,12 +302,16 @@ struct CantResetWithStrong
|
||||||
template < class P >
|
template < class P >
|
||||||
struct AllowReset
|
struct AllowReset
|
||||||
{
|
{
|
||||||
inline bool OnReleaseAll( bool ) const
|
inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const
|
||||||
{
|
{
|
||||||
|
(void)isThisStrong;
|
||||||
|
(void)isAnyStrong;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
inline bool OnResetAll( bool ) const
|
inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const
|
||||||
{
|
{
|
||||||
|
(void)isThisStrong;
|
||||||
|
(void)isAnyStrong;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -293,18 +327,26 @@ struct AllowReset
|
||||||
template < class P >
|
template < class P >
|
||||||
struct NeverReset
|
struct NeverReset
|
||||||
{
|
{
|
||||||
inline bool OnReleaseAll( bool ) const
|
inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const
|
||||||
{
|
{
|
||||||
|
(void)isThisStrong;
|
||||||
|
(void)isAnyStrong;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool OnResetAll( bool ) const
|
inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const
|
||||||
{
|
{
|
||||||
|
(void)isThisStrong;
|
||||||
|
(void)isAnyStrong;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Forward declaration needed for pointer to single-owner strong pointer.
|
||||||
|
class SingleOwnerRefCount;
|
||||||
|
class Lockable1OwnerRefCount;
|
||||||
|
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -399,6 +441,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Default constructor not implemented.
|
||||||
|
TwoRefCountInfo( void );
|
||||||
/// Copy-constructor not implemented.
|
/// Copy-constructor not implemented.
|
||||||
TwoRefCountInfo( const TwoRefCountInfo & );
|
TwoRefCountInfo( const TwoRefCountInfo & );
|
||||||
/// Copy-assignment operator not implemented.
|
/// Copy-assignment operator not implemented.
|
||||||
|
@ -409,6 +453,105 @@ private:
|
||||||
unsigned int m_weakCount;
|
unsigned int m_weakCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// \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
|
/// \class LockableTwoRefCountInfo
|
||||||
///
|
///
|
||||||
|
@ -427,8 +570,6 @@ private:
|
||||||
/// do run properly.
|
/// do run properly.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
|
|
||||||
|
|
||||||
class LOKI_EXPORT LockableTwoRefCountInfo
|
class LOKI_EXPORT LockableTwoRefCountInfo
|
||||||
: private Loki::Private::TwoRefCountInfo
|
: private Loki::Private::TwoRefCountInfo
|
||||||
{
|
{
|
||||||
|
@ -540,6 +681,154 @@ private:
|
||||||
mutable LOKI_DEFAULT_MUTEX m_Mutex;
|
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
|
#endif // if object-level-locking or class-level-locking
|
||||||
|
|
||||||
} // end namespace Private
|
} // end namespace Private
|
||||||
|
@ -582,7 +871,7 @@ protected:
|
||||||
return Decrement( strong );
|
return Decrement( strong );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasStrongPointer( void ) const
|
inline bool HasStrongPointer( void ) const
|
||||||
{
|
{
|
||||||
return m_counts->HasStrongPointer();
|
return m_counts->HasStrongPointer();
|
||||||
}
|
}
|
||||||
|
@ -607,7 +896,12 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/// Default constructor is not implemented.
|
||||||
TwoRefCounts( void );
|
TwoRefCounts( void );
|
||||||
|
/// Copy constructor is not implemented.
|
||||||
|
TwoRefCounts( const TwoRefCounts & );
|
||||||
|
/// Copy-assignment operator is not implemented.
|
||||||
TwoRefCounts & operator = ( const TwoRefCounts & );
|
TwoRefCounts & operator = ( const TwoRefCounts & );
|
||||||
|
|
||||||
void Increment( bool strong );
|
void Increment( bool strong );
|
||||||
|
@ -618,6 +912,93 @@ private:
|
||||||
Loki::Private::TwoRefCountInfo * m_counts;
|
Loki::Private::TwoRefCountInfo * m_counts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// \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
|
/// \class LockableTwoRefCounts
|
||||||
///
|
///
|
||||||
|
@ -633,8 +1014,6 @@ private:
|
||||||
/// do run properly.
|
/// do run properly.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
|
|
||||||
|
|
||||||
class LOKI_EXPORT LockableTwoRefCounts
|
class LOKI_EXPORT LockableTwoRefCounts
|
||||||
{
|
{
|
||||||
typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
|
typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
|
||||||
|
@ -744,7 +1123,7 @@ protected:
|
||||||
|
|
||||||
void Swap( LockableTwoRefCounts & rhs )
|
void Swap( LockableTwoRefCounts & rhs )
|
||||||
{
|
{
|
||||||
std::swap( m_counts, rhs.m_counts );
|
::std::swap( m_counts, rhs.m_counts );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPointer( void * p )
|
void SetPointer( void * p )
|
||||||
|
@ -780,13 +1159,250 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Default constructor is not implemented.
|
||||||
LockableTwoRefCounts( void );
|
LockableTwoRefCounts( void );
|
||||||
|
/// Copy constructor is not implemented.
|
||||||
|
LockableTwoRefCounts( const LockableTwoRefCounts & );
|
||||||
|
/// Copy-assignment operator is not implemented.
|
||||||
LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & );
|
LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & );
|
||||||
|
|
||||||
/// Pointer to all shared data.
|
/// Pointer to all shared data.
|
||||||
Loki::Private::LockableTwoRefCountInfo * m_counts;
|
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
|
#endif // if object-level-locking or class-level-locking
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -817,14 +1433,21 @@ protected:
|
||||||
|
|
||||||
TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong );
|
TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong );
|
||||||
|
|
||||||
|
~TwoRefLinks( void );
|
||||||
|
|
||||||
bool Release( bool strong );
|
bool Release( bool strong );
|
||||||
|
|
||||||
void Swap( TwoRefLinks & rhs );
|
void Swap( TwoRefLinks & rhs );
|
||||||
|
|
||||||
bool Merge( 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;
|
bool HasStrongPointer( void ) const;
|
||||||
|
|
||||||
|
unsigned int GetStrongPointerCount( void ) const;
|
||||||
|
|
||||||
inline void ZapPointer( void )
|
inline void ZapPointer( void )
|
||||||
{
|
{
|
||||||
ZapAllNodes();
|
ZapAllNodes();
|
||||||
|
@ -842,13 +1465,20 @@ protected:
|
||||||
return const_cast< void * & >( m_pointer );
|
return const_cast< void * & >( m_pointer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsStrong( void ) const
|
||||||
|
{
|
||||||
|
return m_strong;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static unsigned int CountPrevCycle( const TwoRefLinks * pThis );
|
static unsigned int CountPrevCycle( const TwoRefLinks * pThis );
|
||||||
static unsigned int CountNextCycle( const TwoRefLinks * pThis );
|
static unsigned int CountNextCycle( const TwoRefLinks * pThis );
|
||||||
|
|
||||||
/// Not implemented.
|
/// Default constructor is not implemented.
|
||||||
TwoRefLinks( void );
|
TwoRefLinks( void );
|
||||||
/// Not implemented.
|
/// Copy constructor is not implemented.
|
||||||
|
TwoRefLinks( const TwoRefLinks & );
|
||||||
|
/// Copy-assignment operator is not implemented.
|
||||||
TwoRefLinks & operator = ( const TwoRefLinks & );
|
TwoRefLinks & operator = ( const TwoRefLinks & );
|
||||||
|
|
||||||
bool HasPrevNode( const TwoRefLinks * p ) const;
|
bool HasPrevNode( const TwoRefLinks * p ) const;
|
||||||
|
@ -856,12 +1486,69 @@ private:
|
||||||
bool AllNodesHaveSamePointer( void ) const;
|
bool AllNodesHaveSamePointer( void ) const;
|
||||||
void ZapAllNodes( void );
|
void ZapAllNodes( void );
|
||||||
|
|
||||||
|
bool IsValid( void ) const;
|
||||||
|
|
||||||
void * m_pointer;
|
void * m_pointer;
|
||||||
mutable TwoRefLinks * m_prev;
|
mutable TwoRefLinks * m_prev;
|
||||||
mutable TwoRefLinks * m_next;
|
mutable TwoRefLinks * m_next;
|
||||||
const bool m_strong;
|
const bool m_strong;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// \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
|
/// \class StrongPtr
|
||||||
///
|
///
|
||||||
|
@ -880,11 +1567,11 @@ template
|
||||||
<
|
<
|
||||||
typename T,
|
typename T,
|
||||||
bool Strong = true,
|
bool Strong = true,
|
||||||
class OwnershipPolicy = Loki::TwoRefCounts,
|
class OwnershipPolicy = ::Loki::TwoRefCounts,
|
||||||
class ConversionPolicy = Loki::DisallowConversion,
|
class ConversionPolicy = ::Loki::DisallowConversion,
|
||||||
template < class > class CheckingPolicy = Loki::AssertCheck,
|
template < class > class CheckingPolicy = ::Loki::AssertCheck,
|
||||||
template < class > class ResetPolicy = Loki::CantResetWithStrong,
|
template < class > class ResetPolicy = ::Loki::CantResetWithStrong,
|
||||||
template < class > class DeletePolicy = Loki::DeleteSingle,
|
template < class > class DeletePolicy = ::Loki::DeleteSingle,
|
||||||
template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
||||||
>
|
>
|
||||||
class StrongPtr
|
class StrongPtr
|
||||||
|
@ -1072,7 +1759,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsStrong( void ) const
|
inline bool IsStrong( void ) const
|
||||||
{
|
{
|
||||||
return Strong;
|
return Strong;
|
||||||
}
|
}
|
||||||
|
@ -1159,7 +1846,7 @@ public:
|
||||||
friend bool ReleaseAll( StrongPtr & sp,
|
friend bool ReleaseAll( StrongPtr & sp,
|
||||||
typename StrongPtr::StoredType & p )
|
typename StrongPtr::StoredType & p )
|
||||||
{
|
{
|
||||||
if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
|
if ( !sp.RP::OnReleaseAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1175,7 +1862,7 @@ public:
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
|
if ( !sp.RP::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1498,7 +2185,7 @@ template
|
||||||
bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
|
bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
|
||||||
typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p )
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1526,7 +2213,7 @@ bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
|
if ( !sp.RP<T>::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue