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_locks_chrono test suite |
8 | |
9 | #include <boost/test/unit_test.hpp> |
10 | #include <boost/thread/thread.hpp> |
11 | #include <boost/thread/shared_mutex.hpp> |
12 | #include "./util.inl" |
13 | #include "./shared_mutex_locking_thread.hpp" |
14 | |
15 | #if defined BOOST_THREAD_USES_CHRONO |
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 | |
24 | BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held) |
25 | { |
26 | boost::shared_mutex rw_mutex; |
27 | boost::mutex finish_mutex; |
28 | boost::mutex unblocked_mutex; |
29 | unsigned unblocked_count=0; |
30 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); |
31 | boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); |
32 | boost::this_thread::sleep_for(d: boost::chrono::seconds(1)); |
33 | CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); |
34 | |
35 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
36 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
37 | boost::chrono::milliseconds const timeout_resolution(50); |
38 | bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(abs_time: timeout); |
39 | BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); |
40 | BOOST_CHECK(!timed_lock_succeeded); |
41 | if(timed_lock_succeeded) |
42 | { |
43 | rw_mutex.unlock_shared(); |
44 | } |
45 | |
46 | boost::chrono::milliseconds const wait_duration(500); |
47 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
48 | timed_lock_succeeded=rw_mutex.try_lock_shared_for(rel_time: wait_duration); |
49 | BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); |
50 | BOOST_CHECK(!timed_lock_succeeded); |
51 | if(timed_lock_succeeded) |
52 | { |
53 | rw_mutex.unlock_shared(); |
54 | } |
55 | |
56 | finish_lock.unlock(); |
57 | writer.join(); |
58 | } |
59 | |
60 | BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held) |
61 | { |
62 | boost::shared_mutex rw_mutex; |
63 | boost::mutex finish_mutex; |
64 | boost::mutex unblocked_mutex; |
65 | |
66 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
67 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
68 | bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(abs_time: timeout); |
69 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); |
70 | BOOST_CHECK(timed_lock_succeeded); |
71 | if(timed_lock_succeeded) |
72 | { |
73 | rw_mutex.unlock_shared(); |
74 | } |
75 | |
76 | boost::chrono::milliseconds const wait_duration(500); |
77 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
78 | timed_lock_succeeded=rw_mutex.try_lock_shared_for(rel_time: wait_duration); |
79 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); |
80 | BOOST_CHECK(timed_lock_succeeded); |
81 | if(timed_lock_succeeded) |
82 | { |
83 | rw_mutex.unlock_shared(); |
84 | } |
85 | |
86 | } |
87 | |
88 | BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held) |
89 | { |
90 | boost::shared_mutex rw_mutex; |
91 | boost::mutex finish_mutex; |
92 | boost::mutex unblocked_mutex; |
93 | unsigned unblocked_count=0; |
94 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); |
95 | boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); |
96 | boost::this_thread::sleep_for(d: boost::chrono::seconds(1)); |
97 | CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); |
98 | |
99 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
100 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
101 | bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(abs_time: timeout); |
102 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); |
103 | BOOST_CHECK(timed_lock_succeeded); |
104 | if(timed_lock_succeeded) |
105 | { |
106 | rw_mutex.unlock_shared(); |
107 | } |
108 | |
109 | boost::chrono::milliseconds const wait_duration(500); |
110 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
111 | timed_lock_succeeded=rw_mutex.try_lock_shared_for(rel_time: wait_duration); |
112 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); |
113 | BOOST_CHECK(timed_lock_succeeded); |
114 | if(timed_lock_succeeded) |
115 | { |
116 | rw_mutex.unlock_shared(); |
117 | } |
118 | |
119 | finish_lock.unlock(); |
120 | reader.join(); |
121 | } |
122 | |
123 | BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held) |
124 | { |
125 | boost::shared_mutex rw_mutex; |
126 | boost::mutex finish_mutex; |
127 | boost::mutex unblocked_mutex; |
128 | unsigned unblocked_count=0; |
129 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); |
130 | boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); |
131 | boost::this_thread::sleep_for(d: boost::chrono::seconds(1)); |
132 | CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); |
133 | |
134 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
135 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
136 | boost::chrono::milliseconds const timeout_resolution(50); |
137 | bool timed_lock_succeeded=rw_mutex.try_lock_until(abs_time: timeout); |
138 | BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); |
139 | BOOST_CHECK(!timed_lock_succeeded); |
140 | if(timed_lock_succeeded) |
141 | { |
142 | rw_mutex.unlock(); |
143 | } |
144 | |
145 | boost::chrono::milliseconds const wait_duration(500); |
146 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
147 | timed_lock_succeeded=rw_mutex.try_lock_for(rel_time: wait_duration); |
148 | BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); |
149 | BOOST_CHECK(!timed_lock_succeeded); |
150 | if(timed_lock_succeeded) |
151 | { |
152 | rw_mutex.unlock(); |
153 | } |
154 | |
155 | finish_lock.unlock(); |
156 | writer.join(); |
157 | } |
158 | |
159 | BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held) |
160 | { |
161 | boost::shared_mutex rw_mutex; |
162 | boost::mutex finish_mutex; |
163 | boost::mutex unblocked_mutex; |
164 | |
165 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
166 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
167 | bool timed_lock_succeeded=rw_mutex.try_lock_until(abs_time: timeout); |
168 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); |
169 | BOOST_CHECK(timed_lock_succeeded); |
170 | if(timed_lock_succeeded) |
171 | { |
172 | rw_mutex.unlock(); |
173 | } |
174 | |
175 | boost::chrono::milliseconds const wait_duration(500); |
176 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
177 | timed_lock_succeeded=rw_mutex.try_lock_for(rel_time: wait_duration); |
178 | BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); |
179 | BOOST_CHECK(timed_lock_succeeded); |
180 | if(timed_lock_succeeded) |
181 | { |
182 | rw_mutex.unlock(); |
183 | } |
184 | |
185 | } |
186 | |
187 | BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held) |
188 | { |
189 | boost::shared_mutex rw_mutex; |
190 | boost::mutex finish_mutex; |
191 | boost::mutex unblocked_mutex; |
192 | unsigned unblocked_count=0; |
193 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); |
194 | boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); |
195 | boost::this_thread::sleep_for(d: boost::chrono::seconds(1)); |
196 | CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); |
197 | |
198 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
199 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
200 | boost::chrono::milliseconds const timeout_resolution(50); |
201 | bool timed_lock_succeeded=rw_mutex.try_lock_until(abs_time: timeout); |
202 | BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); |
203 | BOOST_CHECK(!timed_lock_succeeded); |
204 | if(timed_lock_succeeded) |
205 | { |
206 | rw_mutex.unlock(); |
207 | } |
208 | |
209 | boost::chrono::milliseconds const wait_duration(500); |
210 | boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; |
211 | timed_lock_succeeded=rw_mutex.try_lock_for(rel_time: wait_duration); |
212 | BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); |
213 | BOOST_CHECK(!timed_lock_succeeded); |
214 | if(timed_lock_succeeded) |
215 | { |
216 | rw_mutex.unlock(); |
217 | } |
218 | |
219 | finish_lock.unlock(); |
220 | reader.join(); |
221 | } |
222 | |
223 | BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held) |
224 | { |
225 | boost::shared_mutex rw_mutex; |
226 | boost::mutex finish_mutex; |
227 | boost::mutex unblocked_mutex; |
228 | unsigned unblocked_count=0; |
229 | boost::unique_lock<boost::mutex> finish_lock(finish_mutex); |
230 | boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); |
231 | boost::this_thread::sleep_for(d: boost::chrono::seconds(1)); |
232 | CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); |
233 | |
234 | boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); |
235 | boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); |
236 | bool timed_lock_succeeded=rw_mutex.try_lock_until(abs_time: timeout); |
237 | BOOST_CHECK(!timed_lock_succeeded); |
238 | if(timed_lock_succeeded) |
239 | { |
240 | rw_mutex.unlock(); |
241 | } |
242 | |
243 | boost::chrono::milliseconds const wait_duration(500); |
244 | timed_lock_succeeded=rw_mutex.try_lock_shared_for(rel_time: wait_duration); |
245 | BOOST_CHECK(timed_lock_succeeded); |
246 | if(timed_lock_succeeded) |
247 | { |
248 | rw_mutex.unlock_shared(); |
249 | } |
250 | |
251 | finish_lock.unlock(); |
252 | reader.join(); |
253 | } |
254 | |
255 | #else |
256 | #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" |
257 | #endif |
258 | |
259 | |
260 | |