]> git.saurik.com Git - wxWidgets.git/blame - tests/thread/atomic.cpp
Fix configure check for gcc atomics on 32-bit x86.
[wxWidgets.git] / tests / thread / atomic.cpp
CommitLineData
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
27WX_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
45class AtomicTestCase : public CppUnit::TestCase
46{
47public:
48 AtomicTestCase() { }
49
cde76cf2
VZ
50 enum ETestType
51 {
52 IncAndDecMixed,
53 IncOnly,
54 DecOnly
55 };
56
5098c258 57private:
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
93CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
94
e3778b4d 95// also include in its own registry so that these tests can be run alone
cde76cf2
VZ
96CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
97
98void 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
113void 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
124void 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
171void *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}