PCH-less compilation fix
[wxWidgets.git] / tests / thread / atomic.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/thread/atomic.cpp
3 // Purpose: wxAtomic??? unit test
4 // Author: Armel Asselin
5 // Created: 2006-12-14
6 // RCS-ID: $Id$
7 // Copyright: (c) 2006 Armel Asselin
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "testprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #ifndef WX_PRECOMP
21 #endif // WX_PRECOMP
22
23 #include "wx/atomic.h"
24 #include "wx/thread.h"
25 #include "wx/dynarray.h"
26 #include "wx/log.h"
27
28 WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
29
30 // ----------------------------------------------------------------------------
31 // test class
32 // ----------------------------------------------------------------------------
33
34 class AtomicTestCase : public CppUnit::TestCase
35 {
36 public:
37 AtomicTestCase() { }
38
39 private:
40
41 enum ETestType
42 {
43 IncAndDecMixed,
44 IncOnly,
45 DecOnly
46 };
47
48 class MyThread : public wxThread
49 {
50 public:
51 MyThread(wxAtomicInt &operateOn, ETestType testType) : wxThread(wxTHREAD_JOINABLE),
52 m_operateOn(operateOn), m_testType(testType) {}
53
54 // thread execution starts here
55 virtual void *Entry();
56
57 public:
58 wxAtomicInt &m_operateOn;
59 ETestType m_testType;
60 };
61
62 CPPUNIT_TEST_SUITE( AtomicTestCase );
63 CPPUNIT_TEST( TestNoThread );
64 CPPUNIT_TEST( TestTwoThreadsMix );
65 CPPUNIT_TEST( TestTenThreadsMix );
66 CPPUNIT_TEST( TestTwoThreadsSeparate );
67 CPPUNIT_TEST( TestTenThreadsSeparate );
68 CPPUNIT_TEST_SUITE_END();
69
70 void TestNoThread();
71 void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed); }
72 void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed); }
73 void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly); }
74 void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly); }
75 void TestWithThreads(int count, ETestType testtype);
76
77 DECLARE_NO_COPY_CLASS(AtomicTestCase)
78 };
79
80 // register in the unnamed registry so that these tests are run by default
81 CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
82
83 // also include in it's own registry so that these tests can be run alone
84 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
85
86 void AtomicTestCase::TestNoThread()
87 {
88 wxAtomicInt int1=0, int2=0;
89
90 for (wxInt32 i=0; i<10000000; ++i)
91 {
92 wxAtomicInc(int1);
93 wxAtomicDec(int2);
94 }
95
96 CPPUNIT_ASSERT( int1 == 10000000 );
97 CPPUNIT_ASSERT( int2 == -10000000 );
98 }
99
100 void AtomicTestCase::TestWithThreads(int count, ETestType testType)
101 {
102 wxAtomicInt int1=0;
103
104 wxArrayThread threads;
105
106 int i;
107 for ( i = 0; i < count; ++i )
108 {
109 ETestType actualThreadType;
110 switch(testType)
111 {
112 default:
113 actualThreadType = testType;
114 break;
115 case IncOnly:
116 actualThreadType = (i&1)==0 ? IncOnly : DecOnly;
117 break;
118 }
119
120 MyThread *thread = new MyThread(int1, actualThreadType);
121
122 if ( thread->Create() != wxTHREAD_NO_ERROR )
123 {
124 wxLogError(wxT("Can't create thread!"));
125 }
126 else
127 threads.Add(thread);
128 }
129
130 for ( i = 0; i < count; ++i )
131 {
132 threads[i]->Run();
133 }
134
135
136 for ( i = 0; i < count; ++i )
137 {
138 // each thread should return 0, else it detected some problem
139 CPPUNIT_ASSERT (threads[i]->Wait() == (wxThread::ExitCode)0);
140 }
141
142 CPPUNIT_ASSERT( int1 == 0 );
143 }
144
145 // ----------------------------------------------------------------------------
146
147 void *AtomicTestCase::MyThread::Entry()
148 {
149 wxInt32 negativeValuesSeen = 0;
150
151 for (wxInt32 i=0; i<10000000; ++i)
152 {
153 switch (m_testType)
154 {
155 case AtomicTestCase::IncAndDecMixed:
156 wxAtomicInc(m_operateOn);
157 wxAtomicDec(m_operateOn);
158
159 if (m_operateOn < 0)
160 ++negativeValuesSeen;
161 break;
162
163 case AtomicTestCase::IncOnly:
164 wxAtomicInc(m_operateOn);
165 break;
166
167 case AtomicTestCase::DecOnly:
168 wxAtomicDec(m_operateOn);
169 break;
170 }
171 }
172
173 return (wxThread::ExitCode)negativeValuesSeen;
174 }