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:
rich_sposato 2010-10-30 03:09:25 +00:00
parent 75ce7d41ba
commit 21f46072bd

View file

@ -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,6 +118,9 @@
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,14 +253,41 @@ public:
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;
}
};
@ -272,12 +302,16 @@ struct CantResetWithStrong
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 @@ struct AllowReset
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 @@ public:
}
private:
/// Default constructor not implemented.
TwoRefCountInfo( void );
/// Copy-constructor not implemented.
TwoRefCountInfo( const TwoRefCountInfo & );
/// Copy-assignment operator not implemented.
@ -409,6 +453,105 @@ private:
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
///
@ -427,8 +570,6 @@ private:
/// 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 @@ private:
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 @@ protected:
return Decrement( strong );
}
bool HasStrongPointer( void ) const
inline bool HasStrongPointer( void ) const
{
return m_counts->HasStrongPointer();
}
@ -607,7 +896,12 @@ protected:
}
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 );
@ -618,6 +912,93 @@ private:
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
///
@ -633,8 +1014,6 @@ private:
/// 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 @@ protected:
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 @@ protected:
}
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 @@ protected:
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 @@ protected:
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,12 +1486,69 @@ private:
bool AllNodesHaveSamePointer( void ) const;
void ZapAllNodes( void );
bool IsValid( void ) const;
void * m_pointer;
mutable TwoRefLinks * m_prev;
mutable TwoRefLinks * m_next;
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
///
@ -880,11 +1567,11 @@ template
<
typename T,
bool Strong = true,
class OwnershipPolicy = Loki::TwoRefCounts,
class ConversionPolicy = Loki::DisallowConversion,
template < class > class CheckingPolicy = Loki::AssertCheck,
template < class > class ResetPolicy = Loki::CantResetWithStrong,
template < class > class DeletePolicy = Loki::DeleteSingle,
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 @@ public:
return *this;
}
bool IsStrong( void ) const
inline bool IsStrong( void ) const
{
return Strong;
}
@ -1159,7 +1846,7 @@ public:
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 @@ public:
{
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 @@ template
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 @@ bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
{
return true;
}
if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
if ( !sp.RP<T>::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) )
{
return false;
}