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"
15#include <iostream>
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
23BOOST_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(threadfunc: 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(m&: 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
71BOOST_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(threadfunc: 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(xt: delay(secs: 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
114BOOST_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(threadfunc: 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(m&: lk);
138 }
139 }
140 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
141 pool.create_thread(threadfunc: 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(xt: delay(secs: 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
161BOOST_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(threadfunc: 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(xt: delay(secs: 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(m&: 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
213BOOST_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(threadfunc: 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(xt: delay(secs: 1));
242 for(unsigned i=0;i<writer_count;++i)
243 {
244 pool.create_thread(threadfunc: 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(m&: lk);
252 }
253 }
254 boost::thread::sleep(xt: delay(secs: 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(m&: 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}
282

source code of boost/libs/thread/test/test_shared_mutex.cpp