compilation fixes for VC6
[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 enum ETestType
40 {
41 IncAndDecMixed,
42 IncOnly,
43 DecOnly
44 };
45
46 private:
47 class MyThread : public wxThread
48 {
49 public:
50 MyThread(wxAtomicInt &operateOn, ETestType testType) : wxThread(wxTHREAD_JOINABLE),
51 m_operateOn(operateOn), m_testType(testType) {}
52
53 // thread execution starts here
54 virtual void *Entry();
55
56 public:
57 wxAtomicInt &m_operateOn;
58 ETestType m_testType;
59 };
60
61 CPPUNIT_TEST_SUITE( AtomicTestCase );
62 CPPUNIT_TEST( TestNoThread );
63 CPPUNIT_TEST( TestDecReturn );
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 TestDecReturn();
72 void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed); }
73 void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed); }
74 void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly); }
75 void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly); }
76 void TestWithThreads(int count, ETestType testtype);
77
78 DECLARE_NO_COPY_CLASS(AtomicTestCase)
79 };
80
81 // register in the unnamed registry so that these tests are run by default
82 CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
83
84 // also include in it's own registry so that these tests can be run alone
85 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
86
87 void AtomicTestCase::TestNoThread()
88 {
89 wxAtomicInt int1=0, int2=0;
90
91 for (wxInt32 i=0; i<10000000; ++i)
92 {
93 wxAtomicInc(int1);
94 wxAtomicDec(int2);
95 }
96
97 CPPUNIT_ASSERT( int1 == 10000000 );
98 CPPUNIT_ASSERT( int2 == -10000000 );
99 }
100
101 void AtomicTestCase::TestDecReturn()
102 {
103 wxAtomicInt i(0);
104 wxAtomicInc(i);
105 wxAtomicInc(i);
106 CPPUNIT_ASSERT( i == 2 );
107
108 CPPUNIT_ASSERT( wxAtomicDec(i) > 0 );
109 CPPUNIT_ASSERT( wxAtomicDec(i) == 0 );
110 }
111
112 void AtomicTestCase::TestWithThreads(int count, ETestType testType)
113 {
114 wxAtomicInt int1=0;
115
116 wxArrayThread threads;
117
118 int i;
119 for ( i = 0; i < count; ++i )
120 {
121 ETestType actualThreadType;
122 switch(testType)
123 {
124 default:
125 actualThreadType = testType;
126 break;
127 case IncOnly:
128 actualThreadType = (i&1)==0 ? IncOnly : DecOnly;
129 break;
130 }
131
132 MyThread *thread = new MyThread(int1, actualThreadType);
133
134 if ( thread->Create() != wxTHREAD_NO_ERROR )
135 {
136 wxLogError(wxT("Can't create thread!"));
137 }
138 else
139 threads.Add(thread);
140 }
141
142 for ( i = 0; i < count; ++i )
143 {
144 threads[i]->Run();
145 }
146
147
148 for ( i = 0; i < count; ++i )
149 {
150 // each thread should return 0, else it detected some problem
151 CPPUNIT_ASSERT (threads[i]->Wait() == (wxThread::ExitCode)0);
152 }
153
154 CPPUNIT_ASSERT( int1 == 0 );
155 }
156
157 // ----------------------------------------------------------------------------
158
159 void *AtomicTestCase::MyThread::Entry()
160 {
161 wxInt32 negativeValuesSeen = 0;
162
163 for (wxInt32 i=0; i<10000000; ++i)
164 {
165 switch (m_testType)
166 {
167 case AtomicTestCase::IncAndDecMixed:
168 wxAtomicInc(m_operateOn);
169 wxAtomicDec(m_operateOn);
170
171 if (m_operateOn < 0)
172 ++negativeValuesSeen;
173 break;
174
175 case AtomicTestCase::IncOnly:
176 wxAtomicInc(m_operateOn);
177 break;
178
179 case AtomicTestCase::DecOnly:
180 wxAtomicDec(m_operateOn);
181 break;
182 }
183 }
184
185 return (wxThread::ExitCode)negativeValuesSeen;
186 }