1 // (C) Copyright 2008 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
8 #define BOOST_TEST_MODULE Boost.Threads: generic locks test suite
10 #include <boost/test/unit_test.hpp>
11 #include <boost/thread/mutex.hpp>
12 #include <boost/thread/thread_only.hpp>
13 #include <boost/thread/locks.hpp>
14 #include <boost/thread/condition_variable.hpp>
18 BOOST_AUTO_TEST_CASE(test_lock_two_uncontended
)
22 boost::unique_lock
<boost::mutex
> l1(m1
,boost::defer_lock
),
23 l2(m2
,boost::defer_lock
);
25 BOOST_CHECK(!l1
.owns_lock());
26 BOOST_CHECK(!l2
.owns_lock());
30 BOOST_CHECK(l1
.owns_lock());
31 BOOST_CHECK(l2
.owns_lock());
38 boost::condition_variable cond
;
46 boost::unique_lock
<boost::mutex
> l(m
);
53 template<typename Duration
>
54 bool timed_wait(Duration d
)
56 boost::system_time
const target
=boost::get_system_time()+d
;
58 boost::unique_lock
<boost::mutex
> l(m
);
61 if(!cond
.timed_wait(l
,target
))
71 boost::unique_lock
<boost::mutex
> l(m
);
78 void lock_mutexes_slowly(boost::mutex
* m1
,boost::mutex
* m2
,wait_data
* locked
,wait_data
* quit
)
80 boost::lock_guard
<boost::mutex
> l1(*m1
);
81 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
82 boost::lock_guard
<boost::mutex
> l2(*m2
);
87 void lock_pair(boost::mutex
* m1
,boost::mutex
* m2
)
90 boost::unique_lock
<boost::mutex
> l1(*m1
,boost::adopt_lock
),
91 l2(*m2
,boost::adopt_lock
);
94 BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order
)
100 boost::thread
t(lock_mutexes_slowly
,&m1
,&m2
,&locked
,&release
);
101 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
103 boost::thread
t2(lock_pair
,&m1
,&m2
);
104 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(1)));
108 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(1)));
113 BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order
)
119 boost::thread
t(lock_mutexes_slowly
,&m1
,&m2
,&locked
,&release
);
120 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
122 boost::thread
t2(lock_pair
,&m2
,&m1
);
123 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(1)));
127 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(1)));
132 BOOST_AUTO_TEST_CASE(test_lock_five_uncontended
)
134 boost::mutex m1
,m2
,m3
,m4
,m5
;
136 boost::unique_lock
<boost::mutex
> l1(m1
,boost::defer_lock
),
137 l2(m2
,boost::defer_lock
),
138 l3(m3
,boost::defer_lock
),
139 l4(m4
,boost::defer_lock
),
140 l5(m5
,boost::defer_lock
);
142 BOOST_CHECK(!l1
.owns_lock());
143 BOOST_CHECK(!l2
.owns_lock());
144 BOOST_CHECK(!l3
.owns_lock());
145 BOOST_CHECK(!l4
.owns_lock());
146 BOOST_CHECK(!l5
.owns_lock());
148 boost::lock(l1
,l2
,l3
,l4
,l5
);
150 BOOST_CHECK(l1
.owns_lock());
151 BOOST_CHECK(l2
.owns_lock());
152 BOOST_CHECK(l3
.owns_lock());
153 BOOST_CHECK(l4
.owns_lock());
154 BOOST_CHECK(l5
.owns_lock());
157 void lock_five_mutexes_slowly(boost::mutex
* m1
,boost::mutex
* m2
,boost::mutex
* m3
,boost::mutex
* m4
,boost::mutex
* m5
,
158 wait_data
* locked
,wait_data
* quit
)
160 boost::lock_guard
<boost::mutex
> l1(*m1
);
161 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
162 boost::lock_guard
<boost::mutex
> l2(*m2
);
163 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
164 boost::lock_guard
<boost::mutex
> l3(*m3
);
165 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
166 boost::lock_guard
<boost::mutex
> l4(*m4
);
167 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
168 boost::lock_guard
<boost::mutex
> l5(*m5
);
173 void lock_five(boost::mutex
* m1
,boost::mutex
* m2
,boost::mutex
* m3
,boost::mutex
* m4
,boost::mutex
* m5
)
175 boost::lock(*m1
,*m2
,*m3
,*m4
,*m5
);
183 BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order
)
185 boost::mutex m1
,m2
,m3
,m4
,m5
;
189 boost::thread
t(lock_five_mutexes_slowly
,&m1
,&m2
,&m3
,&m4
,&m5
,&locked
,&release
);
190 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
192 boost::thread
t2(lock_five
,&m1
,&m2
,&m3
,&m4
,&m5
);
193 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
197 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
202 BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order
)
204 boost::mutex m1
,m2
,m3
,m4
,m5
;
208 boost::thread
t(lock_five_mutexes_slowly
,&m1
,&m2
,&m3
,&m4
,&m5
,&locked
,&release
);
209 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
211 boost::thread
t2(lock_five
,&m5
,&m1
,&m4
,&m2
,&m3
);
212 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
216 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
221 void lock_n(boost::mutex
* mutexes
,unsigned count
)
223 boost::lock(mutexes
,mutexes
+count
);
224 for(unsigned i
=0;i
<count
;++i
)
231 BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order
)
233 unsigned const num_mutexes
=10;
235 boost::mutex mutexes
[num_mutexes
];
239 boost::thread
t(lock_five_mutexes_slowly
,&mutexes
[6],&mutexes
[3],&mutexes
[8],&mutexes
[0],&mutexes
[2],&locked
,&release
);
240 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
242 boost::thread
t2(lock_n
,mutexes
,num_mutexes
);
243 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
247 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
284 struct is_mutex_type
<dummy_mutex
>
286 BOOST_STATIC_CONSTANT(bool, value
= true);
292 BOOST_AUTO_TEST_CASE(test_lock_five_in_range
)
294 unsigned const num_mutexes
=5;
295 dummy_mutex mutexes
[num_mutexes
];
297 boost::lock(mutexes
,mutexes
+num_mutexes
);
299 for(unsigned i
=0;i
<num_mutexes
;++i
)
301 BOOST_CHECK(mutexes
[i
].is_locked
);
310 typedef std::forward_iterator_tag iterator_category
;
311 typedef dummy_mutex value_type
;
312 typedef std::ptrdiff_t difference_type
;
313 typedef dummy_mutex
* pointer
;
314 typedef dummy_mutex
& reference
;
316 explicit dummy_iterator(dummy_mutex
* p_
):
320 bool operator==(dummy_iterator
const& other
) const
325 bool operator!=(dummy_iterator
const& other
) const
330 bool operator<(dummy_iterator
const& other
) const
335 dummy_mutex
& operator*() const
340 dummy_mutex
* operator->() const
345 dummy_iterator
operator++(int)
347 dummy_iterator
temp(*this);
352 dummy_iterator
& operator++()
361 BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator
)
363 unsigned const num_mutexes
=5;
364 dummy_mutex mutexes
[num_mutexes
];
366 boost::lock(dummy_iterator(mutexes
),dummy_iterator(mutexes
+num_mutexes
));
368 for(unsigned i
=0;i
<num_mutexes
;++i
)
370 BOOST_CHECK(mutexes
[i
].is_locked
);
379 BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex
)
381 unsigned const num_mutexes
=10;
382 dummy_mutex2 mutexes
[num_mutexes
];
384 boost::lock(mutexes
,mutexes
+num_mutexes
);
386 for(unsigned i
=0;i
<num_mutexes
;++i
)
388 BOOST_CHECK(mutexes
[i
].is_locked
);
392 BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended
)
396 int const res
=boost::try_lock(m1
,m2
);
398 BOOST_CHECK(res
==-1);
399 BOOST_CHECK(m1
.is_locked
);
400 BOOST_CHECK(m2
.is_locked
);
402 BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked
)
407 boost::unique_lock
<dummy_mutex
> l1(m1
,boost::defer_lock
),
408 l2(m2
,boost::defer_lock
);
410 int const res
=boost::try_lock(l1
,l2
);
413 BOOST_CHECK(m1
.is_locked
);
414 BOOST_CHECK(!m2
.is_locked
);
415 BOOST_CHECK(!l1
.owns_lock());
416 BOOST_CHECK(!l2
.owns_lock());
418 BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked
)
423 boost::unique_lock
<dummy_mutex
> l1(m1
,boost::defer_lock
),
424 l2(m2
,boost::defer_lock
);
426 int const res
=boost::try_lock(l1
,l2
);
429 BOOST_CHECK(!m1
.is_locked
);
430 BOOST_CHECK(m2
.is_locked
);
431 BOOST_CHECK(!l1
.owns_lock());
432 BOOST_CHECK(!l2
.owns_lock());
435 BOOST_AUTO_TEST_CASE(test_try_lock_three
)
437 int const num_mutexes
=3;
439 for(int i
=-1;i
<num_mutexes
;++i
)
441 dummy_mutex mutexes
[num_mutexes
];
447 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
448 l2(mutexes
[1],boost::defer_lock
),
449 l3(mutexes
[2],boost::defer_lock
);
451 int const res
=boost::try_lock(l1
,l2
,l3
);
454 for(int j
=0;j
<num_mutexes
;++j
)
456 if((i
==j
) || (i
==-1))
458 BOOST_CHECK(mutexes
[j
].is_locked
);
462 BOOST_CHECK(!mutexes
[j
].is_locked
);
467 BOOST_CHECK(l1
.owns_lock());
468 BOOST_CHECK(l2
.owns_lock());
469 BOOST_CHECK(l3
.owns_lock());
473 BOOST_CHECK(!l1
.owns_lock());
474 BOOST_CHECK(!l2
.owns_lock());
475 BOOST_CHECK(!l3
.owns_lock());
480 BOOST_AUTO_TEST_CASE(test_try_lock_four
)
482 int const num_mutexes
=4;
484 for(int i
=-1;i
<num_mutexes
;++i
)
486 dummy_mutex mutexes
[num_mutexes
];
492 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
493 l2(mutexes
[1],boost::defer_lock
),
494 l3(mutexes
[2],boost::defer_lock
),
495 l4(mutexes
[3],boost::defer_lock
);
497 int const res
=boost::try_lock(l1
,l2
,l3
,l4
);
500 for(int j
=0;j
<num_mutexes
;++j
)
502 if((i
==j
) || (i
==-1))
504 BOOST_CHECK(mutexes
[j
].is_locked
);
508 BOOST_CHECK(!mutexes
[j
].is_locked
);
513 BOOST_CHECK(l1
.owns_lock());
514 BOOST_CHECK(l2
.owns_lock());
515 BOOST_CHECK(l3
.owns_lock());
516 BOOST_CHECK(l4
.owns_lock());
520 BOOST_CHECK(!l1
.owns_lock());
521 BOOST_CHECK(!l2
.owns_lock());
522 BOOST_CHECK(!l3
.owns_lock());
523 BOOST_CHECK(!l4
.owns_lock());
528 BOOST_AUTO_TEST_CASE(test_try_lock_five
)
530 int const num_mutexes
=5;
532 for(int i
=-1;i
<num_mutexes
;++i
)
534 dummy_mutex mutexes
[num_mutexes
];
540 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
541 l2(mutexes
[1],boost::defer_lock
),
542 l3(mutexes
[2],boost::defer_lock
),
543 l4(mutexes
[3],boost::defer_lock
),
544 l5(mutexes
[4],boost::defer_lock
);
546 int const res
=boost::try_lock(l1
,l2
,l3
,l4
,l5
);
549 for(int j
=0;j
<num_mutexes
;++j
)
551 if((i
==j
) || (i
==-1))
553 BOOST_CHECK(mutexes
[j
].is_locked
);
557 BOOST_CHECK(!mutexes
[j
].is_locked
);
562 BOOST_CHECK(l1
.owns_lock());
563 BOOST_CHECK(l2
.owns_lock());
564 BOOST_CHECK(l3
.owns_lock());
565 BOOST_CHECK(l4
.owns_lock());
566 BOOST_CHECK(l5
.owns_lock());
570 BOOST_CHECK(!l1
.owns_lock());
571 BOOST_CHECK(!l2
.owns_lock());
572 BOOST_CHECK(!l3
.owns_lock());
573 BOOST_CHECK(!l4
.owns_lock());
574 BOOST_CHECK(!l5
.owns_lock());