• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite
8 
9 #include <boost/config.hpp>
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 
16 #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value)    \
17     {                                                                \
18         boost::unique_lock<boost::mutex> lock(mutex_name);                  \
19         BOOST_CHECK_EQUAL(value,expected_value);                     \
20     }
21 
22 class simple_upgrade_thread
23 {
24     boost::shared_mutex& rwm;
25     boost::mutex& finish_mutex;
26     boost::mutex& unblocked_mutex;
27     unsigned& unblocked_count;
28 
29     void operator=(simple_upgrade_thread&);
30 
31 public:
simple_upgrade_thread(boost::shared_mutex & rwm_,boost::mutex & finish_mutex_,boost::mutex & unblocked_mutex_,unsigned & unblocked_count_)32     simple_upgrade_thread(boost::shared_mutex& rwm_,
33                           boost::mutex& finish_mutex_,
34                           boost::mutex& unblocked_mutex_,
35                           unsigned& unblocked_count_):
36         rwm(rwm_),finish_mutex(finish_mutex_),
37         unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
38     {}
39 
40 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
41     simple_upgrade_thread(simple_upgrade_thread const&) = default;
42 #endif
43 
operator ()()44     void operator()()
45     {
46         boost::upgrade_lock<boost::shared_mutex> lk(rwm);
47 
48         {
49             boost::unique_lock<boost::mutex> ulk(unblocked_mutex);
50             ++unblocked_count;
51         }
52 
53         boost::unique_lock<boost::mutex> flk(finish_mutex);
54     }
55 };
56 
57 
BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted)58 BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted)
59 {
60     unsigned const number_of_threads=2;
61 
62     boost::thread_group pool;
63 
64     boost::shared_mutex rw_mutex;
65     unsigned unblocked_count=0;
66     unsigned simultaneous_running_count=0;
67     unsigned max_simultaneous_running=0;
68     boost::mutex unblocked_count_mutex;
69     boost::condition_variable unblocked_condition;
70     boost::mutex finish_mutex;
71     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
72 
73     try
74     {
75         for(unsigned i=0;i<number_of_threads;++i)
76         {
77             pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
78                                                                                          finish_mutex,simultaneous_running_count,max_simultaneous_running));
79         }
80 
81         boost::thread::sleep(delay(1));
82 
83         CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
84 
85         finish_lock.unlock();
86 
87         pool.join_all();
88     }
89     catch(...)
90     {
91         pool.interrupt_all();
92         pool.join_all();
93         throw;
94     }
95 
96     CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
97     CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
98 }
99 
BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared)100 BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared)
101 {
102     boost::thread_group pool;
103 
104     boost::shared_mutex rw_mutex;
105     unsigned unblocked_count=0;
106     unsigned simultaneous_running_count=0;
107     unsigned max_simultaneous_running=0;
108     boost::mutex unblocked_count_mutex;
109     boost::condition_variable unblocked_condition;
110     boost::mutex finish_mutex;
111     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
112 
113     unsigned const reader_count=10;
114 
115     try
116     {
117         for(unsigned i=0;i<reader_count;++i)
118         {
119             pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
120                                                                                         finish_mutex,simultaneous_running_count,max_simultaneous_running));
121         }
122         boost::thread::sleep(delay(1));
123         pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
124                                                                                      finish_mutex,simultaneous_running_count,max_simultaneous_running));
125         {
126             boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
127             while(unblocked_count<(reader_count+1))
128             {
129                 unblocked_condition.wait(lk);
130             }
131         }
132         CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
133 
134         finish_lock.unlock();
135         pool.join_all();
136     }
137     catch(...)
138     {
139         pool.interrupt_all();
140         pool.join_all();
141         throw;
142     }
143 
144 
145     CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
146     CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
147 }
148 
BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade)149 BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade)
150 {
151     boost::shared_mutex mtx;
152     boost::upgrade_lock<boost::shared_mutex> l(mtx);
153     boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l);
154     BOOST_CHECK(ul.owns_lock());
155 }
156 
BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false)157 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false)
158 {
159 
160     boost::shared_mutex rw_mutex;
161     boost::mutex finish_mutex;
162     boost::mutex unblocked_mutex;
163     unsigned unblocked_count=0;
164     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
165     boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
166     boost::this_thread::sleep(boost::posix_time::seconds(1));
167     CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
168 
169     bool const try_succeeded=rw_mutex.try_lock_shared();
170     BOOST_CHECK(!try_succeeded);
171     if(try_succeeded)
172     {
173         rw_mutex.unlock_shared();
174     }
175 
176     finish_lock.unlock();
177     writer.join();
178 }
179 
BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false)180 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false)
181 {
182 
183     boost::shared_mutex rw_mutex;
184     boost::mutex finish_mutex;
185     boost::mutex unblocked_mutex;
186     unsigned unblocked_count=0;
187     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
188     boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
189     boost::this_thread::sleep(boost::posix_time::seconds(1));
190     CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
191 
192     bool const try_succeeded=rw_mutex.try_lock_upgrade();
193     BOOST_CHECK(!try_succeeded);
194     if(try_succeeded)
195     {
196         rw_mutex.unlock_upgrade();
197     }
198 
199     finish_lock.unlock();
200     writer.join();
201 }
202 
BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true)203 BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true)
204 {
205     boost::shared_mutex rw_mutex;
206     bool const try_succeeded=rw_mutex.try_lock_shared();
207     BOOST_CHECK(try_succeeded);
208     if(try_succeeded)
209     {
210         rw_mutex.unlock_shared();
211     }
212 }
213 
BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true)214 BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true)
215 {
216     boost::shared_mutex rw_mutex;
217     bool const try_succeeded=rw_mutex.try_lock_upgrade();
218     BOOST_CHECK(try_succeeded);
219     if(try_succeeded)
220     {
221         rw_mutex.unlock_upgrade();
222     }
223 }
224 
BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true)225 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true)
226 {
227 
228     boost::shared_mutex rw_mutex;
229     boost::mutex finish_mutex;
230     boost::mutex unblocked_mutex;
231     unsigned unblocked_count=0;
232     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
233     boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
234     boost::thread::sleep(delay(1));
235     CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
236 
237     bool const try_succeeded=rw_mutex.try_lock_shared();
238     BOOST_CHECK(try_succeeded);
239     if(try_succeeded)
240     {
241         rw_mutex.unlock_shared();
242     }
243 
244     finish_lock.unlock();
245     writer.join();
246 }
247 
BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true)248 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true)
249 {
250 
251     boost::shared_mutex rw_mutex;
252     boost::mutex finish_mutex;
253     boost::mutex unblocked_mutex;
254     unsigned unblocked_count=0;
255     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
256     boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
257     boost::thread::sleep(delay(1));
258     CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
259 
260     bool const try_succeeded=rw_mutex.try_lock_upgrade();
261     BOOST_CHECK(try_succeeded);
262     if(try_succeeded)
263     {
264         rw_mutex.unlock_upgrade();
265     }
266 
267     finish_lock.unlock();
268     writer.join();
269 }
270 
BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false)271 BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false)
272 {
273 
274     boost::shared_mutex rw_mutex;
275     boost::mutex finish_mutex;
276     boost::mutex unblocked_mutex;
277     unsigned unblocked_count=0;
278     boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
279     boost::thread writer(simple_upgrade_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
280     boost::this_thread::sleep(boost::posix_time::seconds(1));
281     CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
282 
283     bool const try_succeeded=rw_mutex.try_lock_upgrade();
284     BOOST_CHECK(!try_succeeded);
285     if(try_succeeded)
286     {
287         rw_mutex.unlock_upgrade();
288     }
289 
290     finish_lock.unlock();
291     writer.join();
292 }
293 
294 
295