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