]> git.saurik.com Git - wxWidgets.git/blame - tests/thread/atomic.cpp
chanegd wxTlsValue to be pointer-like instead of value-like which doesn't work for...
[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
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"
cb979a71
VS
26#include "wx/log.h"
27
cde76cf2
VZ
28WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
29
42124e68
VZ
30// ----------------------------------------------------------------------------
31// constants
32// ----------------------------------------------------------------------------
33
34// number of times to run the loops: the code takes too long to run if we use
35// the bigger value with generic atomic operations implementation
36#ifdef wxHAS_ATOMIC_OPS
37 static const wxInt32 ITERATIONS_NUM = 10000000;
38#else
39 static const wxInt32 ITERATIONS_NUM = 1000;
40#endif
41
cde76cf2
VZ
42// ----------------------------------------------------------------------------
43// test class
44// ----------------------------------------------------------------------------
45
46class AtomicTestCase : public CppUnit::TestCase
47{
48public:
49 AtomicTestCase() { }
50
cde76cf2
VZ
51 enum ETestType
52 {
53 IncAndDecMixed,
54 IncOnly,
55 DecOnly
56 };
57
5098c258 58private:
cde76cf2
VZ
59 class MyThread : public wxThread
60 {
61 public:
62 MyThread(wxAtomicInt &operateOn, ETestType testType) : wxThread(wxTHREAD_JOINABLE),
63 m_operateOn(operateOn), m_testType(testType) {}
64
65 // thread execution starts here
66 virtual void *Entry();
67
68 public:
69 wxAtomicInt &m_operateOn;
70 ETestType m_testType;
71 };
72
73 CPPUNIT_TEST_SUITE( AtomicTestCase );
74 CPPUNIT_TEST( TestNoThread );
630dad8c 75 CPPUNIT_TEST( TestDecReturn );
cde76cf2
VZ
76 CPPUNIT_TEST( TestTwoThreadsMix );
77 CPPUNIT_TEST( TestTenThreadsMix );
78 CPPUNIT_TEST( TestTwoThreadsSeparate );
79 CPPUNIT_TEST( TestTenThreadsSeparate );
80 CPPUNIT_TEST_SUITE_END();
81
82 void TestNoThread();
630dad8c 83 void TestDecReturn();
cde76cf2
VZ
84 void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed); }
85 void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed); }
86 void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly); }
87 void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly); }
88 void TestWithThreads(int count, ETestType testtype);
89
90 DECLARE_NO_COPY_CLASS(AtomicTestCase)
91};
92
93// register in the unnamed registry so that these tests are run by default
94CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
95
96// also include in it's own registry so that these tests can be run alone
97CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
98
99void AtomicTestCase::TestNoThread()
100{
42124e68
VZ
101 wxAtomicInt int1 = 0,
102 int2 = 0;
cde76cf2 103
42124e68 104 for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
cde76cf2
VZ
105 {
106 wxAtomicInc(int1);
107 wxAtomicDec(int2);
108 }
109
42124e68
VZ
110 CPPUNIT_ASSERT( int1 == ITERATIONS_NUM );
111 CPPUNIT_ASSERT( int2 == -ITERATIONS_NUM );
cde76cf2
VZ
112}
113
630dad8c
VS
114void AtomicTestCase::TestDecReturn()
115{
116 wxAtomicInt i(0);
117 wxAtomicInc(i);
118 wxAtomicInc(i);
119 CPPUNIT_ASSERT( i == 2 );
120
121 CPPUNIT_ASSERT( wxAtomicDec(i) > 0 );
122 CPPUNIT_ASSERT( wxAtomicDec(i) == 0 );
123}
124
cde76cf2
VZ
125void AtomicTestCase::TestWithThreads(int count, ETestType testType)
126{
127 wxAtomicInt int1=0;
128
129 wxArrayThread threads;
130
131 int i;
132 for ( i = 0; i < count; ++i )
133 {
134 ETestType actualThreadType;
135 switch(testType)
136 {
137 default:
138 actualThreadType = testType;
139 break;
140 case IncOnly:
141 actualThreadType = (i&1)==0 ? IncOnly : DecOnly;
142 break;
143 }
144
145 MyThread *thread = new MyThread(int1, actualThreadType);
146
147 if ( thread->Create() != wxTHREAD_NO_ERROR )
148 {
149 wxLogError(wxT("Can't create thread!"));
150 }
151 else
152 threads.Add(thread);
153 }
154
155 for ( i = 0; i < count; ++i )
156 {
157 threads[i]->Run();
158 }
159
160
161 for ( i = 0; i < count; ++i )
162 {
163 // each thread should return 0, else it detected some problem
164 CPPUNIT_ASSERT (threads[i]->Wait() == (wxThread::ExitCode)0);
165 }
166
167 CPPUNIT_ASSERT( int1 == 0 );
168}
169
170// ----------------------------------------------------------------------------
171
172void *AtomicTestCase::MyThread::Entry()
173{
174 wxInt32 negativeValuesSeen = 0;
175
42124e68 176 for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
cde76cf2 177 {
42124e68 178 switch ( m_testType )
cde76cf2 179 {
42124e68
VZ
180 case AtomicTestCase::IncAndDecMixed:
181 wxAtomicInc(m_operateOn);
182 wxAtomicDec(m_operateOn);
cde76cf2 183
42124e68
VZ
184 if (m_operateOn < 0)
185 ++negativeValuesSeen;
186 break;
cde76cf2 187
42124e68
VZ
188 case AtomicTestCase::IncOnly:
189 wxAtomicInc(m_operateOn);
190 break;
cde76cf2 191
42124e68
VZ
192 case AtomicTestCase::DecOnly:
193 wxAtomicDec(m_operateOn);
194 break;
cde76cf2
VZ
195 }
196 }
197
c71396b4 198 return wxUIntToPtr(negativeValuesSeen);
cde76cf2 199}