]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright 2006-7 Anthony Williams |
2 | // Distributed under the Boost Software License, Version 1.0. (See | |
3 | // accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #define BOOST_THREAD_VERSION 2 | |
7 | #define BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
8 | #define BOOST_TEST_MODULE Boost.Threads: shared_mutex test suite | |
9 | ||
10 | #include <boost/test/unit_test.hpp> | |
11 | #include <boost/thread/thread.hpp> | |
12 | #include <boost/thread/xtime.hpp> | |
13 | #include "./util.inl" | |
14 | #include "./shared_mutex_locking_thread.hpp" | |
b32b8144 | 15 | #include <iostream> |
7c673cae FG |
16 | |
17 | #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ | |
18 | { \ | |
19 | boost::unique_lock<boost::mutex> lock(mutex_name); \ | |
20 | BOOST_CHECK_EQUAL(value,expected_value); \ | |
21 | } | |
22 | ||
23 | BOOST_AUTO_TEST_CASE(test_multiple_readers) | |
24 | { | |
25 | std::cout << __LINE__ << std::endl; | |
26 | unsigned const number_of_threads=10; | |
27 | ||
28 | boost::thread_group pool; | |
29 | ||
30 | boost::shared_mutex rw_mutex; | |
31 | unsigned unblocked_count=0; | |
32 | unsigned simultaneous_running_count=0; | |
33 | unsigned max_simultaneous_running=0; | |
34 | boost::mutex unblocked_count_mutex; | |
35 | boost::condition_variable unblocked_condition; | |
36 | boost::mutex finish_mutex; | |
37 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); | |
38 | ||
39 | try | |
40 | { | |
41 | for(unsigned i=0;i<number_of_threads;++i) | |
42 | { | |
43 | pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
44 | finish_mutex,simultaneous_running_count,max_simultaneous_running)); | |
45 | } | |
46 | ||
47 | { | |
48 | boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); | |
49 | while(unblocked_count<number_of_threads) | |
50 | { | |
51 | unblocked_condition.wait(lk); | |
52 | } | |
53 | } | |
54 | ||
55 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); | |
56 | ||
57 | finish_lock.unlock(); | |
58 | ||
59 | pool.join_all(); | |
60 | } | |
61 | catch(...) | |
62 | { | |
63 | pool.interrupt_all(); | |
64 | pool.join_all(); | |
65 | throw; | |
66 | } | |
67 | ||
68 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads); | |
69 | } | |
70 | ||
71 | BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted) | |
72 | { | |
73 | std::cout << __LINE__ << std::endl; | |
74 | unsigned const number_of_threads=10; | |
75 | ||
76 | boost::thread_group pool; | |
77 | ||
78 | boost::shared_mutex rw_mutex; | |
79 | unsigned unblocked_count=0; | |
80 | unsigned simultaneous_running_count=0; | |
81 | unsigned max_simultaneous_running=0; | |
82 | boost::mutex unblocked_count_mutex; | |
83 | boost::condition_variable unblocked_condition; | |
84 | boost::mutex finish_mutex; | |
85 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); | |
86 | ||
87 | try | |
88 | { | |
89 | for(unsigned i=0;i<number_of_threads;++i) | |
90 | { | |
91 | pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
92 | finish_mutex,simultaneous_running_count,max_simultaneous_running)); | |
93 | } | |
94 | ||
95 | boost::thread::sleep(delay(2)); | |
96 | ||
97 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); | |
98 | ||
99 | finish_lock.unlock(); | |
100 | ||
101 | pool.join_all(); | |
102 | } | |
103 | catch(...) | |
104 | { | |
105 | pool.interrupt_all(); | |
106 | pool.join_all(); | |
107 | throw; | |
108 | } | |
109 | ||
110 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); | |
111 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); | |
112 | } | |
113 | ||
114 | BOOST_AUTO_TEST_CASE(test_reader_blocks_writer) | |
115 | { | |
116 | std::cout << __LINE__ << std::endl; | |
117 | boost::thread_group pool; | |
118 | ||
119 | boost::shared_mutex rw_mutex; | |
120 | unsigned unblocked_count=0; | |
121 | unsigned simultaneous_running_count=0; | |
122 | unsigned max_simultaneous_running=0; | |
123 | boost::mutex unblocked_count_mutex; | |
124 | boost::condition_variable unblocked_condition; | |
125 | boost::mutex finish_mutex; | |
126 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); | |
127 | ||
128 | try | |
129 | { | |
130 | ||
131 | pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
132 | finish_mutex,simultaneous_running_count,max_simultaneous_running)); | |
133 | { | |
134 | boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); | |
135 | while(unblocked_count<1) | |
136 | { | |
137 | unblocked_condition.wait(lk); | |
138 | } | |
139 | } | |
140 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); | |
141 | pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
142 | finish_mutex,simultaneous_running_count,max_simultaneous_running)); | |
143 | boost::thread::sleep(delay(1)); | |
144 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); | |
145 | ||
146 | finish_lock.unlock(); | |
147 | ||
148 | pool.join_all(); | |
149 | } | |
150 | catch(...) | |
151 | { | |
152 | pool.interrupt_all(); | |
153 | pool.join_all(); | |
154 | throw; | |
155 | } | |
156 | ||
157 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U); | |
158 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); | |
159 | } | |
160 | ||
161 | BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers) | |
162 | { | |
163 | std::cout << __LINE__ << std::endl; | |
164 | boost::thread_group pool; | |
165 | ||
166 | boost::shared_mutex rw_mutex; | |
167 | boost::unique_lock<boost::shared_mutex> write_lock(rw_mutex); | |
168 | unsigned unblocked_count=0; | |
169 | unsigned simultaneous_running_count=0; | |
170 | unsigned max_simultaneous_running=0; | |
171 | boost::mutex unblocked_count_mutex; | |
172 | boost::condition_variable unblocked_condition; | |
173 | boost::mutex finish_mutex; | |
174 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); | |
175 | ||
176 | unsigned const reader_count=10; | |
177 | ||
178 | try | |
179 | { | |
180 | for(unsigned i=0;i<reader_count;++i) | |
181 | { | |
182 | pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
183 | finish_mutex,simultaneous_running_count,max_simultaneous_running)); | |
184 | } | |
185 | boost::thread::sleep(delay(1)); | |
186 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,0U); | |
187 | ||
188 | write_lock.unlock(); | |
189 | ||
190 | { | |
191 | boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); | |
192 | while(unblocked_count<reader_count) | |
193 | { | |
194 | unblocked_condition.wait(lk); | |
195 | } | |
196 | } | |
197 | ||
198 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); | |
199 | ||
200 | finish_lock.unlock(); | |
201 | pool.join_all(); | |
202 | } | |
203 | catch(...) | |
204 | { | |
205 | pool.interrupt_all(); | |
206 | pool.join_all(); | |
207 | throw; | |
208 | } | |
209 | ||
210 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count); | |
211 | } | |
212 | ||
213 | BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer) | |
214 | { | |
215 | std::cout << __LINE__ << std::endl; | |
216 | boost::thread_group pool; | |
217 | ||
218 | boost::shared_mutex rw_mutex; | |
219 | unsigned unblocked_count=0; | |
220 | unsigned simultaneous_running_readers=0; | |
221 | unsigned max_simultaneous_readers=0; | |
222 | unsigned simultaneous_running_writers=0; | |
223 | unsigned max_simultaneous_writers=0; | |
224 | boost::mutex unblocked_count_mutex; | |
225 | boost::condition_variable unblocked_condition; | |
226 | boost::mutex finish_reading_mutex; | |
227 | boost::unique_lock<boost::mutex> finish_reading_lock(finish_reading_mutex); | |
228 | boost::mutex finish_writing_mutex; | |
229 | boost::unique_lock<boost::mutex> finish_writing_lock(finish_writing_mutex); | |
230 | ||
231 | unsigned const reader_count=10; | |
232 | unsigned const writer_count=10; | |
233 | ||
234 | try | |
235 | { | |
236 | for(unsigned i=0;i<reader_count;++i) | |
237 | { | |
238 | pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
239 | finish_reading_mutex,simultaneous_running_readers,max_simultaneous_readers)); | |
240 | } | |
241 | boost::thread::sleep(delay(1)); | |
242 | for(unsigned i=0;i<writer_count;++i) | |
243 | { | |
244 | pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, | |
245 | finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers)); | |
246 | } | |
247 | { | |
248 | boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); | |
249 | while(unblocked_count<reader_count) | |
250 | { | |
251 | unblocked_condition.wait(lk); | |
252 | } | |
253 | } | |
254 | boost::thread::sleep(delay(1)); | |
255 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); | |
256 | ||
257 | finish_reading_lock.unlock(); | |
258 | ||
259 | { | |
260 | boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); | |
261 | while(unblocked_count<(reader_count+1)) | |
262 | { | |
263 | unblocked_condition.wait(lk); | |
264 | } | |
265 | } | |
266 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); | |
267 | ||
268 | finish_writing_lock.unlock(); | |
269 | pool.join_all(); | |
270 | } | |
271 | catch(...) | |
272 | { | |
273 | pool.interrupt_all(); | |
274 | pool.join_all(); | |
275 | throw; | |
276 | } | |
277 | ||
278 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count); | |
279 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count); | |
280 | CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u); | |
281 | } |