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