| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- ///////////////////////////////////////////////////////////////////////////////
- // Name: tests/thread/atomic.cpp
- // Purpose: wxAtomic??? unit test
- // Author: Armel Asselin
- // Created: 2006-12-14
- // Copyright: (c) 2006 Armel Asselin
- ///////////////////////////////////////////////////////////////////////////////
- // ----------------------------------------------------------------------------
- // headers
- // ----------------------------------------------------------------------------
- #include "testprec.h"
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
- #ifndef WX_PRECOMP
- #endif // WX_PRECOMP
- #include "wx/atomic.h"
- #include "wx/thread.h"
- #include "wx/dynarray.h"
- #include "wx/log.h"
- WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
- // ----------------------------------------------------------------------------
- // constants
- // ----------------------------------------------------------------------------
- // number of times to run the loops: the code takes too long to run if we use
- // the bigger value with generic atomic operations implementation
- #ifdef wxHAS_ATOMIC_OPS
- static const wxInt32 ITERATIONS_NUM = 10000000;
- #else
- static const wxInt32 ITERATIONS_NUM = 1000;
- #endif
- // ----------------------------------------------------------------------------
- // test class
- // ----------------------------------------------------------------------------
- class AtomicTestCase : public CppUnit::TestCase
- {
- public:
- AtomicTestCase() { }
- enum ETestType
- {
- IncAndDecMixed,
- IncOnly,
- DecOnly
- };
- private:
- class MyThread : public wxThread
- {
- public:
- MyThread(wxAtomicInt &operateOn, ETestType testType) : wxThread(wxTHREAD_JOINABLE),
- m_operateOn(operateOn), m_testType(testType) {}
- // thread execution starts here
- virtual void *Entry();
- public:
- wxAtomicInt &m_operateOn;
- ETestType m_testType;
- };
- CPPUNIT_TEST_SUITE( AtomicTestCase );
- CPPUNIT_TEST( TestNoThread );
- CPPUNIT_TEST( TestDecReturn );
- CPPUNIT_TEST( TestTwoThreadsMix );
- CPPUNIT_TEST( TestTenThreadsMix );
- CPPUNIT_TEST( TestTwoThreadsSeparate );
- CPPUNIT_TEST( TestTenThreadsSeparate );
- CPPUNIT_TEST_SUITE_END();
- void TestNoThread();
- void TestDecReturn();
- void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed); }
- void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed); }
- void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly); }
- void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly); }
- void TestWithThreads(int count, ETestType testtype);
- DECLARE_NO_COPY_CLASS(AtomicTestCase)
- };
- // register in the unnamed registry so that these tests are run by default
- CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
- // also include in its own registry so that these tests can be run alone
- CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
- void AtomicTestCase::TestNoThread()
- {
- wxAtomicInt int1 = 0,
- int2 = 0;
- for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
- {
- wxAtomicInc(int1);
- wxAtomicDec(int2);
- }
- CPPUNIT_ASSERT( int1 == ITERATIONS_NUM );
- CPPUNIT_ASSERT( int2 == -ITERATIONS_NUM );
- }
- void AtomicTestCase::TestDecReturn()
- {
- wxAtomicInt i(0);
- wxAtomicInc(i);
- wxAtomicInc(i);
- CPPUNIT_ASSERT( i == 2 );
- CPPUNIT_ASSERT( wxAtomicDec(i) > 0 );
- CPPUNIT_ASSERT( wxAtomicDec(i) == 0 );
- }
- void AtomicTestCase::TestWithThreads(int count, ETestType testType)
- {
- wxAtomicInt int1=0;
- wxArrayThread threads;
- int i;
- for ( i = 0; i < count; ++i )
- {
- ETestType actualThreadType;
- switch(testType)
- {
- default:
- actualThreadType = testType;
- break;
- case IncOnly:
- actualThreadType = (i&1)==0 ? IncOnly : DecOnly;
- break;
- }
- MyThread *thread = new MyThread(int1, actualThreadType);
- if ( thread->Create() != wxTHREAD_NO_ERROR )
- {
- wxLogError(wxT("Can't create thread!"));
- }
- else
- threads.Add(thread);
- }
- for ( i = 0; i < count; ++i )
- {
- threads[i]->Run();
- }
- for ( i = 0; i < count; ++i )
- {
- // each thread should return 0, else it detected some problem
- CPPUNIT_ASSERT (threads[i]->Wait() == (wxThread::ExitCode)0);
- }
- CPPUNIT_ASSERT( int1 == 0 );
- }
- // ----------------------------------------------------------------------------
- void *AtomicTestCase::MyThread::Entry()
- {
- wxInt32 negativeValuesSeen = 0;
- for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
- {
- switch ( m_testType )
- {
- case AtomicTestCase::IncAndDecMixed:
- wxAtomicInc(m_operateOn);
- wxAtomicDec(m_operateOn);
- if (m_operateOn < 0)
- ++negativeValuesSeen;
- break;
- case AtomicTestCase::IncOnly:
- wxAtomicInc(m_operateOn);
- break;
- case AtomicTestCase::DecOnly:
- wxAtomicDec(m_operateOn);
- break;
- }
- }
- return wxUIntToPtr(negativeValuesSeen);
- }
|