• 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_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 
BOOST_AUTO_TEST_CASE(test_multiple_readers)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 
BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted)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 
BOOST_AUTO_TEST_CASE(test_reader_blocks_writer)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 
BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers)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 
BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer)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 }
282