Added StrongPtr class to Loki along with tests for StrongPtr.
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@623 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
0201647cdc
commit
d5f4f0f77f
7 changed files with 3294 additions and 52 deletions
1459
include/loki/StrongPtr.h
Normal file
1459
include/loki/StrongPtr.h
Normal file
File diff suppressed because it is too large
Load diff
619
src/StrongPtr.cpp
Normal file
619
src/StrongPtr.cpp
Normal file
|
@ -0,0 +1,619 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2006 Rich Sposato
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Header$
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <loki/StrongPtr.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <loki/SmallObj.h>
|
||||
|
||||
//#define DO_EXTRA_LOKI_TESTS
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TwoRefCounts::TwoRefCounts( bool strong )
|
||||
: m_counts( NULL )
|
||||
{
|
||||
void * temp = SmallObject<>::operator new(
|
||||
sizeof(Loki::Private::TwoRefCountInfo) );
|
||||
assert( temp != 0 );
|
||||
m_counts = new ( temp ) Loki::Private::TwoRefCountInfo( strong );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TwoRefCounts::TwoRefCounts( const void * p, bool strong )
|
||||
: m_counts( NULL )
|
||||
{
|
||||
void * temp = SmallObject<>::operator new(
|
||||
sizeof(Loki::Private::TwoRefCountInfo) );
|
||||
assert( temp != 0 );
|
||||
void * p2 = const_cast< void * >( p );
|
||||
m_counts = new ( temp ) Loki::Private::TwoRefCountInfo( p2, strong );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefCounts::Increment( bool strong )
|
||||
{
|
||||
if ( strong )
|
||||
{
|
||||
m_counts->IncStrongCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_counts->IncWeakCount();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefCounts::Decrement( bool strong )
|
||||
{
|
||||
if ( strong )
|
||||
{
|
||||
m_counts->DecStrongCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_counts->DecWeakCount();
|
||||
}
|
||||
return !m_counts->HasStrongPointer();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefCounts::Swap( TwoRefCounts & rhs )
|
||||
{
|
||||
std::swap( m_counts, rhs.m_counts );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefCounts::ZapPointer( void )
|
||||
{
|
||||
assert( !m_counts->HasStrongPointer() );
|
||||
if ( m_counts->HasWeakPointer() )
|
||||
{
|
||||
m_counts->ZapPointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
SmallObject<>::operator delete ( m_counts,
|
||||
sizeof(Loki::Private::TwoRefCountInfo) );
|
||||
m_counts = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
LockableTwoRefCounts::LockableTwoRefCounts( bool strong )
|
||||
: m_counts( NULL )
|
||||
{
|
||||
void * temp = SmallObject<>::operator new(
|
||||
sizeof(Loki::Private::LockableTwoRefCountInfo) );
|
||||
assert( temp != 0 );
|
||||
m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
LockableTwoRefCounts::LockableTwoRefCounts( const void * p, bool strong )
|
||||
: m_counts( NULL )
|
||||
{
|
||||
void * temp = SmallObject<>::operator new(
|
||||
sizeof(Loki::Private::LockableTwoRefCountInfo) );
|
||||
assert( temp != 0 );
|
||||
void * p2 = const_cast< void * >( p );
|
||||
m_counts = new ( temp )
|
||||
Loki::Private::LockableTwoRefCountInfo( p2, strong );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void LockableTwoRefCounts::Increment( bool strong )
|
||||
{
|
||||
if ( strong )
|
||||
{
|
||||
m_counts->IncStrongCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_counts->IncWeakCount();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool LockableTwoRefCounts::Decrement( bool strong )
|
||||
{
|
||||
if ( strong )
|
||||
{
|
||||
m_counts->DecStrongCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_counts->DecWeakCount();
|
||||
}
|
||||
return !m_counts->HasStrongPointer();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void LockableTwoRefCounts::Swap( LockableTwoRefCounts & rhs )
|
||||
{
|
||||
std::swap( m_counts, rhs.m_counts );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void LockableTwoRefCounts::ZapPointer( void )
|
||||
{
|
||||
assert( !m_counts->HasStrongPointer() );
|
||||
if ( m_counts->HasWeakPointer() )
|
||||
{
|
||||
m_counts->ZapPointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
SmallObject<>::operator delete ( m_counts,
|
||||
sizeof(Loki::Private::LockableTwoRefCountInfo) );
|
||||
m_counts = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
//namespace Private
|
||||
//{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TwoRefLinks::TwoRefLinks( const void * p, bool strong )
|
||||
: m_strong( strong )
|
||||
, m_pointer( const_cast< void * >( p ) )
|
||||
{
|
||||
m_prev = m_next = this;
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TwoRefLinks::TwoRefLinks( const TwoRefLinks & rhs, bool strong )
|
||||
: m_strong( strong )
|
||||
, m_prev( const_cast< TwoRefLinks * >( &rhs ) )
|
||||
, m_next( rhs.m_next )
|
||||
, m_pointer( rhs.m_pointer )
|
||||
{
|
||||
m_prev->m_next = this;
|
||||
m_next->m_prev = this;
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( rhs.m_next->HasNextNode( this ) );
|
||||
assert( rhs.m_prev->HasPrevNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( &rhs ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefLinks::SetPointer( void * p )
|
||||
{
|
||||
TwoRefLinks * node = m_prev;
|
||||
if ( ( this == node ) || ( 0 == node ) )
|
||||
return;
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
|
||||
while ( node != this )
|
||||
{
|
||||
node->m_pointer = p;
|
||||
node = node->m_next;
|
||||
}
|
||||
m_pointer = node;
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::Release( bool strong )
|
||||
{
|
||||
|
||||
assert( strong == m_strong );
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
|
||||
if ( NULL == m_next )
|
||||
{
|
||||
assert( NULL == m_prev );
|
||||
// Return false so it does not try to destroy shared object
|
||||
// more than once.
|
||||
return false;
|
||||
}
|
||||
else if (m_next == this)
|
||||
{
|
||||
assert(m_prev == this);
|
||||
// Set these to NULL to prevent re-entrancy.
|
||||
m_prev = NULL;
|
||||
m_next = NULL;
|
||||
// Last one in the cycle has to release the pointer.
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( this != m_prev );
|
||||
assert( NULL != m_prev );
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
#endif
|
||||
|
||||
// If a single node is strong, then return false so it won't release.
|
||||
if ( HasStrongPointer() )
|
||||
{
|
||||
// A cyclic chain of pointers is only as strong as the strongest link.
|
||||
m_prev->m_next = m_next;
|
||||
m_next->m_prev = m_prev;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefLinks::ZapAllNodes( void )
|
||||
{
|
||||
TwoRefLinks * p = m_prev;
|
||||
if ( ( this == p ) || ( 0 == p ) )
|
||||
return;
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
|
||||
while ( p != this )
|
||||
{
|
||||
TwoRefLinks * p1 = p->m_prev;
|
||||
p->m_pointer = 0;
|
||||
p->m_next = p;
|
||||
p->m_prev = p;
|
||||
p = p1;
|
||||
}
|
||||
m_pointer = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void TwoRefLinks::Swap( TwoRefLinks & rhs )
|
||||
{
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
assert( rhs.AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
|
||||
std::swap( rhs.m_pointer, m_pointer );
|
||||
if (m_next == this)
|
||||
{
|
||||
// This is in a cycle by itself.
|
||||
assert(m_prev == this);
|
||||
if (rhs.m_next == &rhs)
|
||||
{
|
||||
assert(rhs.m_prev == &rhs);
|
||||
// both are in 1-node cycles - thus there is nothing to do.
|
||||
return;
|
||||
}
|
||||
m_prev = rhs.m_prev;
|
||||
m_next = rhs.m_next;
|
||||
m_prev->m_next = m_next->m_prev = this;
|
||||
rhs.m_next = rhs.m_prev = &rhs;
|
||||
return;
|
||||
}
|
||||
if (rhs.m_next == &rhs)
|
||||
{
|
||||
// rhs is in a cycle by itself.
|
||||
assert( rhs.m_prev == &rhs );
|
||||
// rhs.Swap(*this);
|
||||
rhs.m_prev = m_prev;
|
||||
rhs.m_next = m_next;
|
||||
m_prev->m_next = m_next->m_prev = &rhs;
|
||||
m_next = m_prev = this;
|
||||
return;
|
||||
}
|
||||
if (m_next == &rhs ) // rhs is next neighbour
|
||||
{
|
||||
if ( m_prev == &rhs )
|
||||
return; // cycle of 2 pointers - no need to swap.
|
||||
std::swap(m_prev, m_next);
|
||||
std::swap(rhs.m_prev, rhs.m_next);
|
||||
std::swap(rhs.m_prev, m_next);
|
||||
std::swap(rhs.m_prev->m_next,m_next->m_prev);
|
||||
}
|
||||
else if ( m_prev == &rhs ) // rhs is prev neighbor
|
||||
{
|
||||
if ( m_next == &rhs )
|
||||
return; // cycle of 2 pointers - no need to swap.
|
||||
std::swap( m_prev, m_next );
|
||||
std::swap( rhs.m_next, rhs.m_prev );
|
||||
std::swap( rhs.m_next, m_prev );
|
||||
std::swap( rhs.m_next->m_prev, m_prev->m_next );
|
||||
}
|
||||
else // not neighhbors
|
||||
{
|
||||
std::swap(m_prev, rhs.m_prev);
|
||||
std::swap(m_next, rhs.m_next);
|
||||
std::swap(m_prev->m_next, rhs.m_prev->m_next);
|
||||
std::swap(m_next->m_prev, rhs.m_next->m_prev);
|
||||
}
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
assert( m_next == this ? m_prev == this : m_prev != this);
|
||||
assert( m_prev == this ? m_next == this : m_next != this);
|
||||
assert( m_prev->HasPrevNode( this ) );
|
||||
assert( m_next->HasNextNode( this ) );
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( rhs.m_prev->HasPrevNode( &rhs ) );
|
||||
assert( rhs.m_next->HasNextNode( &rhs ) );
|
||||
assert( CountPrevCycle( &rhs ) == CountNextCycle( &rhs ) );
|
||||
assert( AllNodesHaveSamePointer() );
|
||||
assert( rhs.AllNodesHaveSamePointer() );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::AllNodesHaveSamePointer( void ) const
|
||||
{
|
||||
const TwoRefLinks * next = m_next;
|
||||
if ( NULL == next )
|
||||
return true;
|
||||
do
|
||||
{
|
||||
if ( next->m_pointer != m_pointer )
|
||||
return false;
|
||||
next = next->m_next;
|
||||
} while ( next != this );
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
unsigned int TwoRefLinks::CountPrevCycle( const TwoRefLinks * pThis )
|
||||
{
|
||||
if ( NULL == pThis )
|
||||
return 0;
|
||||
const TwoRefLinks * p = pThis->m_prev;
|
||||
if ( NULL == p )
|
||||
return 0;
|
||||
if ( pThis == p )
|
||||
return 1;
|
||||
|
||||
unsigned int count = 1;
|
||||
do
|
||||
{
|
||||
p = p->m_prev;
|
||||
++count;
|
||||
} while ( p != pThis );
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
unsigned int TwoRefLinks::CountNextCycle( const TwoRefLinks * pThis )
|
||||
{
|
||||
if ( NULL == pThis )
|
||||
return 0;
|
||||
const TwoRefLinks * p = pThis->m_next;
|
||||
if ( NULL == p )
|
||||
return 0;
|
||||
if ( pThis == p )
|
||||
return 1;
|
||||
|
||||
unsigned int count = 1;
|
||||
while ( p != pThis )
|
||||
{
|
||||
p = p->m_next;
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::HasPrevNode( const TwoRefLinks * p ) const
|
||||
{
|
||||
if ( this == p )
|
||||
return true;
|
||||
const TwoRefLinks * prev = m_prev;
|
||||
if ( NULL == prev )
|
||||
return false;
|
||||
while ( prev != this )
|
||||
{
|
||||
if ( p == prev )
|
||||
return true;
|
||||
prev = prev->m_prev;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::HasNextNode( const TwoRefLinks * p ) const
|
||||
{
|
||||
if ( this == p )
|
||||
return true;
|
||||
const TwoRefLinks * next = m_next;
|
||||
if ( NULL == next )
|
||||
return false;
|
||||
while ( next != this )
|
||||
{
|
||||
if ( p == next )
|
||||
return true;
|
||||
next = next->m_next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::HasStrongPointer( void ) const
|
||||
{
|
||||
const TwoRefLinks * next = m_next;
|
||||
if ( NULL == next )
|
||||
return false;
|
||||
while ( next != this )
|
||||
{
|
||||
if ( next->m_strong )
|
||||
return true;
|
||||
next = next->m_next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool TwoRefLinks::Merge( TwoRefLinks & rhs )
|
||||
{
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << std::endl << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
|
||||
if ( NULL == m_next )
|
||||
{
|
||||
assert( NULL == m_prev );
|
||||
return false;
|
||||
}
|
||||
TwoRefLinks * prhs = &rhs;
|
||||
if ( prhs == this )
|
||||
return true;
|
||||
if ( NULL == prhs->m_next )
|
||||
{
|
||||
assert( NULL == prhs->m_prev );
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
assert( CountPrevCycle( prhs ) == CountNextCycle( prhs ) );
|
||||
// If rhs node is already in this cycle, then no need to merge.
|
||||
if ( HasPrevNode( &rhs ) )
|
||||
{
|
||||
assert( HasNextNode( &rhs ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
|
||||
if ( prhs == prhs->m_next )
|
||||
{
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
/// rhs is in a cycle with 1 node.
|
||||
assert( prhs->m_prev == prhs );
|
||||
prhs->m_prev = m_prev;
|
||||
prhs->m_next = this;
|
||||
m_prev->m_next = prhs;
|
||||
m_prev = prhs;
|
||||
}
|
||||
else if ( this == m_next )
|
||||
{
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
/// this is in a cycle with 1 node.
|
||||
assert( m_prev == this );
|
||||
m_prev = prhs->m_prev;
|
||||
m_next = prhs;
|
||||
prhs->m_prev->m_next = this;
|
||||
prhs->m_prev = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
m_next->m_prev = prhs->m_prev;
|
||||
prhs->m_prev->m_next = m_prev;
|
||||
m_next = prhs;
|
||||
prhs->m_prev = this;
|
||||
}
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
|
||||
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
|
||||
|
||||
#ifdef DO_EXTRA_LOKI_TESTS
|
||||
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
//} // end namespace Private
|
||||
|
||||
} // end namespace Loki
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// $Log$
|
||||
// Revision 1.1 2006/04/05 22:53:10 rich_sposato
|
||||
// Added StrongPtr class to Loki along with tests for StrongPtr.
|
||||
//
|
|
@ -1,11 +1,11 @@
|
|||
[Project]
|
||||
FileName=SmartPtr.dev
|
||||
Name=SmartPtr
|
||||
UnitCount=10
|
||||
UnitCount=12
|
||||
Type=1
|
||||
Ver=1
|
||||
ObjFiles=
|
||||
Includes=C:\Projects\loki\include
|
||||
Includes=C:\DevCpp\include;C:\Projects\loki\include
|
||||
Libs=
|
||||
PrivateResource=
|
||||
ResourceIncludes=
|
||||
|
@ -20,49 +20,49 @@ ObjectOutput=
|
|||
OverrideOutput=0
|
||||
OverrideOutputName=SmartPtr.exe
|
||||
HostApplication=
|
||||
Folders=Loki_Headers,Loki_Sources,Test
|
||||
Folders=Headers,Sources,Tests
|
||||
CommandLine=
|
||||
UseCustomMakefile=0
|
||||
CustomMakefile=
|
||||
IncludeVersionInfo=0
|
||||
SupportXPThemes=0
|
||||
CompilerSet=0
|
||||
CompilerSettings=1000001001001001000000
|
||||
CompilerSettings=0000001001001001000000
|
||||
|
||||
[Unit1]
|
||||
FileName=..\..\src\Singleton.cpp
|
||||
FileName=main.cpp
|
||||
CompileCpp=1
|
||||
Folder=Loki_Sources
|
||||
Folder=Tests
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit2]
|
||||
FileName=..\..\src\SmallObj.cpp
|
||||
FileName=..\..\src\Singleton.cpp
|
||||
CompileCpp=1
|
||||
Folder=Loki_Sources
|
||||
Folder=Sources
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=2
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit3]
|
||||
FileName=..\..\src\SmartPtr.cpp
|
||||
FileName=..\..\src\SmallObj.cpp
|
||||
CompileCpp=1
|
||||
Folder=Loki_Sources
|
||||
Folder=Sources
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=3
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit4]
|
||||
FileName=..\..\include\loki\Threads.h
|
||||
CompileCpp=1
|
||||
Folder=Loki_Headers
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
|
@ -70,9 +70,9 @@ OverrideBuildCmd=0
|
|||
BuildCmd=
|
||||
|
||||
[Unit5]
|
||||
FileName=..\..\include\loki\ConstPolicy.h
|
||||
FileName=..\..\include\loki\Singleton.h
|
||||
CompileCpp=1
|
||||
Folder=Loki_Headers
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
|
@ -80,9 +80,9 @@ OverrideBuildCmd=0
|
|||
BuildCmd=
|
||||
|
||||
[Unit6]
|
||||
FileName=..\..\include\loki\Singleton.h
|
||||
FileName=..\..\include\loki\SmallObj.h
|
||||
CompileCpp=1
|
||||
Folder=Loki_Headers
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
|
@ -90,39 +90,9 @@ OverrideBuildCmd=0
|
|||
BuildCmd=
|
||||
|
||||
[Unit7]
|
||||
FileName=..\..\include\loki\SmallObj.h
|
||||
CompileCpp=1
|
||||
Folder=Loki_Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit8]
|
||||
FileName=..\..\include\loki\SmartPtr.h
|
||||
CompileCpp=1
|
||||
Folder=Loki_Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit9]
|
||||
FileName=main.cpp
|
||||
CompileCpp=1
|
||||
Folder=Test
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit10]
|
||||
FileName=base.h
|
||||
CompileCpp=1
|
||||
Folder=Test
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
|
@ -147,3 +117,53 @@ ProductName=
|
|||
ProductVersion=
|
||||
AutoIncBuildNr=0
|
||||
|
||||
[Unit8]
|
||||
FileName=strong.cpp
|
||||
CompileCpp=1
|
||||
Folder=Tests
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit9]
|
||||
FileName=..\..\src\StrongPtr.cpp
|
||||
CompileCpp=1
|
||||
Folder=Sources
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit10]
|
||||
FileName=..\..\include\loki\StrongPtr.h
|
||||
CompileCpp=1
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit11]
|
||||
FileName=..\..\src\SmartPtr.cpp
|
||||
CompileCpp=1
|
||||
Folder=Sources
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit12]
|
||||
FileName=base.h
|
||||
CompileCpp=1
|
||||
Folder=Tests
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Version="8.00"
|
||||
Name="SmartPtr"
|
||||
ProjectGUID="{D7AB4FEF-E7AF-443D-93A5-37F323F2042D}"
|
||||
RootNamespace="SmartPtr"
|
||||
|
@ -150,6 +150,10 @@
|
|||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
|
@ -178,6 +182,18 @@
|
|||
RelativePath="..\..\include\loki\SmartPtr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\strong.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\StrongPtr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\loki\StrongPtr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\loki\Threads.h"
|
||||
>
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
// $Header$
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -38,6 +40,8 @@ public:
|
|||
return new BaseClass();
|
||||
}
|
||||
|
||||
void DoThat( void ) const {}
|
||||
|
||||
static inline bool AllDestroyed( void )
|
||||
{
|
||||
return ( s_constructions == s_destructions );
|
||||
|
@ -82,7 +86,7 @@ public:
|
|||
// This function is used only for the DeepCopy policy.
|
||||
virtual BaseClass * Clone( void ) const
|
||||
{
|
||||
return new BaseClass;
|
||||
return new PublicSubClass;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -94,13 +98,98 @@ public:
|
|||
// This function is used only for the DeepCopy policy.
|
||||
virtual BaseClass * Clone( void ) const
|
||||
{
|
||||
return new BaseClass;
|
||||
return new PrivateSubClass;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class MimicCOM Acts like a COM object by having an intrusive ref count.
|
||||
*/
|
||||
class MimicCOM
|
||||
{
|
||||
public:
|
||||
MimicCOM( void )
|
||||
: m_count( 0 )
|
||||
, m_AddRefCount( 0 )
|
||||
, m_ReleaseCount( 0 )
|
||||
{
|
||||
s_constructions++;
|
||||
}
|
||||
|
||||
virtual ~MimicCOM( void )
|
||||
{
|
||||
s_destructions++;
|
||||
}
|
||||
|
||||
void AddRef( void )
|
||||
{
|
||||
m_count++;
|
||||
m_AddRefCount++;
|
||||
}
|
||||
|
||||
void Release( void )
|
||||
{
|
||||
m_ReleaseCount++;
|
||||
assert( 0 < m_count );
|
||||
m_count--;
|
||||
if ( 0 == m_count )
|
||||
{
|
||||
/** @note I consider "delete this;" to be very unsafe! I'm only
|
||||
using it here for the purpose of testing.
|
||||
*/
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void DoThat( void ) {}
|
||||
|
||||
static inline bool AllDestroyed( void )
|
||||
{
|
||||
return ( s_constructions == s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraConstructions( void )
|
||||
{
|
||||
return ( s_constructions > s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraDestructions( void )
|
||||
{
|
||||
return ( s_constructions < s_destructions );
|
||||
}
|
||||
|
||||
static inline unsigned int GetCtorCount( void )
|
||||
{
|
||||
return s_constructions;
|
||||
}
|
||||
|
||||
static inline unsigned int GetDtorCount( void )
|
||||
{
|
||||
return s_destructions;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Not implemented.
|
||||
MimicCOM( const MimicCOM & );
|
||||
/// Not implemented.
|
||||
MimicCOM & operator = ( const MimicCOM & );
|
||||
|
||||
static unsigned int s_constructions;
|
||||
static unsigned int s_destructions;
|
||||
|
||||
unsigned int m_count;
|
||||
unsigned int m_AddRefCount;
|
||||
unsigned int m_ReleaseCount;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// $Log$
|
||||
// Revision 1.2 2006/04/05 22:53:12 rich_sposato
|
||||
// Added StrongPtr class to Loki along with tests for StrongPtr.
|
||||
//
|
||||
// Revision 1.1 2006/03/20 21:14:16 rich_sposato
|
||||
// Adding base.h to CVS.
|
||||
//
|
||||
|
|
|
@ -27,10 +27,31 @@ using namespace Loki;
|
|||
|
||||
extern void DoStrongRefCountTests( void );
|
||||
extern void DoStrongRefLinkTests( void );
|
||||
extern void DoStrongReleaseTests( void );
|
||||
extern void DoWeakCycleTests( void );
|
||||
extern void DoStrongConstTests( void );
|
||||
extern void DoStrongForwardReferenceTest( void );
|
||||
|
||||
unsigned int BaseClass::s_constructions = 0;
|
||||
unsigned int BaseClass::s_destructions = 0;
|
||||
|
||||
unsigned int MimicCOM::s_constructions = 0;
|
||||
unsigned int MimicCOM::s_destructions = 0;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Used to check if SmartPtr can be used with a forward-reference.
|
||||
class Thingy;
|
||||
|
||||
typedef Loki::SmartPtr< Thingy, RefCounted, DisallowConversion,
|
||||
AssertCheck, DefaultSPStorage, PropagateConst >
|
||||
Thingy_DefaultStorage_ptr;
|
||||
|
||||
typedef Loki::SmartPtr< Thingy, RefCounted, DisallowConversion,
|
||||
AssertCheck, HeapStorage, PropagateConst >
|
||||
Thingy_HeapStorage_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -53,6 +74,8 @@ typedef Loki::SmartPtr< BaseClass, RefCounted, DisallowConversion,
|
|||
NonConstBase_RefCount_NoConvert_Assert_Propagate_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// @note These 5 are used for testing ownership policies.
|
||||
typedef Loki::SmartPtr< BaseClass, COMRefCounted, DisallowConversion,
|
||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||
|
@ -74,6 +97,9 @@ typedef Loki::SmartPtr< BaseClass, NoCopy, DisallowConversion,
|
|||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||
NonConstBase_NoCopy_NoConvert_Assert_DontPropagate_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// @note These 2 are used for testing inheritance.
|
||||
typedef Loki::SmartPtr< PublicSubClass, RefCounted, DisallowConversion,
|
||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||
|
@ -84,6 +110,14 @@ typedef Loki::SmartPtr< PrivateSubClass, RefCounted, DisallowConversion,
|
|||
PrivateSub_RefCount_NoConvert_Assert_DontPropagate_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// @note Used for testing how well SmartPtr works with COM objects.
|
||||
typedef Loki::SmartPtr< MimicCOM, COMRefCounted, DisallowConversion,
|
||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||
MimicCOM_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoConstConversionTests( void )
|
||||
|
@ -303,6 +337,8 @@ void DoRefLinkSwapTests( void )
|
|||
BaseClass * pBaseClass = new BaseClass;
|
||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p1( pBaseClass );
|
||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p2( new BaseClass );
|
||||
p1->DoThat();
|
||||
p2->DoThat();
|
||||
|
||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p3( p1 );
|
||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p4( p2 );
|
||||
|
@ -785,6 +821,7 @@ void DoRefLinkTests( void )
|
|||
assert( w3 );
|
||||
assert( w4 );
|
||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||
w3->DoThat();
|
||||
}
|
||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
||||
|
@ -902,16 +939,80 @@ void DoRefLinkNullPointerTests( void )
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoComRefTest( void )
|
||||
{
|
||||
|
||||
const unsigned int ctorCount = MimicCOM::GetCtorCount();
|
||||
const unsigned int dtorCount = MimicCOM::GetDtorCount();
|
||||
assert( MimicCOM::AllDestroyed() );
|
||||
{
|
||||
MimicCOM_ptr p1;
|
||||
}
|
||||
assert( MimicCOM::AllDestroyed() );
|
||||
assert( ctorCount == MimicCOM::GetCtorCount() );
|
||||
assert( dtorCount == MimicCOM::GetDtorCount() );
|
||||
|
||||
{
|
||||
MimicCOM_ptr p1( new MimicCOM );
|
||||
}
|
||||
assert( ctorCount+1 == MimicCOM::GetCtorCount() );
|
||||
assert( dtorCount+1 == MimicCOM::GetDtorCount() );
|
||||
|
||||
{
|
||||
MimicCOM_ptr p2( new MimicCOM );
|
||||
MimicCOM_ptr p3( p2 );
|
||||
MimicCOM_ptr p4;
|
||||
p4 = p2;
|
||||
}
|
||||
assert( ctorCount+2 == MimicCOM::GetCtorCount() );
|
||||
assert( dtorCount+2 == MimicCOM::GetDtorCount() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoForwardReferenceTest( void )
|
||||
{
|
||||
/** @note These lines should cause the compiler to make a warning message
|
||||
about attempting to delete an undefined type. But it should not produce
|
||||
any error messages.
|
||||
*/
|
||||
Thingy_DefaultStorage_ptr p1;
|
||||
Thingy_DefaultStorage_ptr p2( p1 );
|
||||
Thingy_DefaultStorage_ptr p3;
|
||||
p3 = p2;
|
||||
|
||||
/** @note These lines should cause the compiler to make an error message
|
||||
about attempting to call the destructor for an undefined type.
|
||||
*/
|
||||
//Thingy_HeapStorage_ptr p4;
|
||||
//Thingy_HeapStorage_ptr p5( p4 );
|
||||
//Thingy_HeapStorage_ptr p6;
|
||||
//p6 = p5;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main( unsigned int , const char * [] )
|
||||
{
|
||||
|
||||
DoRefLinkTests();
|
||||
DoStrongRefCountTests();
|
||||
DoStrongRefLinkTests();
|
||||
DoStrongReleaseTests();
|
||||
DoWeakCycleTests();
|
||||
|
||||
DoForwardReferenceTest();
|
||||
DoStrongForwardReferenceTest();
|
||||
|
||||
DoRefCountNullPointerTests();
|
||||
DoRefLinkNullPointerTests();
|
||||
|
||||
DoRefCountSwapTests();
|
||||
DoRefLinkSwapTests();
|
||||
|
||||
DoComRefTest();
|
||||
|
||||
DoStrongConstTests();
|
||||
DoConstConversionTests();
|
||||
DoOwnershipConversionTests();
|
||||
DoInheritanceConversionTests();
|
||||
|
@ -930,6 +1031,9 @@ int main( unsigned int , const char * [] )
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
// $Log$
|
||||
// Revision 1.5 2006/04/05 22:53:12 rich_sposato
|
||||
// Added StrongPtr class to Loki along with tests for StrongPtr.
|
||||
//
|
||||
// Revision 1.4 2006/03/21 20:50:22 syntheticpp
|
||||
// fix include error
|
||||
//
|
||||
|
|
935
test/SmartPtr/strong.cpp
Normal file
935
test/SmartPtr/strong.cpp
Normal file
|
@ -0,0 +1,935 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Test program for The Loki Library
|
||||
// Copyright (c) 2006 Richard Sposato
|
||||
// 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 authors make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Header$
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <loki/StrongPtr.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace std;
|
||||
using namespace Loki;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Used to check if SmartPtr can be used with a forward-reference.
|
||||
class Thingy;
|
||||
|
||||
typedef Loki::StrongPtr< Thingy, true, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
Thingy_DeleteSingle_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< Thingy, true, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteUsingFree, DontPropagateConst >
|
||||
Thingy_DeleteUsingFree_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< Thingy, true, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteNothing, DontPropagateConst >
|
||||
Thingy_DeleteNothing_ptr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class Earth;
|
||||
class Moon;
|
||||
|
||||
typedef Loki::StrongPtr< Earth, false, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
Earth_WeakPtr;
|
||||
|
||||
typedef Loki::StrongPtr< Earth, true, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, AllowReset, DeleteSingle, DontPropagateConst >
|
||||
Earth_StrongPtr;
|
||||
|
||||
typedef Loki::StrongPtr< Moon, false, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
Moon_WeakPtr;
|
||||
|
||||
typedef Loki::StrongPtr< Moon, true, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, AllowReset, DeleteSingle, DontPropagateConst >
|
||||
Moon_StrongPtr;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class Earth
|
||||
{
|
||||
public:
|
||||
|
||||
Earth( void ) : m_moon()
|
||||
{
|
||||
s_constructions++;
|
||||
}
|
||||
|
||||
~Earth( void )
|
||||
{
|
||||
s_destructions++;
|
||||
}
|
||||
|
||||
void SetMoon( const Moon_StrongPtr & p );
|
||||
|
||||
void SetMoon( const Moon_WeakPtr & p );
|
||||
|
||||
static inline bool AllDestroyed( void )
|
||||
{
|
||||
return ( s_constructions == s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraConstructions( void )
|
||||
{
|
||||
return ( s_constructions > s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraDestructions( void )
|
||||
{
|
||||
return ( s_constructions < s_destructions );
|
||||
}
|
||||
|
||||
static inline unsigned int GetCtorCount( void )
|
||||
{
|
||||
return s_constructions;
|
||||
}
|
||||
|
||||
static inline unsigned int GetDtorCount( void )
|
||||
{
|
||||
return s_destructions;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Not implemented.
|
||||
Earth( const Earth & );
|
||||
/// Not implemented.
|
||||
Earth & operator = ( const Earth & );
|
||||
|
||||
static unsigned int s_constructions;
|
||||
static unsigned int s_destructions;
|
||||
|
||||
Moon_WeakPtr m_moon;
|
||||
};
|
||||
|
||||
unsigned int Earth::s_constructions = 0;
|
||||
unsigned int Earth::s_destructions = 0;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class Moon
|
||||
{
|
||||
public:
|
||||
|
||||
Moon( void ) : m_earth()
|
||||
{
|
||||
s_constructions++;
|
||||
}
|
||||
|
||||
~Moon( void )
|
||||
{
|
||||
s_destructions++;
|
||||
}
|
||||
|
||||
void SetEarth( const Earth_WeakPtr & p );
|
||||
|
||||
void SetEarth( const Earth_StrongPtr & p );
|
||||
|
||||
static inline bool AllDestroyed( void )
|
||||
{
|
||||
return ( s_constructions == s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraConstructions( void )
|
||||
{
|
||||
return ( s_constructions > s_destructions );
|
||||
}
|
||||
|
||||
static inline bool ExtraDestructions( void )
|
||||
{
|
||||
return ( s_constructions < s_destructions );
|
||||
}
|
||||
|
||||
static inline unsigned int GetCtorCount( void )
|
||||
{
|
||||
return s_constructions;
|
||||
}
|
||||
|
||||
static inline unsigned int GetDtorCount( void )
|
||||
{
|
||||
return s_destructions;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Not implemented.
|
||||
Moon( const Moon & );
|
||||
/// Not implemented.
|
||||
Moon & operator = ( const Moon & );
|
||||
|
||||
static unsigned int s_constructions;
|
||||
static unsigned int s_destructions;
|
||||
Earth_WeakPtr m_earth;
|
||||
};
|
||||
|
||||
unsigned int Moon::s_constructions = 0;
|
||||
unsigned int Moon::s_destructions = 0;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Moon::SetEarth( const Earth_WeakPtr & p )
|
||||
{
|
||||
m_earth = p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Moon::SetEarth( const Earth_StrongPtr & p )
|
||||
{
|
||||
m_earth = p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Earth::SetMoon( const Moon_WeakPtr & p )
|
||||
{
|
||||
m_moon = p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Earth::SetMoon( const Moon_StrongPtr & p )
|
||||
{
|
||||
m_moon = p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, false, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, true, TwoRefCounts, DisallowConversion,
|
||||
NoCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, false, TwoRefLinks, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_WeakLink_NoConvert_Assert_NoPropagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, true, TwoRefLinks, DisallowConversion,
|
||||
NoCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_StrongLink_NoConvert_NoCheck_NoPropagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, false, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, AllowReset, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_WeakCount_NoConvert_Assert_Reset_NoPropagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< BaseClass, true, TwoRefCounts, DisallowConversion,
|
||||
NoCheck, AllowReset, DeleteSingle, DontPropagateConst >
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_Reset_NoPropagate_ptr;
|
||||
|
||||
/// @note Used for const propagation tests.
|
||||
typedef Loki::StrongPtr< const BaseClass, true, TwoRefCounts, DisallowConversion,
|
||||
NoCheck, CantResetWithStrong, DeleteSingle, PropagateConst >
|
||||
ConstBase_StrongCount_NoConvert_NoCheck_Propagate_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< const BaseClass, false, TwoRefCounts, DisallowConversion,
|
||||
AssertCheck, CantResetWithStrong, DeleteSingle, PropagateConst >
|
||||
ConstBase_WeakCount_NoConvert_Assert_Propagate_ptr;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoStrongRefCountTests( void )
|
||||
{
|
||||
|
||||
BaseClass * pNull = NULL;
|
||||
const unsigned int ctorCount = BaseClass::GetCtorCount();
|
||||
const unsigned int dtorCount = BaseClass::GetDtorCount();
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w0;
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s0;
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( w0 );
|
||||
|
||||
// Copy from weak to strong is available.
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( w0 );
|
||||
// Assignment from weak to strong is available.
|
||||
s1 = w1;
|
||||
|
||||
// Converting from strong to weak is available.
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( s0 );
|
||||
// Assignment from strong to weak is available.
|
||||
w1 = s1;
|
||||
|
||||
assert( !s0 );
|
||||
assert( !s1 );
|
||||
assert( !w0 );
|
||||
assert( !w1 );
|
||||
assert( s1 == pNull );
|
||||
assert( s0 == pNull );
|
||||
assert( w1 == pNull );
|
||||
assert( w1 == pNull );
|
||||
assert( pNull == s0 );
|
||||
assert( pNull == s1 );
|
||||
assert( pNull == w0 );
|
||||
assert( pNull == w1 );
|
||||
assert( s0 == s0 );
|
||||
assert( s1 == s1 );
|
||||
assert( w0 == w0 );
|
||||
assert( w1 == w1 );
|
||||
assert( s1 == s0 );
|
||||
assert( s0 == s1 );
|
||||
assert( w0 == s0 );
|
||||
assert( s0 == w0 );
|
||||
assert( w0 == w1 );
|
||||
assert( w1 == w0 );
|
||||
assert( w0 == w1 );
|
||||
assert( w1 == s1 );
|
||||
assert( s1 == w1 );
|
||||
assert( s1 <= s0 );
|
||||
assert( s1 >= s0 );
|
||||
assert( s0 <= s1 );
|
||||
assert( s0 >= s1 );
|
||||
assert( w0 <= s0 );
|
||||
assert( w0 >= s0 );
|
||||
assert( s0 <= w0 );
|
||||
assert( s0 >= w0 );
|
||||
assert( w1 <= w0 );
|
||||
assert( w1 >= w0 );
|
||||
assert( w0 <= w1 );
|
||||
assert( w0 >= w1 );
|
||||
assert( !( s1 < s0 ) );
|
||||
assert( !( s1 > s0 ) );
|
||||
assert( !( s0 < s1 ) );
|
||||
assert( !( s0 > s1 ) );
|
||||
assert( !( w0 < s0 ) );
|
||||
assert( !( w0 > s0 ) );
|
||||
assert( !( s0 < w0 ) );
|
||||
assert( !( s0 > w0 ) );
|
||||
assert( !( w1 < w0 ) );
|
||||
assert( !( w1 > w0 ) );
|
||||
assert( !( w0 < w1 ) );
|
||||
assert( !( w0 > w1 ) );
|
||||
assert( !( w0 < pNull ) );
|
||||
assert( !( w0 > pNull ) );
|
||||
assert( !( pNull < w0 ) );
|
||||
assert( !( pNull > w0 ) );
|
||||
}
|
||||
assert( ctorCount == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( new BaseClass );
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( new BaseClass );
|
||||
assert( w1 != w2 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
w1 = w2;
|
||||
assert( w1 == w2 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( new BaseClass );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s2( new BaseClass );
|
||||
assert( s1 != s2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
s1 = s2;
|
||||
assert( s1 == s2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
assert( dtorCount + 3 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
assert( ctorCount + 4 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 4 == BaseClass::GetDtorCount() );
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( new BaseClass );
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( new BaseClass );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( w1 );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s2( w2 );
|
||||
|
||||
// prove basic stuff.
|
||||
assert( w1 != w2 );
|
||||
assert( s1 != s2 );
|
||||
assert( s1 == w1 );
|
||||
assert( s2 == w2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
|
||||
// prove a weak pointer can be re-assigned to another without affecting
|
||||
// any strong co-pointers. and that no objects were released.
|
||||
w1 = w2; // w1 == w2 == s2 s1
|
||||
assert( w1 == w2 );
|
||||
assert( s1 != s2 );
|
||||
assert( s1 != w1 );
|
||||
assert( s1 != w2 );
|
||||
assert( s2 == w1 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
assert( dtorCount + 4 == BaseClass::GetDtorCount() );
|
||||
|
||||
// Prove they all point to same thing.
|
||||
s1 = s2; // w1 == w2 == s2 == s1
|
||||
// and prove that one of them released the object.
|
||||
assert( dtorCount + 5 == BaseClass::GetDtorCount() );
|
||||
assert( w1 == w2 );
|
||||
assert( s1 == s2 );
|
||||
assert( s1 == w1 );
|
||||
assert( s1 == w2 );
|
||||
assert( s2 == w1 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
}
|
||||
assert( ctorCount + 6 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 6 == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( new BaseClass );
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( new BaseClass );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( w1 );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s2( w2 );
|
||||
|
||||
// prove basic stuff. w1 == s1 w2 == s2
|
||||
assert( w1 != w2 );
|
||||
assert( s1 != s2 );
|
||||
assert( s1 == w1 );
|
||||
assert( s2 == w2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
assert( w1 );
|
||||
assert( w2 );
|
||||
|
||||
// prove a strong pointer can be re-assigned to another weak pointer,
|
||||
// and that any weak co-pointers released the object.
|
||||
s1 = w2; // s1 == w2 == s2 w1
|
||||
assert( w1 != w2 );
|
||||
assert( s1 == s2 );
|
||||
assert( s1 != w1 );
|
||||
assert( s1 == w2 );
|
||||
assert( s2 != w1 );
|
||||
assert( !w1 );
|
||||
assert( w2 );
|
||||
assert( s1 );
|
||||
assert( s2 );
|
||||
assert( dtorCount + 7 == BaseClass::GetDtorCount() );
|
||||
|
||||
// Prove that when strong pointer is re-assigned, object
|
||||
// is not destroyed if another strong co-pointer exists.
|
||||
s1 = w1; // w1 == s1 w2 == s2
|
||||
// and prove that none of them released an object.
|
||||
assert( dtorCount + 7 == BaseClass::GetDtorCount() );
|
||||
assert( w1 != w2 );
|
||||
assert( s1 != s2 );
|
||||
assert( s1 == w1 );
|
||||
assert( s2 == w2 );
|
||||
assert( !s1 );
|
||||
assert( s2 );
|
||||
assert( !w1 );
|
||||
assert( w2 );
|
||||
}
|
||||
assert( ctorCount + 8 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 8 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoStrongConstTests( void )
|
||||
{
|
||||
|
||||
const unsigned int ctorCount = BaseClass::GetCtorCount();
|
||||
const unsigned int dtorCount = BaseClass::GetDtorCount();
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( new BaseClass );
|
||||
const NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( w1 );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( w1 );
|
||||
const NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s2( w2 );
|
||||
|
||||
const BaseClass & cbw1 = *w1;
|
||||
cbw1.DoThat();
|
||||
const BaseClass & cbw2 = *w2;
|
||||
cbw2.DoThat();
|
||||
const BaseClass & cbs1 = *s1;
|
||||
cbs1.DoThat();
|
||||
const BaseClass & cbs2 = *s2;
|
||||
cbs2.DoThat();
|
||||
|
||||
BaseClass & bw1 = *w1;
|
||||
bw1.DoThat();
|
||||
BaseClass & bw2 = *w2;
|
||||
bw2.DoThat();
|
||||
BaseClass & bs1 = *s1;
|
||||
bs1.DoThat();
|
||||
BaseClass & bs2 = *s2;
|
||||
bs2.DoThat();
|
||||
}
|
||||
assert( ctorCount + 1 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
ConstBase_WeakCount_NoConvert_Assert_Propagate_ptr w1( new BaseClass );
|
||||
const ConstBase_WeakCount_NoConvert_Assert_Propagate_ptr w2( w1 );
|
||||
ConstBase_StrongCount_NoConvert_NoCheck_Propagate_ptr s1( w1 );
|
||||
const ConstBase_StrongCount_NoConvert_NoCheck_Propagate_ptr s2( w2 );
|
||||
|
||||
const BaseClass & cbw1 = *w1;
|
||||
cbw1.DoThat();
|
||||
const BaseClass & cbw2 = *w2;
|
||||
cbw2.DoThat();
|
||||
const BaseClass & cbs1 = *s1;
|
||||
cbs1.DoThat();
|
||||
const BaseClass & cbs2 = *s2;
|
||||
cbs2.DoThat();
|
||||
|
||||
/** @note These are illegal because constness is propagated by the
|
||||
StrongPtr's policy. Your compiler should produce error messages if
|
||||
you attempt to compile these lines.
|
||||
*/
|
||||
//BaseClass & bw1 = *w1;
|
||||
//bw1.DoThat();
|
||||
//BaseClass & bw2 = *w2;
|
||||
//bw2.DoThat();
|
||||
//BaseClass & bs1 = *s1;
|
||||
//bs1.DoThat();
|
||||
//BaseClass & bs2 = *s2;
|
||||
//bs2.DoThat();
|
||||
}
|
||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoStrongReleaseTests( void )
|
||||
{
|
||||
|
||||
BaseClass * pNull = NULL;
|
||||
const unsigned int ctorCount = BaseClass::GetCtorCount();
|
||||
const unsigned int dtorCount = BaseClass::GetDtorCount();
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
// These are tests of pointers that don't allow reset or release if
|
||||
// there is at least 1 strong pointer. Ironically, this means that
|
||||
// if only 1 strong pointer holds onto an object, and you call Release
|
||||
// using that strong pointer, it can't release itself.
|
||||
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w1( new BaseClass );
|
||||
NonConstBase_WeakCount_NoConvert_Assert_NoPropagate_ptr w2( new BaseClass );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s1( w1 );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_NoPropagate_ptr s2( w2 );
|
||||
|
||||
// Prove that neither weak nor strong pointers can be
|
||||
// released if any co-pointer is strong.
|
||||
bool released = ReleaseAll( w2, pNull );
|
||||
assert( !released );
|
||||
|
||||
released = ReleaseAll( w1, pNull );
|
||||
assert( !released );
|
||||
|
||||
released = ReleaseAll( s1, pNull );
|
||||
assert( !released );
|
||||
|
||||
released = ReleaseAll( s2, pNull );
|
||||
assert( !released );
|
||||
|
||||
// Prove that weak and strong pointers can be reset only
|
||||
// if stored pointer matches parameter pointer - or there
|
||||
// are no strong co-pointers.
|
||||
bool reset = ResetAll( w2, pNull );
|
||||
assert( !reset );
|
||||
|
||||
reset = ResetAll( w1, pNull );
|
||||
assert( !reset );
|
||||
|
||||
reset = ResetAll( s1, pNull );
|
||||
assert( !reset );
|
||||
|
||||
reset = ResetAll( s2, pNull );
|
||||
assert( !reset );
|
||||
|
||||
s2 = pNull;
|
||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||
reset = ResetAll( w2, pNull );
|
||||
assert( reset );
|
||||
|
||||
reset = ResetAll( w1, pNull );
|
||||
assert( !reset );
|
||||
|
||||
reset = ResetAll( s1, pNull );
|
||||
assert( !reset );
|
||||
|
||||
reset = ResetAll( s2, pNull );
|
||||
assert( reset );
|
||||
}
|
||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
// These are tests of pointers that do allow reset and release even
|
||||
// if a strong pointer exists.
|
||||
|
||||
NonConstBase_WeakCount_NoConvert_Assert_Reset_NoPropagate_ptr w1( new BaseClass );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_Reset_NoPropagate_ptr w2( new BaseClass );
|
||||
NonConstBase_WeakCount_NoConvert_Assert_Reset_NoPropagate_ptr s1( w1 );
|
||||
NonConstBase_StrongCount_NoConvert_NoCheck_Reset_NoPropagate_ptr s2( w2 );
|
||||
|
||||
BaseClass * thing = NULL;
|
||||
bool released = ReleaseAll( w2, thing );
|
||||
assert( released );
|
||||
assert( NULL != thing );
|
||||
delete thing;
|
||||
assert( dtorCount + 3 == BaseClass::GetDtorCount() );
|
||||
|
||||
released = ReleaseAll( s1, thing );
|
||||
assert( released );
|
||||
assert( NULL != thing );
|
||||
delete thing;
|
||||
assert( dtorCount + 4 == BaseClass::GetDtorCount() );
|
||||
|
||||
released = ReleaseAll( w1, thing );
|
||||
assert( released );
|
||||
assert( NULL == thing );
|
||||
|
||||
released = ReleaseAll( s2, thing );
|
||||
assert( released );
|
||||
assert( NULL == thing );
|
||||
|
||||
// Prove that weak and strong pointers can be reset
|
||||
// only if stored pointer matches parameter pointer
|
||||
// - even if there are strong co-pointers.
|
||||
bool reset = ResetAll( w2, pNull );
|
||||
assert( reset );
|
||||
|
||||
reset = ResetAll( w1, pNull );
|
||||
assert( reset );
|
||||
|
||||
reset = ResetAll( s1, pNull );
|
||||
assert( reset );
|
||||
|
||||
reset = ResetAll( s2, pNull );
|
||||
assert( reset );
|
||||
assert( ctorCount + 4 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 4 == BaseClass::GetDtorCount() );
|
||||
|
||||
s2 = new BaseClass;
|
||||
s1 = new BaseClass;
|
||||
reset = ResetAll( w2, pNull );
|
||||
assert( reset );
|
||||
|
||||
reset = ResetAll( w1, pNull );
|
||||
assert( reset );
|
||||
}
|
||||
assert( ctorCount + 6 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 6 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoStrongRefLinkTests( void )
|
||||
{
|
||||
|
||||
BaseClass * pNull = NULL;
|
||||
const unsigned int ctorCount = BaseClass::GetCtorCount();
|
||||
const unsigned int dtorCount = BaseClass::GetDtorCount();
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakLink_NoConvert_Assert_NoPropagate_ptr w0;
|
||||
NonConstBase_WeakLink_NoConvert_Assert_NoPropagate_ptr w1;
|
||||
NonConstBase_StrongLink_NoConvert_NoCheck_NoPropagate_ptr s0;
|
||||
NonConstBase_StrongLink_NoConvert_NoCheck_NoPropagate_ptr s1;
|
||||
assert( !s0 );
|
||||
assert( !s1 );
|
||||
assert( s0 == s1 );
|
||||
assert( s1 == pNull );
|
||||
assert( s0 == pNull );
|
||||
assert( pNull == s0 );
|
||||
assert( pNull == s1 );
|
||||
assert( s1 == s0 );
|
||||
assert( s1 == s1 );
|
||||
assert( s0 == s0 );
|
||||
assert( s0 == s1 );
|
||||
assert( s1 <= s0 );
|
||||
assert( s1 >= s0 );
|
||||
assert( s0 <= s1 );
|
||||
assert( s0 >= s1 );
|
||||
assert( !( s1 < s0 ) );
|
||||
assert( !( s1 > s0 ) );
|
||||
assert( !( s0 < s1 ) );
|
||||
assert( !( s0 > s1 ) );
|
||||
assert( !w0 );
|
||||
assert( !w1 );
|
||||
assert( w0 == pNull );
|
||||
assert( s0 == pNull );
|
||||
assert( pNull == s0 );
|
||||
assert( pNull == w0 );
|
||||
assert( w0 == s0 );
|
||||
assert( w0 == w0 );
|
||||
assert( s0 == s0 );
|
||||
assert( s0 == w0 );
|
||||
assert( w0 <= s0 );
|
||||
assert( w0 >= s0 );
|
||||
assert( s0 <= w0 );
|
||||
assert( s0 >= w0 );
|
||||
assert( !( w0 < s0 ) );
|
||||
assert( !( w0 > s0 ) );
|
||||
assert( !( s0 < w0 ) );
|
||||
assert( !( s0 > w0 ) );
|
||||
assert( w0 == w1 );
|
||||
assert( w1 == pNull );
|
||||
assert( w0 == pNull );
|
||||
assert( pNull == w0 );
|
||||
assert( pNull == w1 );
|
||||
assert( w1 == w0 );
|
||||
assert( w1 == w1 );
|
||||
assert( w0 == w0 );
|
||||
assert( w0 == w1 );
|
||||
assert( w1 <= w0 );
|
||||
assert( w1 >= w0 );
|
||||
assert( w0 <= w1 );
|
||||
assert( w0 >= w1 );
|
||||
assert( !( w1 < w0 ) );
|
||||
assert( !( w1 > w0 ) );
|
||||
assert( !( w0 < w1 ) );
|
||||
assert( !( w0 > w1 ) );
|
||||
}
|
||||
assert( ctorCount == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_WeakLink_NoConvert_Assert_NoPropagate_ptr w3( new BaseClass );
|
||||
NonConstBase_WeakLink_NoConvert_Assert_NoPropagate_ptr w4( new BaseClass );
|
||||
assert( w3 != w4 );
|
||||
assert( w3 );
|
||||
assert( w4 );
|
||||
w3 = w4;
|
||||
assert( w3 == w4 );
|
||||
assert( w3 );
|
||||
assert( w4 );
|
||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
||||
|
||||
{
|
||||
NonConstBase_StrongLink_NoConvert_NoCheck_NoPropagate_ptr s3( new BaseClass );
|
||||
NonConstBase_StrongLink_NoConvert_NoCheck_NoPropagate_ptr s4( new BaseClass );
|
||||
assert( s3 != s4 );
|
||||
assert( s3 );
|
||||
assert( s4 );
|
||||
s3 = s4;
|
||||
assert( s3 == s4 );
|
||||
assert( s3 );
|
||||
assert( s4 );
|
||||
assert( dtorCount + 3 == BaseClass::GetDtorCount() );
|
||||
}
|
||||
assert( ctorCount + 4 == BaseClass::GetCtorCount() );
|
||||
assert( dtorCount + 4 == BaseClass::GetDtorCount() );
|
||||
assert( BaseClass::GetCtorCount() == BaseClass::GetDtorCount() );
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoWeakCycleTests( void )
|
||||
{
|
||||
|
||||
const unsigned int ctorCountMoon = Moon::GetCtorCount();
|
||||
const unsigned int dtorCountMoon = Moon::GetDtorCount();
|
||||
assert( Moon::AllDestroyed() );
|
||||
const unsigned int ctorCountEarth = Earth::GetCtorCount();
|
||||
const unsigned int dtorCountEarth = Earth::GetDtorCount();
|
||||
assert( Earth::AllDestroyed() );
|
||||
|
||||
{
|
||||
Earth_WeakPtr ew0;
|
||||
Moon_WeakPtr mw0;
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth );
|
||||
|
||||
{
|
||||
Earth_WeakPtr ew1( new Earth );
|
||||
}
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+1 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+1 );
|
||||
|
||||
{
|
||||
Moon_WeakPtr mw1( new Moon );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+1 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+1 );
|
||||
|
||||
{
|
||||
Earth_WeakPtr ew1( new Earth );
|
||||
Moon_WeakPtr mw1( new Moon );
|
||||
ew1->SetMoon( mw1 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+2 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+2 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+2 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+2 );
|
||||
|
||||
{
|
||||
Earth_WeakPtr ew1( new Earth );
|
||||
Moon_WeakPtr mw1( new Moon );
|
||||
mw1->SetEarth( ew1 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+3 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+3 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+3 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+3 );
|
||||
|
||||
{
|
||||
Earth_WeakPtr ew1( new Earth );
|
||||
Moon_WeakPtr mw1( new Moon );
|
||||
ew1->SetMoon( mw1 );
|
||||
mw1->SetEarth( ew1 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+4 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+4 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+4 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+4 );
|
||||
|
||||
{
|
||||
Earth_StrongPtr es1( new Earth );
|
||||
Moon_StrongPtr ms1( new Moon );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+5 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+5 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+5 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+5 );
|
||||
|
||||
{
|
||||
Earth_StrongPtr es1( new Earth );
|
||||
Moon_StrongPtr ms1( new Moon );
|
||||
es1->SetMoon( ms1 );
|
||||
ms1->SetEarth( es1 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+6 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+6 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+6 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+6 );
|
||||
|
||||
{
|
||||
Earth_StrongPtr es1( new Earth );
|
||||
Moon_StrongPtr ms1( new Moon );
|
||||
{
|
||||
Earth_WeakPtr ew1( es1 );
|
||||
Moon_WeakPtr mw1( ms1 );
|
||||
ew1->SetMoon( mw1 );
|
||||
mw1->SetEarth( ew1 );
|
||||
}
|
||||
// Note that dtor counts have not changed from previous test.
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+7 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+6 );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+7 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+6 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+7 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+7 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+7 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+7 );
|
||||
|
||||
{
|
||||
Earth_StrongPtr es1;
|
||||
Moon_StrongPtr ms1;
|
||||
{
|
||||
Earth_WeakPtr ew1( new Earth );
|
||||
Moon_WeakPtr mw1( new Moon );
|
||||
ew1->SetMoon( mw1 );
|
||||
mw1->SetEarth( ew1 );
|
||||
es1 = ew1;
|
||||
ms1 = mw1;
|
||||
}
|
||||
// Note that dtor counts have not changed from previous test.
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+8 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+7 );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+8 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+7 );
|
||||
}
|
||||
assert( Moon::AllDestroyed() );
|
||||
assert( Moon::GetCtorCount() == ctorCountMoon+8 );
|
||||
assert( Moon::GetDtorCount() == dtorCountMoon+8 );
|
||||
assert( Earth::AllDestroyed() );
|
||||
assert( Earth::GetCtorCount() == ctorCountEarth+8 );
|
||||
assert( Earth::GetDtorCount() == dtorCountEarth+8 );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoStrongForwardReferenceTest( void )
|
||||
{
|
||||
/** @note These lines should cause the compiler to make a warning message
|
||||
about attempting to delete an undefined type. But it should not produce
|
||||
any error messages.
|
||||
*/
|
||||
Thingy_DeleteSingle_ptr p1;
|
||||
Thingy_DeleteSingle_ptr p2( p1 );
|
||||
Thingy_DeleteSingle_ptr p3;
|
||||
p3 = p1;
|
||||
|
||||
/** @note These lines should cause the compiler to make an error message
|
||||
about attempting to call the destructor for an undefined type.
|
||||
*/
|
||||
//Thingy_DeleteUsingFree_ptr p4;
|
||||
//Thingy_DeleteUsingFree_ptr p5( p4 );
|
||||
//Thingy_DeleteUsingFree_ptr p6;
|
||||
//p6 = p4;
|
||||
|
||||
/** @note These lines should cause the compiler to make neither a warning
|
||||
nor an error message even though the type is undefined.
|
||||
*/
|
||||
Thingy_DeleteNothing_ptr p7;
|
||||
Thingy_DeleteNothing_ptr p8( p7 );
|
||||
Thingy_DeleteNothing_ptr p9;
|
||||
p9 = p7;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
Loading…
Reference in a new issue