]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/test/test_lock_concept.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / thread / test / test_lock_concept.cpp
1 // (C) Copyright 2006-8 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: lock_concept test suite
8
9 #include <boost/test/unit_test.hpp>
10 #include <boost/test/test_case_template.hpp>
11 #include <boost/mpl/vector.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/lock_types.hpp>
14 #include <boost/thread/shared_mutex.hpp>
15 #include <boost/thread/thread_only.hpp>
16 #include <boost/thread/recursive_mutex.hpp>
17 #include <boost/thread/condition_variable.hpp>
18
19 template<typename Mutex,typename Lock>
20 struct test_initially_locked
21 {
22 void operator()() const
23 {
24 Mutex m;
25 Lock lock(m);
26
27 BOOST_CHECK(lock);
28 BOOST_CHECK(lock.owns_lock());
29 }
30 };
31
32 template<typename Mutex,typename Lock>
33 struct test_initially_unlocked_if_other_thread_has_lock
34 {
35 Mutex m;
36 boost::mutex done_mutex;
37 bool done;
38 bool locked;
39 boost::condition_variable done_cond;
40
41 test_initially_unlocked_if_other_thread_has_lock():
42 done(false),locked(false)
43 {}
44
45 void locking_thread()
46 {
47 Lock lock(m);
48
49 boost::lock_guard<boost::mutex> lk(done_mutex);
50 locked=lock.owns_lock();
51 done=true;
52 done_cond.notify_one();
53 }
54
55 bool is_done() const
56 {
57 return done;
58 }
59
60
61 void operator()()
62 {
63 Lock lock(m);
64
65 typedef test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock> this_type;
66
67 boost::thread t(&this_type::locking_thread,this);
68
69 try
70 {
71 {
72 boost::unique_lock<boost::mutex> lk(done_mutex);
73 BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
74 boost::bind(&this_type::is_done,this)));
75 BOOST_CHECK(!locked);
76 }
77
78 lock.unlock();
79 t.join();
80 }
81 catch(...)
82 {
83 lock.unlock();
84 t.join();
85 throw;
86 }
87 }
88 };
89
90 template<typename Mutex,typename Lock>
91 struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
92 {
93 Mutex m;
94 boost::mutex done_mutex;
95 bool done;
96 bool locked;
97 boost::condition_variable done_cond;
98
99 test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock():
100 done(false),locked(false)
101 {}
102
103 void locking_thread()
104 {
105 Lock lock(m,boost::try_to_lock);
106
107 boost::lock_guard<boost::mutex> lk(done_mutex);
108 locked=lock.owns_lock();
109 done=true;
110 done_cond.notify_one();
111 }
112
113 bool is_done() const
114 {
115 return done;
116 }
117
118
119 void operator()()
120 {
121 boost::unique_lock<Mutex> lock(m);
122
123 typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock> this_type;
124
125 boost::thread t(&this_type::locking_thread,this);
126
127 try
128 {
129 {
130 boost::unique_lock<boost::mutex> lk(done_mutex);
131 BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
132 boost::bind(&this_type::is_done,this)));
133 BOOST_CHECK(!locked);
134 }
135
136 lock.unlock();
137 t.join();
138 }
139 catch(...)
140 {
141 lock.unlock();
142 t.join();
143 throw;
144 }
145 }
146 };
147
148 template<typename Mutex,typename Lock>
149 struct test_initially_locked_if_other_thread_has_shared_lock
150 {
151 Mutex m;
152 boost::mutex done_mutex;
153 bool done;
154 bool locked;
155 boost::condition_variable done_cond;
156
157 test_initially_locked_if_other_thread_has_shared_lock():
158 done(false),locked(false)
159 {}
160
161 void locking_thread()
162 {
163 Lock lock(m);
164
165 boost::lock_guard<boost::mutex> lk(done_mutex);
166 locked=lock.owns_lock();
167 done=true;
168 done_cond.notify_one();
169 }
170
171 bool is_done() const
172 {
173 return done;
174 }
175
176
177 void operator()()
178 {
179 boost::shared_lock<Mutex> lock(m);
180
181 typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock> this_type;
182
183 boost::thread t(&this_type::locking_thread,this);
184
185 try
186 {
187 {
188 boost::unique_lock<boost::mutex> lk(done_mutex);
189 BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
190 boost::bind(&this_type::is_done,this)));
191 BOOST_CHECK(locked);
192 }
193
194 lock.unlock();
195 t.join();
196 }
197 catch(...)
198 {
199 lock.unlock();
200 t.join();
201 throw;
202 }
203 }
204 };
205
206 template<typename Mutex,typename Lock>
207 struct test_initially_unlocked_with_defer_lock_parameter
208 {
209 void operator()() const
210 {
211 Mutex m;
212 Lock lock(m,boost::defer_lock);
213
214 BOOST_CHECK(!lock);
215 BOOST_CHECK(!lock.owns_lock());
216 }
217 };
218
219 template<typename Mutex,typename Lock>
220 struct test_initially_locked_with_adopt_lock_parameter
221 {
222 void operator()() const
223 {
224 Mutex m;
225 m.lock();
226 Lock lock(m,boost::adopt_lock);
227
228 BOOST_CHECK(lock);
229 BOOST_CHECK(lock.owns_lock());
230 }
231 };
232 template<typename Mutex,typename Lock>
233 struct test_initially_lock_shared_with_adopt_lock_parameter
234 {
235 void operator()() const
236 {
237 Mutex m;
238 m.lock_shared();
239 Lock lock(m,boost::adopt_lock);
240
241 BOOST_CHECK(lock);
242 BOOST_CHECK(lock.owns_lock());
243 }
244 };
245
246
247 template<typename Mutex,typename Lock>
248 struct test_unlocked_after_unlock_called
249 {
250 void operator()() const
251 {
252 Mutex m;
253 Lock lock(m);
254 lock.unlock();
255 BOOST_CHECK(!lock);
256 BOOST_CHECK(!lock.owns_lock());
257 }
258 };
259
260 template<typename Mutex,typename Lock>
261 struct test_locked_after_lock_called
262 {
263 void operator()() const
264 {
265 Mutex m;
266 Lock lock(m,boost::defer_lock);
267 lock.lock();
268 BOOST_CHECK(lock);
269 BOOST_CHECK(lock.owns_lock());
270 }
271 };
272
273 template<typename Mutex,typename Lock>
274 struct test_locked_after_try_lock_called
275 {
276 void operator()() const
277 {
278 Mutex m;
279 Lock lock(m,boost::defer_lock);
280 lock.try_lock();
281 BOOST_CHECK(lock);
282 BOOST_CHECK(lock.owns_lock());
283 }
284 };
285
286 template<typename Mutex,typename Lock>
287 struct test_unlocked_after_try_lock_if_other_thread_has_lock
288 {
289 Mutex m;
290 boost::mutex done_mutex;
291 bool done;
292 bool locked;
293 boost::condition_variable done_cond;
294
295 test_unlocked_after_try_lock_if_other_thread_has_lock():
296 done(false),locked(false)
297 {}
298
299 void locking_thread()
300 {
301 Lock lock(m,boost::defer_lock);
302
303 boost::lock_guard<boost::mutex> lk(done_mutex);
304 locked=lock.owns_lock();
305 done=true;
306 done_cond.notify_one();
307 }
308
309 bool is_done() const
310 {
311 return done;
312 }
313
314
315 void operator()()
316 {
317 Lock lock(m);
318
319 typedef test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock> this_type;
320
321 boost::thread t(&this_type::locking_thread,this);
322
323 try
324 {
325 {
326 boost::unique_lock<boost::mutex> lk(done_mutex);
327 BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
328 boost::bind(&this_type::is_done,this)));
329 BOOST_CHECK(!locked);
330 }
331
332 lock.unlock();
333 t.join();
334 }
335 catch(...)
336 {
337 lock.unlock();
338 t.join();
339 throw;
340 }
341 }
342 };
343
344 template<typename Mutex,typename Lock>
345 struct test_throws_if_lock_called_when_already_locked
346 {
347 void operator()() const
348 {
349 Mutex m;
350 Lock lock(m);
351
352 BOOST_CHECK_THROW( lock.lock(), boost::lock_error );
353 }
354 };
355
356 template<typename Mutex,typename Lock>
357 struct test_throws_if_try_lock_called_when_already_locked
358 {
359 void operator()() const
360 {
361 Mutex m;
362 Lock lock(m);
363
364 BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error );
365 }
366 };
367
368 template<typename Mutex,typename Lock>
369 struct test_throws_if_unlock_called_when_already_unlocked
370 {
371 void operator()() const
372 {
373 Mutex m;
374 Lock lock(m);
375 lock.unlock();
376
377 BOOST_CHECK_THROW( lock.unlock(), boost::lock_error );
378 }
379 };
380 template<typename Lock>
381 struct test_default_constructed_has_no_mutex_and_unlocked
382 {
383 void operator()() const
384 {
385 Lock l;
386 BOOST_CHECK(!l.mutex());
387 BOOST_CHECK(!l.owns_lock());
388 }
389 };
390
391
392 template<typename Mutex,typename Lock>
393 struct test_locks_can_be_swapped
394 {
395 void operator()() const
396 {
397 Mutex m1;
398 Mutex m2;
399 Mutex m3;
400
401 Lock l1(m1);
402 Lock l2(m2);
403
404 BOOST_CHECK_EQUAL(l1.mutex(),&m1);
405 BOOST_CHECK_EQUAL(l2.mutex(),&m2);
406
407 l1.swap(l2);
408
409 BOOST_CHECK_EQUAL(l1.mutex(),&m2);
410 BOOST_CHECK_EQUAL(l2.mutex(),&m1);
411
412 swap(l1,l2);
413
414 BOOST_CHECK_EQUAL(l1.mutex(),&m1);
415 BOOST_CHECK_EQUAL(l2.mutex(),&m2);
416
417 #if 0
418 l1.swap(Lock(m3));
419
420 BOOST_CHECK_EQUAL(l1.mutex(),&m3);
421 #endif
422
423 }
424 };
425
426 template<typename Mutex,typename Lock>
427 void test_lock_is_scoped_lock_concept_for_mutex()
428 {
429 test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
430 test_initially_locked<Mutex,Lock>()();
431 test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
432 test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
433 test_unlocked_after_unlock_called<Mutex,Lock>()();
434 test_locked_after_lock_called<Mutex,Lock>()();
435 test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
436 test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
437 test_locks_can_be_swapped<Mutex,Lock>()();
438 test_locked_after_try_lock_called<Mutex,Lock>()();
439 test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
440 test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
441 }
442
443 typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
444 boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
445
446 BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept,Mutex,mutex_types_with_scoped_lock)
447 {
448 typedef typename Mutex::scoped_lock Lock;
449
450 test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
451 }
452
453 typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
454 boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
455
456 BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,Mutex,all_mutex_types)
457 {
458 typedef boost::unique_lock<Mutex> Lock;
459
460 test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
461 }
462
463 typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
464 boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
465
466 BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,Mutex,mutex_types_with_scoped_try_lock)
467 {
468 typedef typename Mutex::scoped_try_lock Lock;
469
470 test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
471 test_initially_locked<Mutex,Lock>()();
472 test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()();
473 test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
474 test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
475 test_unlocked_after_unlock_called<Mutex,Lock>()();
476 test_locked_after_lock_called<Mutex,Lock>()();
477 test_locked_after_try_lock_called<Mutex,Lock>()();
478 test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
479 test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
480 test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
481 test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
482 test_locks_can_be_swapped<Mutex,Lock>()();
483 }
484
485 struct dummy_shared_mutex
486 {
487 bool locked;
488 bool shared_locked;
489 bool shared_unlocked;
490 bool shared_timed_locked_relative;
491 bool shared_timed_locked_absolute;
492 bool timed_locked_relative;
493 bool timed_locked_absolute;
494
495 dummy_shared_mutex():
496 locked(false),shared_locked(false),shared_unlocked(false),
497 shared_timed_locked_relative(false),
498 shared_timed_locked_absolute(false),
499 timed_locked_relative(false),
500 timed_locked_absolute(false)
501 {}
502
503 void lock()
504 {
505 locked=true;
506 }
507
508 void lock_shared()
509 {
510 shared_locked=true;
511 }
512
513 void unlock()
514 {}
515
516 void unlock_shared()
517 {
518 shared_unlocked=true;
519 }
520
521 bool timed_lock_shared(boost::system_time)
522 {
523 shared_timed_locked_absolute=true;
524 return false;
525 }
526 template<typename Duration>
527 bool timed_lock_shared(Duration)
528 {
529 shared_timed_locked_relative=true;
530 return false;
531 }
532 bool timed_lock(boost::system_time)
533 {
534 timed_locked_absolute=true;
535 return false;
536 }
537 template<typename Duration>
538 bool timed_lock(Duration)
539 {
540 timed_locked_relative=true;
541 return false;
542 }
543
544 };
545
546
547 BOOST_AUTO_TEST_CASE(test_shared_lock)
548 {
549 typedef boost::shared_mutex Mutex;
550 typedef boost::shared_lock<Mutex> Lock;
551
552 test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
553 test_initially_locked<Mutex,Lock>()();
554 test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()();
555 test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()();
556 test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
557 test_initially_lock_shared_with_adopt_lock_parameter<Mutex,Lock>()();
558 test_unlocked_after_unlock_called<Mutex,Lock>()();
559 test_locked_after_lock_called<Mutex,Lock>()();
560 test_locked_after_try_lock_called<Mutex,Lock>()();
561 test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
562 test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
563 test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
564 test_locks_can_be_swapped<Mutex,Lock>()();
565
566 dummy_shared_mutex dummy;
567 boost::shared_lock<dummy_shared_mutex> lk(dummy);
568 BOOST_CHECK(dummy.shared_locked);
569 lk.unlock();
570 BOOST_CHECK(dummy.shared_unlocked);
571 lk.timed_lock(boost::posix_time::milliseconds(5));
572 BOOST_CHECK(dummy.shared_timed_locked_relative);
573 lk.timed_lock(boost::get_system_time());
574 BOOST_CHECK(dummy.shared_timed_locked_absolute);
575 }
576
577 //boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
578 //{
579 // boost::unit_test::test_suite* test =
580 // BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
581 //
582 // typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
583 // boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
584 //
585 // test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
586 //
587 // typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
588 // boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
589 //
590 // test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
591 //
592 // typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
593 // boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
594 //
595 // test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
596 // test->add(BOOST_TEST_CASE(&test_shared_lock));
597 //
598 // return test;
599 //}
600