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:
rich_sposato 2006-04-05 22:56:58 +00:00
parent 0201647cdc
commit d5f4f0f77f
7 changed files with 3294 additions and 52 deletions

View file

@ -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=

View file

@ -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"
>

View file

@ -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.
//

View file

@ -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
View 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;
}
// ----------------------------------------------------------------------------