/** IncreaseThread provide data.
*/ class IncreaseThread : public Thread
{ public: explicit IncreaseThread( struct resource *pData ): pResource( pData ) { }
virtual ~IncreaseThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#IncreaseThread does not shutdown properly.\n", !isRunning( ) );
} protected: struct resource *pResource;
void SAL_CALL run( ) override
{
pResource->lock.acquire( ); for( sal_Int8 i = 0; i < 3; i++ )
{
pResource->data1++;
yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
} if ( pResource->data2 == 0 )
pResource->data2 = ( pResource->data1 > 0 ? pResource->data1 : 0 - pResource->data1 );
pResource->lock.release();
}
};
virtual ~DecreaseThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#DecreaseThread does not shutdown properly.\n", !isRunning( ) );
} protected: struct resource *pResource;
void SAL_CALL run( ) override
{
pResource->lock.acquire( ); for( sal_Int8 i = 0; i < 3; i++ )
{
pResource->data1--;
yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
} if ( pResource->data2 == 0 )
pResource->data2 = ( pResource->data1 > 0 ? pResource->data1 : 0 - pResource->data1 );
pResource->lock.release();
}
};
/** chain structure used in Threads as critical resource
*/ struct chain {
sal_Int32 buffer[ BUFFER_SIZE ];
Mutex lock;
sal_Int8 pos;
};
/** PutThread write to the chain structure in a mutex manner.
*/ class PutThread : public Thread
{ public: //get the struct pointer to write data to buffer explicit PutThread( struct chain* pData ): pChain( pData ) { }
virtual ~PutThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#PutThread does not shutdown properly.\n", !isRunning( ) );
} protected: struct chain* pChain;
void SAL_CALL run( ) override
{ //block here if the mutex has been acquired
pChain->lock.acquire( );
//current position in buffer to write
sal_Int8 nPos = pChain->pos;
oslThreadIdentifier oId = getIdentifier( ); //write data
sal_Int8 i; for ( i = 0; i < 5; i++ )
{
pChain->buffer[ nPos + i ] = oId;
yield( );
} //revise the position
pChain->pos = nPos + i;
//finish writing, release the mutex
pChain->lock.release();
}
};
/** thread for testing Mutex acquire.
*/ class HoldThread : public Thread
{ public: //get the Mutex pointer to operate explicit HoldThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
virtual ~HoldThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#HoldThread does not shutdown properly.\n", !isRunning( ) );
} protected:
Mutex* pMyMutex;
void SAL_CALL run() override
{ // block here if the mutex has been acquired
pMyMutex->acquire( );
printf("# Mutex acquired. \n" );
pMyMutex->release( );
}
};
class WaitThread : public Thread
{ public: //get the Mutex pointer to operate explicit WaitThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
virtual ~WaitThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#WaitThread does not shutdown properly.\n", !isRunning( ) );
} protected:
Mutex* pMyMutex;
void SAL_CALL run( ) override
{ // block here if the mutex has been acquired
pMyMutex->acquire( );
ThreadHelper::thread_sleep_tenth_sec( 2 );
pMyMutex->release( );
}
};
/** thread for testing getGlobalMutex.
*/ class GlobalMutexThread : public Thread
{ public: //get the Mutex pointer to operate
GlobalMutexThread( ){ }
virtual ~GlobalMutexThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#GlobalMutexThread does not shutdown properly.\n", !isRunning( ) );
} protected: void SAL_CALL run( ) override
{ // block here if the mutex has been acquired
Mutex* pGlobalMutex;
pGlobalMutex = Mutex::getGlobalMutex( );
pGlobalMutex->acquire( );
printf("# Global Mutex acquired. \n" );
pGlobalMutex->release( );
}
};
}
namespace osl_Mutex
{
/** Test of the osl::Mutex::constructor
*/ class ctor : public CppUnit::TestFixture
{ public: // initialise your test code values here. struct chain m_Data; struct resource m_Res;
void setUp( ) override
{ for ( sal_Int8 i=0; i < BUFFER_SIZE; i++ )
m_Data.buffer[i] = 0;
m_Data.pos = 0;
m_Res.data1 = 0;
m_Res.data2 = 0;
}
/** Create two threads to write data to the same buffer, use Mutex to assure duringonethreadwritedatafivetimes,theotherthreadshouldnotbeginwriting. thetwothreadswrotetwodifferentdata:theirthreadID,sowecancheckthedata inbuffertoknowtheorderofthetwothreadswriting
*/ void ctor_001()
{
PutThread myThread1( &m_Data );
PutThread myThread2( &m_Data );
myThread1.create( );
myThread2.create( );
//wait until the two threads terminate
myThread1.join( );
myThread2.join( );
bool bRes = false;
// every 5 data should the same // LLA: this is not a good check, it's too fix if (m_Data.buffer[0] == m_Data.buffer[1] &&
m_Data.buffer[1] == m_Data.buffer[2] &&
m_Data.buffer[2] == m_Data.buffer[3] &&
m_Data.buffer[3] == m_Data.buffer[4] &&
m_Data.buffer[5] == m_Data.buffer[6] &&
m_Data.buffer[6] == m_Data.buffer[7] &&
m_Data.buffer[7] == m_Data.buffer[8] &&
m_Data.buffer[8] == m_Data.buffer[9])
bRes = true;
/** Create two threads to write data to operate on the same number , use Mutex to assure, onethreadincreasedata3times,theotherthreaddecrease3times,storetheoperate resultwhenthefirstthreadcomplete,ifitisinterruptbytheotherthread,thestored numberwillnotbe3.
*/ void ctor_002()
{
IncreaseThread myThread1( &m_Res );
DecreaseThread myThread2( &m_Res );
myThread1.create( );
myThread2.create( );
//wait until the two threads terminate
myThread1.join( );
myThread2.join( );
bool bRes = false;
// every 5 data should the same if ( ( m_Res.data1 == 0 ) && ( m_Res.data2 == 3 ) )
bRes = true;
CPPUNIT_ASSERT_MESSAGE( "test Mutex ctor function: increase and decrease a number 3 times without interrupt.", bRes );
}
/** Test of the osl::Mutex::acquire method
*/ class acquire : public CppUnit::TestFixture
{ public: // acquire mutex in main thread, and then call acquire again in myThread, // the child thread should block, wait 2 secs, it still block. // Then release mutex in main thread, the child thread could return from acquire, // and go to exec next statement, so could terminate quickly. void acquire_001( )
{
Mutex aMutex; //acquire here bool bRes = aMutex.acquire( ); // pass the pointer of mutex to child thread
HoldThread myThread( &aMutex );
myThread.create( );
ThreadHelper::thread_sleep_tenth_sec( 2 ); // if acquire in myThread does not work, 2 secs is long enough, // myThread should terminate now, and bRes1 should be sal_False bool bRes1 = myThread.isRunning( );
aMutex.release( );
ThreadHelper::thread_sleep_tenth_sec( 1 ); // after release mutex, myThread stops blocking and will terminate immediately bool bRes2 = myThread.isRunning( );
myThread.join( );
/** Test of the osl::Mutex::tryToAcquire method
*/ class tryToAcquire : public CppUnit::TestFixture
{ public: // First let child thread acquire the mutex, and wait 2 secs, during the 2 secs, // in main thread, tryToAcquire mutex should return False // then after the child thread terminated, tryToAcquire should return True void tryToAcquire_001()
{
Mutex aMutex;
WaitThread myThread(&aMutex);
myThread.create();
// ensure the child thread acquire the mutex
ThreadHelper::thread_sleep_tenth_sec(1);
bool bRes1 = aMutex.tryToAcquire();
if (bRes1)
aMutex.release(); // wait the child thread terminate
myThread.join();
bool bRes2 = aMutex.tryToAcquire();
if (bRes2)
aMutex.release();
CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", !bRes1);
CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", bRes2);
}
CPPUNIT_TEST_SUITE(tryToAcquire);
CPPUNIT_TEST(tryToAcquire_001);
CPPUNIT_TEST_SUITE_END();
}; // class tryToAcquire
/** Test of the osl::Mutex::release method
*/ class release : public CppUnit::TestFixture
{ public: /** acquire/release are not used in pairs: after child thread acquired mutex, themainthreadreleaseit,thenanythreadcouldacquireit.
*/ void release_001()
{
Mutex aMutex;
WaitThread myThread( &aMutex );
myThread.create( );
// ensure the child thread acquire the mutex
ThreadHelper::thread_sleep_tenth_sec( 1 );
CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
!bRes1 );
CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
bRes2 );
CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
bRunning );
}
// how about release twice? void release_002()
{
}
/** Test of the osl::Mutex::getGlobalMutex method
*/ class getGlobalMutex : public CppUnit::TestFixture
{ public: // initialise your test code values here. void getGlobalMutex_001()
{
Mutex* pGlobalMutex;
pGlobalMutex = Mutex::getGlobalMutex();
pGlobalMutex->acquire();
CPPUNIT_ASSERT_MESSAGE( "Global Mutex works: if the code between {} get the different mutex as the former one, it will return false when release.",
bRes );
}
CPPUNIT_TEST_SUITE(getGlobalMutex);
CPPUNIT_TEST(getGlobalMutex_001);
CPPUNIT_TEST(getGlobalMutex_002);
CPPUNIT_TEST_SUITE_END();
}; // class getGlobalMutex
// Beginning of the test cases for osl_Guard class
namespace {
class GuardThread : public Thread
{ public: //get the Mutex pointer to operate explicit GuardThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
virtual ~GuardThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#GuardThread does not shutdown properly.\n", !isRunning( ) );
} protected:
Mutex* pMyMutex;
void SAL_CALL run( ) override
{ // block here if the mutex has been acquired
MutexGuard aGuard( pMyMutex );
ThreadHelper::thread_sleep_tenth_sec( 2 );
}
};
}
namespace osl_Guard
{ class ctor : public CppUnit::TestFixture
{ public: // insert your test code here. void ctor_001()
{
Mutex aMutex;
GuardThread myThread(&aMutex);
myThread.create();
ThreadHelper::thread_sleep_tenth_sec(1); bool bRes = aMutex.tryToAcquire(); // after 1 second, the mutex has been guarded, and the child thread should be running bool bRes1 = myThread.isRunning();
CPPUNIT_ASSERT_MESSAGE("GuardThread constructor: reference initialization, acquire the mutex before running the thread, then check if it is blocking.",
bRes);
}
CPPUNIT_TEST_SUITE(ctor);
CPPUNIT_TEST(ctor_001);
CPPUNIT_TEST(ctor_002);
CPPUNIT_TEST_SUITE_END();
}; // class ctor
// Beginning of the test cases for osl_ClearableGuard class
namespace {
/** Thread for test ClearableGuard
*/ class ClearGuardThread : public Thread
{ public: //get the Mutex pointer to operate explicit ClearGuardThread( Mutex* pMutex ): pMyMutex( pMutex ) {}
virtual ~ClearGuardThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#ClearGuardThread does not shutdown properly.\n", !isRunning( ) );
} protected:
Mutex* pMyMutex;
class ctor : public CppUnit::TestFixture
{ public: void ctor_001()
{
Mutex aMutex;
/// now, the aMutex has been guarded.
ClearableMutexGuard myMutexGuard( &aMutex );
/// it will return sal_False if the aMutex has not been Guarded. bool bRes = aMutex.release( );
CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized.",
bRes);
}
void ctor_002( )
{
Mutex aMutex;
/// now, the aMutex has been guarded, this time, we use reference constructor.
ClearableMutexGuard myMutexGuard( aMutex );
/// it will return sal_False if the aMutex has not been Guarded. bool bRes = aMutex.release( );
CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
bRes);
}
CPPUNIT_TEST_SUITE(ctor);
CPPUNIT_TEST(ctor_001);
CPPUNIT_TEST(ctor_002);
CPPUNIT_TEST_SUITE_END();
}; // class ctor
class clear : public CppUnit::TestFixture
{ public: void clear_001()
{
Mutex aMutex;
ClearGuardThread myThread(&aMutex);
myThread.create();
TimeValue aTimeVal_befor;
osl_getSystemTime( &aTimeVal_befor ); // wait 1 second to assure the child thread has begun
ThreadHelper::thread_sleep(1);
while (true)
{ if (aMutex.tryToAcquire())
{ break;
}
ThreadHelper::thread_sleep(1);
}
TimeValue aTimeVal_after;
osl_getSystemTime( &aTimeVal_after );
sal_Int32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
printf("nSec is %" SAL_PRIdINT32 "\n", nSec);
// Beginning of the test cases for osl_ResettableGuard class
namespace {
/** Thread for test ResettableGuard
*/ class ResetGuardThread : public Thread
{ public: //get the Mutex pointer to operate explicit ResetGuardThread( Mutex* pMutex ): pMyMutex( pMutex ) {}
virtual ~ResetGuardThread( ) override
{
CPPUNIT_ASSERT_MESSAGE( "#ResetGuardThread does not shutdown properly.\n", !isRunning( ) );
} protected:
Mutex* pMyMutex;
namespace osl_ResettableGuard
{ class ctor : public CppUnit::TestFixture
{ public: void ctor_001()
{
Mutex aMutex;
/// now, the aMutex has been guarded.
ResettableMutexGuard myMutexGuard( &aMutex );
/// it will return sal_False if the aMutex has not been Guarded. bool bRes = aMutex.release( );
CPPUNIT_ASSERT_MESSAGE("ResettableMutexGuard constructor, test the acquire operation when initialized.",
bRes);
aMutex.acquire();
}
void ctor_002( )
{
Mutex aMutex;
/// now, the aMutex has been guarded, this time, we use reference constructor.
ResettableMutexGuard myMutexGuard( aMutex );
/// it will return sal_False if the aMutex has not been Guarded. bool bRes = aMutex.release( );
CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
bRes);
aMutex.acquire();
}
CPPUNIT_TEST_SUITE(ctor);
CPPUNIT_TEST(ctor_001);
CPPUNIT_TEST(ctor_002);
CPPUNIT_TEST_SUITE_END();
}; // class ctor
/// can release after reset.
myMutexGuard.reset( ); bool bRes1 = aMutex.release( );
CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
bRes );
CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
bRes1 );
aMutex.acquire();
} #endif
CPPUNIT_TEST_SUITE(reset);
CPPUNIT_TEST(reset_001); #ifdef LINUX
CPPUNIT_TEST(reset_002); #endif
CPPUNIT_TEST_SUITE_END();
}; // class reset
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.