Added test for thread-safe StrongPtr policy.
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@643 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
5261fbbcd6
commit
4bc6a12222
4 changed files with 385 additions and 1 deletions
331
test/SmartPtr/LockTest.cpp
Normal file
331
test/SmartPtr/LockTest.cpp
Normal file
|
@ -0,0 +1,331 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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$
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
//#define LOKI_CLASS_LEVEL_THREADING
|
||||
|
||||
#ifndef LOKI_CLASS_LEVEL_THREADING
|
||||
#define LOKI_OBJECT_LEVEL_THREADING
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#include <loki/Threads.h>
|
||||
#include <loki/StrongPtr.h>
|
||||
#include <loki/SafeFormat.h>
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
typedef unsigned int ( WINAPI * ThreadFunction_ )( void * );
|
||||
|
||||
#define LOKI_pthread_t HANDLE
|
||||
|
||||
#define LOKI_pthread_create(handle,attr,func,arg) \
|
||||
(int)((*handle=(HANDLE) _beginthreadex (NULL,0,(ThreadFunction_)func,arg,0,NULL))==NULL)
|
||||
|
||||
#define LOKI_pthread_join(thread, result) \
|
||||
((::WaitForSingleObject((thread),INFINITE)!=WAIT_OBJECT_0) || !CloseHandle(thread))
|
||||
|
||||
#else
|
||||
|
||||
#define LOKI_pthread_t \
|
||||
pthread_t
|
||||
#define LOKI_pthread_create(handle,attr,func,arg) \
|
||||
pthread_create(handle,attr,func,arg)
|
||||
#define LOKI_pthread_join(thread, result) \
|
||||
pthread_join(thread, result)
|
||||
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace Loki;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
|
||||
typedef void * ( * CallFunction )( void * );
|
||||
|
||||
Thread( CallFunction func, void * parm )
|
||||
: pthread_()
|
||||
, func_( func )
|
||||
, parm_( parm )
|
||||
{
|
||||
}
|
||||
|
||||
void AssignTask( CallFunction func, void * parm )
|
||||
{
|
||||
func_ = func;
|
||||
parm_ = parm;
|
||||
}
|
||||
|
||||
int Start( void )
|
||||
{
|
||||
return LOKI_pthread_create( &pthread_, NULL, func_, parm_ );
|
||||
}
|
||||
|
||||
int WaitForThread( void ) const
|
||||
{
|
||||
int status = 0;
|
||||
(void) status;
|
||||
return LOKI_pthread_join( pthread_,
|
||||
reinterpret_cast< void * * >( &status ) );
|
||||
}
|
||||
|
||||
private:
|
||||
LOKI_pthread_t pthread_;
|
||||
CallFunction func_;
|
||||
void * parm_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
ThreadPool( void ) : m_threads()
|
||||
{
|
||||
}
|
||||
|
||||
void Create( size_t threadCount, Thread::CallFunction function )
|
||||
{
|
||||
for( size_t ii = 0; ii < threadCount; ii++ )
|
||||
{
|
||||
Printf( "Creating thread %d\n" )( ii );
|
||||
Thread * thread = new Thread( function,
|
||||
reinterpret_cast< void * >( ii ) );
|
||||
m_threads.push_back( thread );
|
||||
}
|
||||
}
|
||||
|
||||
void Start( void )
|
||||
{
|
||||
for ( size_t ii = 0; ii < m_threads.size(); ii++ )
|
||||
m_threads.at( ii )->Start();
|
||||
}
|
||||
|
||||
void Join( void ) const
|
||||
{
|
||||
for ( size_t ii = 0; ii < m_threads.size(); ii++ )
|
||||
m_threads.at( ii )->WaitForThread();
|
||||
}
|
||||
|
||||
~ThreadPool( void )
|
||||
{
|
||||
for ( size_t ii = 0; ii < m_threads.size(); ii++ )
|
||||
{
|
||||
delete m_threads.at(ii);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector< Thread * > Threads;
|
||||
|
||||
Threads m_threads;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const unsigned int loop = 5;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
|
||||
A( void ) {}
|
||||
|
||||
#define BIG_FOR_LOOP for( unsigned int i = 0; i < 10000000; i++ ) g++;
|
||||
|
||||
void Print( void * id ) const
|
||||
{
|
||||
BIG_FOR_LOOP;Printf("%p: ----------------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ---------------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: --------------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: -------------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ------------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: -----------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ----------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ---------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: --------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: -------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ------\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: -----\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ----\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: ---\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: --\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: -\n")(id);
|
||||
BIG_FOR_LOOP;Printf("%p: \n")(id);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static unsigned int g;
|
||||
};
|
||||
|
||||
unsigned int A::g = 0;
|
||||
|
||||
typedef Loki::StrongPtr< A, true, TwoRefCounts, DisallowConversion,
|
||||
NoCheck, NeverReset, DeleteSingle, DontPropagateConst >
|
||||
A_ptr;
|
||||
|
||||
typedef Loki::StrongPtr< A, true, LockableTwoRefCounts, DisallowConversion,
|
||||
NoCheck, NeverReset, DeleteSingle, DontPropagateConst >
|
||||
A_Lockable_ptr;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class SafeA
|
||||
{
|
||||
public:
|
||||
static SafeA & GetIt( void )
|
||||
{
|
||||
if ( NULL == s_instance )
|
||||
s_instance = new SafeA;
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
static void Destroy( void )
|
||||
{
|
||||
if ( NULL == s_instance )
|
||||
{
|
||||
delete s_instance;
|
||||
s_instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
A_Lockable_ptr GetA (void) { return m_ptr; }
|
||||
|
||||
private:
|
||||
static SafeA * s_instance;
|
||||
|
||||
SafeA( void ) : m_ptr( new A ) {}
|
||||
|
||||
~SafeA( void ) {}
|
||||
|
||||
A_Lockable_ptr m_ptr;
|
||||
};
|
||||
|
||||
SafeA * SafeA::s_instance = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class UnsafeA
|
||||
{
|
||||
public:
|
||||
static UnsafeA & GetIt( void )
|
||||
{
|
||||
if ( NULL == s_instance )
|
||||
s_instance = new UnsafeA;
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
static void Destroy( void )
|
||||
{
|
||||
if ( NULL == s_instance )
|
||||
{
|
||||
delete s_instance;
|
||||
s_instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
A_ptr GetA (void) { return m_ptr; }
|
||||
|
||||
private:
|
||||
static UnsafeA * s_instance;
|
||||
|
||||
UnsafeA( void ) : m_ptr( new A ) {}
|
||||
|
||||
~UnsafeA( void ) {}
|
||||
|
||||
A_ptr m_ptr;
|
||||
};
|
||||
|
||||
UnsafeA * UnsafeA::s_instance = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void * RunLocked( void * id )
|
||||
{
|
||||
A_Lockable_ptr ap( SafeA::GetIt().GetA() );
|
||||
for( unsigned int i = 0; i < loop; i++ )
|
||||
{
|
||||
ap.Lock();
|
||||
ap->Print( id );
|
||||
ap.Unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void * Run( void * id )
|
||||
{
|
||||
A_ptr ap( UnsafeA::GetIt().GetA() );
|
||||
for( unsigned int i = 0; i < loop; i++ )
|
||||
{
|
||||
ap->Print( id );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DoLockedPtrTest( void )
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
/** @note For some reason, mutexes implemented using Microsoft's
|
||||
CriticalSection don't work properly unless this mutex is here.
|
||||
*/
|
||||
Loki::Mutex mutex;
|
||||
|
||||
SafeA::GetIt();
|
||||
UnsafeA::GetIt();
|
||||
::system( "pause" );
|
||||
{
|
||||
ThreadPool pool;
|
||||
pool.Create( 5, RunLocked );
|
||||
pool.Start();
|
||||
pool.Join();
|
||||
}
|
||||
::system( "pause" );
|
||||
{
|
||||
ThreadPool pool;
|
||||
pool.Create( 5, Run );
|
||||
pool.Start();
|
||||
pool.Join();
|
||||
}
|
||||
SafeA::Destroy();
|
||||
UnsafeA::Destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// $Log$
|
||||
// Revision 1.1 2006/04/28 00:34:21 rich_sposato
|
||||
// Added test for thread-safe StrongPtr policy.
|
||||
//
|
|
@ -1,7 +1,7 @@
|
|||
[Project]
|
||||
FileName=SmartPtr.dev
|
||||
Name=SmartPtr
|
||||
UnitCount=12
|
||||
UnitCount=15
|
||||
Type=1
|
||||
Ver=1
|
||||
ObjFiles=
|
||||
|
@ -167,3 +167,33 @@ Priority=1000
|
|||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit13]
|
||||
FileName=LockTest.cpp
|
||||
CompileCpp=1
|
||||
Folder=Tests
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit14]
|
||||
FileName=..\..\src\SafeFormat.cpp
|
||||
CompileCpp=1
|
||||
Folder=Sources
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit15]
|
||||
FileName=..\..\include\loki\SafeFormat.h
|
||||
CompileCpp=1
|
||||
Folder=Headers
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE _SECURE_SCL=1"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="3"
|
||||
WarningLevel="4"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
|
@ -105,6 +108,7 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
WarningLevel="4"
|
||||
/>
|
||||
|
@ -154,10 +158,22 @@
|
|||
RelativePath=".\base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\LockTest.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SafeFormat.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\loki\SafeFormat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\Singleton.cpp"
|
||||
>
|
||||
|
|
|
@ -32,6 +32,8 @@ extern void DoWeakCycleTests( void );
|
|||
extern void DoStrongConstTests( void );
|
||||
extern void DoStrongForwardReferenceTest( void );
|
||||
|
||||
extern void DoLockedPtrTest( void );
|
||||
|
||||
unsigned int BaseClass::s_constructions = 0;
|
||||
unsigned int BaseClass::s_destructions = 0;
|
||||
|
||||
|
@ -1016,6 +1018,8 @@ int main( unsigned int , const char * [] )
|
|||
DoConstConversionTests();
|
||||
DoOwnershipConversionTests();
|
||||
DoInheritanceConversionTests();
|
||||
|
||||
DoLockedPtrTest();
|
||||
|
||||
// Check that nothing was leaked.
|
||||
assert( BaseClass::AllDestroyed() );
|
||||
|
@ -1031,6 +1035,9 @@ int main( unsigned int , const char * [] )
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
// $Log$
|
||||
// Revision 1.7 2006/04/28 00:34:21 rich_sposato
|
||||
// Added test for thread-safe StrongPtr policy.
|
||||
//
|
||||
// Revision 1.6 2006/04/16 14:05:39 syntheticpp
|
||||
// remove warnings
|
||||
//
|
||||
|
|
Loading…
Add table
Reference in a new issue