1 /*
2 *
3 * Copyright (c) 2004
4 * John Maddock
5 *
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 *
10 */
11
12 /*
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE static_mutex_test.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: test program for boost::static_mutex.
17 */
18
19 #include <boost/regex/pending/static_mutex.hpp>
20 #include <boost/thread/thread.hpp>
21 #include <boost/timer.hpp>
22 #include <iostream>
23 #include <iomanip>
24
25 #ifdef BOOST_REGEX_CXX03
26 //
27 // we cannot use the regular Boost.Test in here: it is not thread safe
28 // and calls to BOOST_CHECK will eventually crash on some compilers
29 // (Borland certainly) due to race conditions inside the Boost.Test lib.
30 //
31 #define BOOST_CHECK(pred) if(!(pred)) failed_test(__FILE__, __LINE__, BOOST_STRINGIZE(pred));
32
33 int total_failures = 0;
failed_test(const char * file,int line,const char * pred)34 void failed_test(const char* file, int line, const char* pred)
35 {
36 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
37 boost::static_mutex::scoped_lock guard(mut);
38 ++total_failures;
39 std::cout << "Failed test in \"" << file << "\" at line " << line << ": " << pred << std::endl;
40 }
41
print_cycles(int c)42 void print_cycles(int c)
43 {
44 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
45 boost::static_mutex::scoped_lock guard(mut);
46 std::cout << "Thread exited after " << c << " cycles." << std::endl;
47 }
48
sufficient_time()49 bool sufficient_time()
50 {
51 // return true if enough time has passed since the tests began:
52 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
53 boost::static_mutex::scoped_lock guard(mut);
54 static boost::timer t;
55 // is 10 seconds enough?
56 return t.elapsed() >= 10.0;
57 }
58
59 // define three trivial test proceedures:
t1()60 bool t1()
61 {
62 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
63 static int has_lock = 0;
64 static int data = 10000;
65
66 boost::static_mutex::scoped_lock guard(mut);
67 BOOST_CHECK(++has_lock == 1);
68 BOOST_CHECK(guard.locked());
69 BOOST_CHECK(guard);
70 bool result = (--data > 0) ? true : false;
71 BOOST_CHECK(--has_lock == 0);
72 return result;
73 }
74
t2()75 bool t2()
76 {
77 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
78 static int has_lock = 0;
79 static int data = 10000;
80
81 boost::static_mutex::scoped_lock guard(mut, false);
82 BOOST_CHECK(0 == guard.locked());
83 BOOST_CHECK(!guard);
84 guard.lock();
85 BOOST_CHECK(++has_lock == 1);
86 BOOST_CHECK(guard.locked());
87 BOOST_CHECK(guard);
88 bool result = (--data > 0) ? true : false;
89 BOOST_CHECK(--has_lock == 0);
90 guard.unlock();
91 BOOST_CHECK(0 == guard.locked());
92 BOOST_CHECK(!guard);
93 return result;
94 }
95
t3()96 bool t3()
97 {
98 static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
99 static int has_lock = 0;
100 static int data = 10000;
101
102 boost::static_mutex::scoped_lock guard(mut);
103 BOOST_CHECK(++has_lock == 1);
104 BOOST_CHECK(guard.locked());
105 BOOST_CHECK(guard);
106 bool result = (--data > 0) ? true : false;
107 BOOST_CHECK(--has_lock == 0);
108 return result;
109 }
110
111 // define their thread procs:
thread1_proc()112 void thread1_proc()
113 {
114 int cycles = 0;
115 while(!sufficient_time())
116 {
117 t1();
118 t2();
119 ++cycles;
120 }
121 print_cycles(cycles);
122 }
123
thread2_proc()124 void thread2_proc()
125 {
126 int cycles = 0;
127 while(!sufficient_time())
128 {
129 t2();
130 t3();
131 ++cycles;
132 }
133 print_cycles(cycles);
134 }
135
thread3_proc()136 void thread3_proc()
137 {
138 int cycles = 0;
139 while(!sufficient_time())
140 {
141 t1();
142 t3();
143 ++cycles;
144 }
145 print_cycles(cycles);
146 }
147
148 // make sure that at least one of our test proceedures
149 // is called during program startup:
150 struct startup1
151 {
startup1startup1152 startup1()
153 {
154 t1();
155 }
~startup1startup1156 ~startup1()
157 {
158 t1();
159 }
160 };
161
162 startup1 up1;
163
main()164 int main()
165 {
166 (void)up1;
167
168 std::list<boost::shared_ptr<boost::thread> > threads;
169 for(int i = 0; i < 2; ++i)
170 {
171 try{
172 threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread1_proc)));
173 }
174 catch(const std::exception& e)
175 {
176 std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
177 }
178 }
179 for(int i = 0; i < 2; ++i)
180 {
181 try{
182 threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread2_proc)));
183 }
184 catch(const std::exception& e)
185 {
186 std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
187 }
188 }
189 for(int i = 0; i < 2; ++i)
190 {
191 try{
192 threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread3_proc)));
193 }
194 catch(const std::exception& e)
195 {
196 std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
197 }
198 }
199
200 std::list<boost::shared_ptr<boost::thread> >::const_iterator a(threads.begin()), b(threads.end());
201 while(a != b)
202 {
203 (*a)->join();
204 ++a;
205 }
206
207 return total_failures;
208 }
209 #else
main()210 int main() {}
211 #endif
212