Reference-counting helpers - Copy/move cons/ass w/ casts
Added tests and fixed a few bugs.
This commit is contained in:
parent
e8e0e8101d
commit
6afe127d13
3 changed files with 189 additions and 2 deletions
|
@ -73,6 +73,9 @@ class T_RcPtr
|
|||
T_AtomicRcClass , T_SimpleRcClass
|
||||
>;
|
||||
|
||||
// All RcPtr's are friends
|
||||
template< typename > friend class T_RcPtr;
|
||||
|
||||
private:
|
||||
T_Target* target_;
|
||||
void setTarget_( T_Target* t ) noexcept;
|
||||
|
@ -88,6 +91,10 @@ class T_RcPtr
|
|||
template< typename... AT >
|
||||
static T_RcPtr< Type > New( AT&& ... arguments );
|
||||
|
||||
// Initialise from raw pointer. The instance must have a reference
|
||||
// count of zero, and must have been allocated using new.
|
||||
static T_RcPtr< Type > FromRaw( Type* ptr ) noexcept;
|
||||
|
||||
void clear( ) noexcept;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
@ -145,6 +152,17 @@ class T_RcPtr
|
|||
template< typename T >
|
||||
void swap( T_RcPtr< T >& lhs , T_RcPtr< T >& rhs ) noexcept;
|
||||
|
||||
template< typename T >
|
||||
inline T_RcPtr< T > T_RcPtr< T >::FromRaw(
|
||||
T* ptr ) noexcept
|
||||
{
|
||||
assert( ptr->getReferenceCount( ) == 0 );
|
||||
T_RcPtr< T > rv;
|
||||
ptr->increaseReferences_( );
|
||||
rv.target_ = ptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
#endif // _H_EBCL_REFCOUNT
|
||||
|
|
|
@ -168,7 +168,9 @@ template<
|
|||
T_RcPtr< Q >&& other ) noexcept
|
||||
: target_{ nullptr }
|
||||
{
|
||||
std::swap( target_ , other.target_ );
|
||||
T* const ptr{ (T*) other.target_ };
|
||||
other.target_ = nullptr;
|
||||
target_ = ptr;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
|
|
|
@ -12,10 +12,13 @@ class RefCountTest : public CppUnit::TestFixture
|
|||
static uint32_t cNew;
|
||||
static uint32_t cDel;
|
||||
T_Test( ) noexcept { cNew ++; }
|
||||
~T_Test( ) noexcept { cDel ++; }
|
||||
virtual ~T_Test( ) noexcept { cDel ++; }
|
||||
};
|
||||
using P_Test = T_RcPtr< T_Test >;
|
||||
|
||||
class T_Child : public T_Test { };
|
||||
using P_Child = T_RcPtr< T_Child >;
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( RefCountTest );
|
||||
CPPUNIT_TEST( testStackInstance );
|
||||
|
@ -24,9 +27,24 @@ class RefCountTest : public CppUnit::TestFixture
|
|||
CPPUNIT_TEST( testConstruct );
|
||||
|
||||
CPPUNIT_TEST( testCopyCons );
|
||||
CPPUNIT_TEST( testCopyConsToBase );
|
||||
CPPUNIT_TEST( testCopyConsToChildOk );
|
||||
CPPUNIT_TEST( testCopyConsToChildBad );
|
||||
|
||||
CPPUNIT_TEST( testCopyAss );
|
||||
CPPUNIT_TEST( testCopyAssToBase );
|
||||
CPPUNIT_TEST( testCopyAssToChildOk );
|
||||
CPPUNIT_TEST( testCopyAssToChildBad );
|
||||
|
||||
CPPUNIT_TEST( testMoveCons );
|
||||
CPPUNIT_TEST( testMoveConsToBase );
|
||||
CPPUNIT_TEST( testMoveConsToChildOk );
|
||||
CPPUNIT_TEST( testMoveConsToChildBad );
|
||||
|
||||
CPPUNIT_TEST( testMoveAss );
|
||||
CPPUNIT_TEST( testMoveAssToBase );
|
||||
CPPUNIT_TEST( testMoveAssToChildOk );
|
||||
CPPUNIT_TEST( testMoveAssToChildBad );
|
||||
|
||||
CPPUNIT_TEST( testSwap );
|
||||
CPPUNIT_TEST_SUITE_END( );
|
||||
|
@ -40,9 +58,24 @@ class RefCountTest : public CppUnit::TestFixture
|
|||
void testConstruct( );
|
||||
|
||||
void testCopyCons( );
|
||||
void testCopyConsToBase( );
|
||||
void testCopyConsToChildOk( );
|
||||
void testCopyConsToChildBad( );
|
||||
|
||||
void testCopyAss( );
|
||||
void testCopyAssToBase( );
|
||||
void testCopyAssToChildOk( );
|
||||
void testCopyAssToChildBad( );
|
||||
|
||||
void testMoveCons( );
|
||||
void testMoveConsToBase( );
|
||||
void testMoveConsToChildOk( );
|
||||
void testMoveConsToChildBad( );
|
||||
|
||||
void testMoveAss( );
|
||||
void testMoveAssToBase( );
|
||||
void testMoveAssToChildOk( );
|
||||
void testMoveAssToChildBad( );
|
||||
|
||||
void testSwap( );
|
||||
};
|
||||
|
@ -127,6 +160,38 @@ void RefCountTest< A >::testCopyCons( )
|
|||
CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyConsToBase( )
|
||||
{
|
||||
P_Child p1{ P_Child::New( ) };
|
||||
P_Test p2{ p1 };
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( p1.get( ) == p2.get( ) );
|
||||
CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyConsToChildOk( )
|
||||
{
|
||||
P_Test p1{ P_Test::FromRaw( new T_Child( ) ) };
|
||||
P_Child p2{ p1 };
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( p1.get( ) == p2.get( ) );
|
||||
CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyConsToChildBad( )
|
||||
{
|
||||
P_Test p1{ P_Test::New( ) };
|
||||
CPPUNIT_ASSERT_THROW( P_Child p2{ p1 } , std::bad_cast );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyAss( )
|
||||
{
|
||||
|
@ -147,6 +212,41 @@ void RefCountTest< A >::testCopyAss( )
|
|||
CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyAssToBase( )
|
||||
{
|
||||
P_Child p1{ P_Child::New( ) };
|
||||
P_Test p2;
|
||||
p2 = p1;
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( p1.get( ) == p2.get( ) );
|
||||
CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyAssToChildOk( )
|
||||
{
|
||||
P_Test p1{ P_Test::FromRaw( new T_Child( ) ) };
|
||||
P_Child p2;
|
||||
p2 = p1;
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( p1.get( ) == p2.get( ) );
|
||||
CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testCopyAssToChildBad( )
|
||||
{
|
||||
P_Test p1{ P_Test::New( ) };
|
||||
P_Child p2;
|
||||
CPPUNIT_ASSERT_THROW( p2 = p1 , std::bad_cast );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveCons( )
|
||||
{
|
||||
|
@ -162,6 +262,39 @@ void RefCountTest< A >::testMoveCons( )
|
|||
CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveConsToBase( )
|
||||
{
|
||||
P_Child p1{ P_Child::New( ) };
|
||||
P_Test p2{ std::move( p1 ) };
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( !p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveConsToChildOk( )
|
||||
{
|
||||
P_Test p1{ P_Test::FromRaw( new T_Child( ) ) };
|
||||
P_Child p2{ std::move( p1 ) };
|
||||
|
||||
CPPUNIT_ASSERT( bool( p2 ) );
|
||||
CPPUNIT_ASSERT( !p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveConsToChildBad( )
|
||||
{
|
||||
P_Test p1{ P_Test::New( ) };
|
||||
CPPUNIT_ASSERT_THROW( P_Child p2{ std::move( p1 ) } , std::bad_cast );
|
||||
CPPUNIT_ASSERT( p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveAss( )
|
||||
{
|
||||
|
@ -179,6 +312,40 @@ void RefCountTest< A >::testMoveAss( )
|
|||
CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveAssToBase( )
|
||||
{
|
||||
P_Child p1{ P_Child::New( ) };
|
||||
P_Test p2;
|
||||
p2 = std::move( p1 );
|
||||
|
||||
CPPUNIT_ASSERT( p2 );
|
||||
CPPUNIT_ASSERT( !p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveAssToChildOk( )
|
||||
{
|
||||
P_Test p1{ P_Test::FromRaw( new T_Child( ) ) };
|
||||
P_Child p2;
|
||||
p2 = std::move( p1 );
|
||||
|
||||
CPPUNIT_ASSERT( p2 );
|
||||
CPPUNIT_ASSERT( !p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
template< bool A >
|
||||
void RefCountTest< A >::testMoveAssToChildBad( )
|
||||
{
|
||||
P_Test p1{ P_Test::New( ) };
|
||||
P_Child p2;
|
||||
CPPUNIT_ASSERT_THROW( p2 = std::move( p1 ) , std::bad_cast );
|
||||
CPPUNIT_ASSERT( p1 );
|
||||
CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
template< bool A >
|
||||
|
|
Loading…
Reference in a new issue