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]
|
[Project]
|
||||||
FileName=SmartPtr.dev
|
FileName=SmartPtr.dev
|
||||||
Name=SmartPtr
|
Name=SmartPtr
|
||||||
UnitCount=10
|
UnitCount=12
|
||||||
Type=1
|
Type=1
|
||||||
Ver=1
|
Ver=1
|
||||||
ObjFiles=
|
ObjFiles=
|
||||||
Includes=C:\Projects\loki\include
|
Includes=C:\DevCpp\include;C:\Projects\loki\include
|
||||||
Libs=
|
Libs=
|
||||||
PrivateResource=
|
PrivateResource=
|
||||||
ResourceIncludes=
|
ResourceIncludes=
|
||||||
|
@ -20,49 +20,49 @@ ObjectOutput=
|
||||||
OverrideOutput=0
|
OverrideOutput=0
|
||||||
OverrideOutputName=SmartPtr.exe
|
OverrideOutputName=SmartPtr.exe
|
||||||
HostApplication=
|
HostApplication=
|
||||||
Folders=Loki_Headers,Loki_Sources,Test
|
Folders=Headers,Sources,Tests
|
||||||
CommandLine=
|
CommandLine=
|
||||||
UseCustomMakefile=0
|
UseCustomMakefile=0
|
||||||
CustomMakefile=
|
CustomMakefile=
|
||||||
IncludeVersionInfo=0
|
IncludeVersionInfo=0
|
||||||
SupportXPThemes=0
|
SupportXPThemes=0
|
||||||
CompilerSet=0
|
CompilerSet=0
|
||||||
CompilerSettings=1000001001001001000000
|
CompilerSettings=0000001001001001000000
|
||||||
|
|
||||||
[Unit1]
|
[Unit1]
|
||||||
FileName=..\..\src\Singleton.cpp
|
FileName=main.cpp
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Sources
|
Folder=Tests
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=1
|
Priority=1000
|
||||||
OverrideBuildCmd=0
|
OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit2]
|
[Unit2]
|
||||||
FileName=..\..\src\SmallObj.cpp
|
FileName=..\..\src\Singleton.cpp
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Sources
|
Folder=Sources
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=2
|
Priority=1000
|
||||||
OverrideBuildCmd=0
|
OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit3]
|
[Unit3]
|
||||||
FileName=..\..\src\SmartPtr.cpp
|
FileName=..\..\src\SmallObj.cpp
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Sources
|
Folder=Sources
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=3
|
Priority=1000
|
||||||
OverrideBuildCmd=0
|
OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit4]
|
[Unit4]
|
||||||
FileName=..\..\include\loki\Threads.h
|
FileName=..\..\include\loki\Threads.h
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Headers
|
Folder=Headers
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=1000
|
Priority=1000
|
||||||
|
@ -70,9 +70,9 @@ OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit5]
|
[Unit5]
|
||||||
FileName=..\..\include\loki\ConstPolicy.h
|
FileName=..\..\include\loki\Singleton.h
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Headers
|
Folder=Headers
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=1000
|
Priority=1000
|
||||||
|
@ -80,9 +80,9 @@ OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit6]
|
[Unit6]
|
||||||
FileName=..\..\include\loki\Singleton.h
|
FileName=..\..\include\loki\SmallObj.h
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Headers
|
Folder=Headers
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=1000
|
Priority=1000
|
||||||
|
@ -90,39 +90,9 @@ OverrideBuildCmd=0
|
||||||
BuildCmd=
|
BuildCmd=
|
||||||
|
|
||||||
[Unit7]
|
[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
|
FileName=..\..\include\loki\SmartPtr.h
|
||||||
CompileCpp=1
|
CompileCpp=1
|
||||||
Folder=Loki_Headers
|
Folder=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
|
|
||||||
Compile=1
|
Compile=1
|
||||||
Link=1
|
Link=1
|
||||||
Priority=1000
|
Priority=1000
|
||||||
|
@ -147,3 +117,53 @@ ProductName=
|
||||||
ProductVersion=
|
ProductVersion=
|
||||||
AutoIncBuildNr=0
|
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"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="SmartPtr"
|
Name="SmartPtr"
|
||||||
ProjectGUID="{D7AB4FEF-E7AF-443D-93A5-37F323F2042D}"
|
ProjectGUID="{D7AB4FEF-E7AF-443D-93A5-37F323F2042D}"
|
||||||
RootNamespace="SmartPtr"
|
RootNamespace="SmartPtr"
|
||||||
|
@ -150,6 +150,10 @@
|
||||||
<References>
|
<References>
|
||||||
</References>
|
</References>
|
||||||
<Files>
|
<Files>
|
||||||
|
<File
|
||||||
|
RelativePath=".\base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\main.cpp"
|
RelativePath=".\main.cpp"
|
||||||
>
|
>
|
||||||
|
@ -178,6 +182,18 @@
|
||||||
RelativePath="..\..\include\loki\SmartPtr.h"
|
RelativePath="..\..\include\loki\SmartPtr.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\strong.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\StrongPtr.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\loki\StrongPtr.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\loki\Threads.h"
|
RelativePath="..\..\include\loki\Threads.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
// $Header$
|
// $Header$
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -38,6 +40,8 @@ public:
|
||||||
return new BaseClass();
|
return new BaseClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoThat( void ) const {}
|
||||||
|
|
||||||
static inline bool AllDestroyed( void )
|
static inline bool AllDestroyed( void )
|
||||||
{
|
{
|
||||||
return ( s_constructions == s_destructions );
|
return ( s_constructions == s_destructions );
|
||||||
|
@ -82,7 +86,7 @@ public:
|
||||||
// This function is used only for the DeepCopy policy.
|
// This function is used only for the DeepCopy policy.
|
||||||
virtual BaseClass * Clone( void ) const
|
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.
|
// This function is used only for the DeepCopy policy.
|
||||||
virtual BaseClass * Clone( void ) const
|
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$
|
// $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
|
// Revision 1.1 2006/03/20 21:14:16 rich_sposato
|
||||||
// Adding base.h to CVS.
|
// Adding base.h to CVS.
|
||||||
//
|
//
|
||||||
|
|
|
@ -27,10 +27,31 @@ using namespace Loki;
|
||||||
|
|
||||||
extern void DoStrongRefCountTests( void );
|
extern void DoStrongRefCountTests( void );
|
||||||
extern void DoStrongRefLinkTests( 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_constructions = 0;
|
||||||
unsigned int BaseClass::s_destructions = 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;
|
NonConstBase_RefCount_NoConvert_Assert_Propagate_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// @note These 5 are used for testing ownership policies.
|
/// @note These 5 are used for testing ownership policies.
|
||||||
typedef Loki::SmartPtr< BaseClass, COMRefCounted, DisallowConversion,
|
typedef Loki::SmartPtr< BaseClass, COMRefCounted, DisallowConversion,
|
||||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||||
|
@ -74,6 +97,9 @@ typedef Loki::SmartPtr< BaseClass, NoCopy, DisallowConversion,
|
||||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||||
NonConstBase_NoCopy_NoConvert_Assert_DontPropagate_ptr;
|
NonConstBase_NoCopy_NoConvert_Assert_DontPropagate_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// @note These 2 are used for testing inheritance.
|
/// @note These 2 are used for testing inheritance.
|
||||||
typedef Loki::SmartPtr< PublicSubClass, RefCounted, DisallowConversion,
|
typedef Loki::SmartPtr< PublicSubClass, RefCounted, DisallowConversion,
|
||||||
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
AssertCheck, DefaultSPStorage, DontPropagateConst >
|
||||||
|
@ -84,6 +110,14 @@ typedef Loki::SmartPtr< PrivateSubClass, RefCounted, DisallowConversion,
|
||||||
PrivateSub_RefCount_NoConvert_Assert_DontPropagate_ptr;
|
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 )
|
void DoConstConversionTests( void )
|
||||||
|
@ -303,6 +337,8 @@ void DoRefLinkSwapTests( void )
|
||||||
BaseClass * pBaseClass = new BaseClass;
|
BaseClass * pBaseClass = new BaseClass;
|
||||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p1( pBaseClass );
|
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p1( pBaseClass );
|
||||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p2( new BaseClass );
|
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 p3( p1 );
|
||||||
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p4( p2 );
|
NonConstBase_RefLink_NoConvert_Assert_DontPropagate_ptr p4( p2 );
|
||||||
|
@ -785,6 +821,7 @@ void DoRefLinkTests( void )
|
||||||
assert( w3 );
|
assert( w3 );
|
||||||
assert( w4 );
|
assert( w4 );
|
||||||
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
assert( dtorCount + 1 == BaseClass::GetDtorCount() );
|
||||||
|
w3->DoThat();
|
||||||
}
|
}
|
||||||
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
assert( ctorCount + 2 == BaseClass::GetCtorCount() );
|
||||||
assert( dtorCount + 2 == BaseClass::GetDtorCount() );
|
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 * [] )
|
int main( unsigned int , const char * [] )
|
||||||
{
|
{
|
||||||
|
|
||||||
DoRefLinkTests();
|
DoRefLinkTests();
|
||||||
|
DoStrongRefCountTests();
|
||||||
|
DoStrongRefLinkTests();
|
||||||
|
DoStrongReleaseTests();
|
||||||
|
DoWeakCycleTests();
|
||||||
|
|
||||||
|
DoForwardReferenceTest();
|
||||||
|
DoStrongForwardReferenceTest();
|
||||||
|
|
||||||
DoRefCountNullPointerTests();
|
DoRefCountNullPointerTests();
|
||||||
DoRefLinkNullPointerTests();
|
DoRefLinkNullPointerTests();
|
||||||
|
|
||||||
DoRefCountSwapTests();
|
DoRefCountSwapTests();
|
||||||
DoRefLinkSwapTests();
|
DoRefLinkSwapTests();
|
||||||
|
|
||||||
|
DoComRefTest();
|
||||||
|
|
||||||
|
DoStrongConstTests();
|
||||||
DoConstConversionTests();
|
DoConstConversionTests();
|
||||||
DoOwnershipConversionTests();
|
DoOwnershipConversionTests();
|
||||||
DoInheritanceConversionTests();
|
DoInheritanceConversionTests();
|
||||||
|
@ -930,6 +1031,9 @@ int main( unsigned int , const char * [] )
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// $Log$
|
// $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
|
// Revision 1.4 2006/03/21 20:50:22 syntheticpp
|
||||||
// fix include error
|
// 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