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)
6 #define BOOST_THREAD_VERSION 2
7 #define BOOST_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite
9 #include <boost/test/unit_test.hpp>
10 #include <boost/thread/thread.hpp>
11 #include <boost/thread/xtime.hpp>
13 #include "./shared_mutex_locking_thread.hpp"
15 #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
17 boost::unique_lock<boost::mutex> lock(mutex_name); \
18 BOOST_CHECK_EQUAL(value,expected_value); \
21 class simple_upgrade_thread
23 boost::shared_mutex
& rwm
;
24 boost::mutex
& finish_mutex
;
25 boost::mutex
& unblocked_mutex
;
26 unsigned& unblocked_count
;
28 void operator=(simple_upgrade_thread
&);
31 simple_upgrade_thread(boost::shared_mutex
& rwm_
,
32 boost::mutex
& finish_mutex_
,
33 boost::mutex
& unblocked_mutex_
,
34 unsigned& unblocked_count_
):
35 rwm(rwm_
),finish_mutex(finish_mutex_
),
36 unblocked_mutex(unblocked_mutex_
),unblocked_count(unblocked_count_
)
41 boost::upgrade_lock
<boost::shared_mutex
> lk(rwm
);
44 boost::unique_lock
<boost::mutex
> ulk(unblocked_mutex
);
48 boost::unique_lock
<boost::mutex
> flk(finish_mutex
);
53 BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted
)
55 unsigned const number_of_threads
=2;
57 boost::thread_group pool
;
59 boost::shared_mutex rw_mutex
;
60 unsigned unblocked_count
=0;
61 unsigned simultaneous_running_count
=0;
62 unsigned max_simultaneous_running
=0;
63 boost::mutex unblocked_count_mutex
;
64 boost::condition_variable unblocked_condition
;
65 boost::mutex finish_mutex
;
66 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
70 for(unsigned i
=0;i
<number_of_threads
;++i
)
72 pool
.create_thread(locking_thread
<boost::upgrade_lock
<boost::shared_mutex
> >(rw_mutex
,unblocked_count
,unblocked_count_mutex
,unblocked_condition
,
73 finish_mutex
,simultaneous_running_count
,max_simultaneous_running
));
76 boost::thread::sleep(delay(1));
78 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,unblocked_count
,1U);
91 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,unblocked_count
,number_of_threads
);
92 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,max_simultaneous_running
,1u);
95 BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared
)
97 boost::thread_group pool
;
99 boost::shared_mutex rw_mutex
;
100 unsigned unblocked_count
=0;
101 unsigned simultaneous_running_count
=0;
102 unsigned max_simultaneous_running
=0;
103 boost::mutex unblocked_count_mutex
;
104 boost::condition_variable unblocked_condition
;
105 boost::mutex finish_mutex
;
106 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
108 unsigned const reader_count
=10;
112 for(unsigned i
=0;i
<reader_count
;++i
)
114 pool
.create_thread(locking_thread
<boost::shared_lock
<boost::shared_mutex
> >(rw_mutex
,unblocked_count
,unblocked_count_mutex
,unblocked_condition
,
115 finish_mutex
,simultaneous_running_count
,max_simultaneous_running
));
117 boost::thread::sleep(delay(1));
118 pool
.create_thread(locking_thread
<boost::upgrade_lock
<boost::shared_mutex
> >(rw_mutex
,unblocked_count
,unblocked_count_mutex
,unblocked_condition
,
119 finish_mutex
,simultaneous_running_count
,max_simultaneous_running
));
121 boost::unique_lock
<boost::mutex
> lk(unblocked_count_mutex
);
122 while(unblocked_count
<(reader_count
+1))
124 unblocked_condition
.wait(lk
);
127 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,unblocked_count
,reader_count
+1);
129 finish_lock
.unlock();
134 pool
.interrupt_all();
140 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,unblocked_count
,reader_count
+1);
141 CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex
,max_simultaneous_running
,reader_count
+1);
144 BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade
)
146 boost::shared_mutex mtx
;
147 boost::upgrade_lock
<boost::shared_mutex
> l(mtx
);
148 boost::upgrade_to_unique_lock
<boost::shared_mutex
> ul(l
);
149 BOOST_CHECK(ul
.owns_lock());
152 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false
)
155 boost::shared_mutex rw_mutex
;
156 boost::mutex finish_mutex
;
157 boost::mutex unblocked_mutex
;
158 unsigned unblocked_count
=0;
159 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
160 boost::thread
writer(simple_writing_thread(rw_mutex
,finish_mutex
,unblocked_mutex
,unblocked_count
));
161 boost::this_thread::sleep(boost::posix_time::seconds(1));
162 CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex
,unblocked_count
,1u);
164 bool const try_succeeded
=rw_mutex
.try_lock_shared();
165 BOOST_CHECK(!try_succeeded
);
168 rw_mutex
.unlock_shared();
171 finish_lock
.unlock();
175 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false
)
178 boost::shared_mutex rw_mutex
;
179 boost::mutex finish_mutex
;
180 boost::mutex unblocked_mutex
;
181 unsigned unblocked_count
=0;
182 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
183 boost::thread
writer(simple_writing_thread(rw_mutex
,finish_mutex
,unblocked_mutex
,unblocked_count
));
184 boost::this_thread::sleep(boost::posix_time::seconds(1));
185 CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex
,unblocked_count
,1u);
187 bool const try_succeeded
=rw_mutex
.try_lock_upgrade();
188 BOOST_CHECK(!try_succeeded
);
191 rw_mutex
.unlock_upgrade();
194 finish_lock
.unlock();
198 BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true
)
200 boost::shared_mutex rw_mutex
;
201 bool const try_succeeded
=rw_mutex
.try_lock_shared();
202 BOOST_CHECK(try_succeeded
);
205 rw_mutex
.unlock_shared();
209 BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true
)
211 boost::shared_mutex rw_mutex
;
212 bool const try_succeeded
=rw_mutex
.try_lock_upgrade();
213 BOOST_CHECK(try_succeeded
);
216 rw_mutex
.unlock_upgrade();
220 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true
)
223 boost::shared_mutex rw_mutex
;
224 boost::mutex finish_mutex
;
225 boost::mutex unblocked_mutex
;
226 unsigned unblocked_count
=0;
227 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
228 boost::thread
writer(simple_reading_thread(rw_mutex
,finish_mutex
,unblocked_mutex
,unblocked_count
));
229 boost::thread::sleep(delay(1));
230 CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex
,unblocked_count
,1u);
232 bool const try_succeeded
=rw_mutex
.try_lock_shared();
233 BOOST_CHECK(try_succeeded
);
236 rw_mutex
.unlock_shared();
239 finish_lock
.unlock();
243 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true
)
246 boost::shared_mutex rw_mutex
;
247 boost::mutex finish_mutex
;
248 boost::mutex unblocked_mutex
;
249 unsigned unblocked_count
=0;
250 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
251 boost::thread
writer(simple_reading_thread(rw_mutex
,finish_mutex
,unblocked_mutex
,unblocked_count
));
252 boost::thread::sleep(delay(1));
253 CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex
,unblocked_count
,1u);
255 bool const try_succeeded
=rw_mutex
.try_lock_upgrade();
256 BOOST_CHECK(try_succeeded
);
259 rw_mutex
.unlock_upgrade();
262 finish_lock
.unlock();
266 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false
)
269 boost::shared_mutex rw_mutex
;
270 boost::mutex finish_mutex
;
271 boost::mutex unblocked_mutex
;
272 unsigned unblocked_count
=0;
273 boost::unique_lock
<boost::mutex
> finish_lock(finish_mutex
);
274 boost::thread
writer(simple_upgrade_thread(rw_mutex
,finish_mutex
,unblocked_mutex
,unblocked_count
));
275 boost::this_thread::sleep(boost::posix_time::seconds(1));
276 CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex
,unblocked_count
,1u);
278 bool const try_succeeded
=rw_mutex
.try_lock_upgrade();
279 BOOST_CHECK(!try_succeeded
);
282 rw_mutex
.unlock_upgrade();
285 finish_lock
.unlock();