1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/thread/atomic.cpp
3 // Purpose: wxAtomic??? unit test
4 // Author: Armel Asselin
6 // Copyright: (c) 2006 Armel Asselin
7 ///////////////////////////////////////////////////////////////////////////////
9 // ----------------------------------------------------------------------------
11 // ----------------------------------------------------------------------------
22 #include "wx/atomic.h"
23 #include "wx/thread.h"
24 #include "wx/dynarray.h"
27 WX_DEFINE_ARRAY_PTR(wxThread
*, wxArrayThread
);
29 // ----------------------------------------------------------------------------
31 // ----------------------------------------------------------------------------
33 // number of times to run the loops: the code takes too long to run if we use
34 // the bigger value with generic atomic operations implementation
35 #ifdef wxHAS_ATOMIC_OPS
36 static const wxInt32 ITERATIONS_NUM
= 10000000;
38 static const wxInt32 ITERATIONS_NUM
= 1000;
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 class AtomicTestCase
: public CppUnit::TestCase
58 class MyThread
: public wxThread
61 MyThread(wxAtomicInt
&operateOn
, ETestType testType
) : wxThread(wxTHREAD_JOINABLE
),
62 m_operateOn(operateOn
), m_testType(testType
) {}
64 // thread execution starts here
65 virtual void *Entry();
68 wxAtomicInt
&m_operateOn
;
72 CPPUNIT_TEST_SUITE( AtomicTestCase
);
73 CPPUNIT_TEST( TestNoThread
);
74 CPPUNIT_TEST( TestDecReturn
);
75 CPPUNIT_TEST( TestTwoThreadsMix
);
76 CPPUNIT_TEST( TestTenThreadsMix
);
77 CPPUNIT_TEST( TestTwoThreadsSeparate
);
78 CPPUNIT_TEST( TestTenThreadsSeparate
);
79 CPPUNIT_TEST_SUITE_END();
83 void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed
); }
84 void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed
); }
85 void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly
); }
86 void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly
); }
87 void TestWithThreads(int count
, ETestType testtype
);
89 DECLARE_NO_COPY_CLASS(AtomicTestCase
)
92 // register in the unnamed registry so that these tests are run by default
93 CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase
);
95 // also include in its own registry so that these tests can be run alone
96 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase
, "AtomicTestCase" );
98 void AtomicTestCase::TestNoThread()
100 wxAtomicInt int1
= 0,
103 for ( wxInt32 i
= 0; i
< ITERATIONS_NUM
; ++i
)
109 CPPUNIT_ASSERT( int1
== ITERATIONS_NUM
);
110 CPPUNIT_ASSERT( int2
== -ITERATIONS_NUM
);
113 void AtomicTestCase::TestDecReturn()
118 CPPUNIT_ASSERT( i
== 2 );
120 CPPUNIT_ASSERT( wxAtomicDec(i
) > 0 );
121 CPPUNIT_ASSERT( wxAtomicDec(i
) == 0 );
124 void AtomicTestCase::TestWithThreads(int count
, ETestType testType
)
128 wxArrayThread threads
;
131 for ( i
= 0; i
< count
; ++i
)
133 ETestType actualThreadType
;
137 actualThreadType
= testType
;
140 actualThreadType
= (i
&1)==0 ? IncOnly
: DecOnly
;
144 MyThread
*thread
= new MyThread(int1
, actualThreadType
);
146 if ( thread
->Create() != wxTHREAD_NO_ERROR
)
148 wxLogError(wxT("Can't create thread!"));
154 for ( i
= 0; i
< count
; ++i
)
160 for ( i
= 0; i
< count
; ++i
)
162 // each thread should return 0, else it detected some problem
163 CPPUNIT_ASSERT (threads
[i
]->Wait() == (wxThread::ExitCode
)0);
166 CPPUNIT_ASSERT( int1
== 0 );
169 // ----------------------------------------------------------------------------
171 void *AtomicTestCase::MyThread::Entry()
173 wxInt32 negativeValuesSeen
= 0;
175 for ( wxInt32 i
= 0; i
< ITERATIONS_NUM
; ++i
)
177 switch ( m_testType
)
179 case AtomicTestCase::IncAndDecMixed
:
180 wxAtomicInc(m_operateOn
);
181 wxAtomicDec(m_operateOn
);
184 ++negativeValuesSeen
;
187 case AtomicTestCase::IncOnly
:
188 wxAtomicInc(m_operateOn
);
191 case AtomicTestCase::DecOnly
:
192 wxAtomicDec(m_operateOn
);
197 return wxUIntToPtr(negativeValuesSeen
);