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>
16 BOOST_AUTO_TEST_CASE(test_lock_two_uncontended
)
20 boost::unique_lock
<boost::mutex
> l1(m1
,boost::defer_lock
),
21 l2(m2
,boost::defer_lock
);
23 BOOST_CHECK(!l1
.owns_lock());
24 BOOST_CHECK(!l2
.owns_lock());
28 BOOST_CHECK(l1
.owns_lock());
29 BOOST_CHECK(l2
.owns_lock());
36 boost::condition_variable cond
;
44 boost::unique_lock
<boost::mutex
> l(m
);
51 template<typename Duration
>
52 bool timed_wait(Duration d
)
54 boost::system_time
const target
=boost::get_system_time()+d
;
56 boost::unique_lock
<boost::mutex
> l(m
);
59 if(!cond
.timed_wait(l
,target
))
69 boost::unique_lock
<boost::mutex
> l(m
);
76 void lock_mutexes_slowly(boost::mutex
* m1
,boost::mutex
* m2
,wait_data
* locked
,wait_data
* quit
)
78 boost::lock_guard
<boost::mutex
> l1(*m1
);
79 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
80 boost::lock_guard
<boost::mutex
> l2(*m2
);
85 void lock_pair(boost::mutex
* m1
,boost::mutex
* m2
)
88 boost::unique_lock
<boost::mutex
> l1(*m1
,boost::adopt_lock
),
89 l2(*m2
,boost::adopt_lock
);
92 BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order
)
98 boost::thread
t(lock_mutexes_slowly
,&m1
,&m2
,&locked
,&release
);
99 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
101 boost::thread
t2(lock_pair
,&m1
,&m2
);
102 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(1)));
106 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(1)));
111 BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order
)
117 boost::thread
t(lock_mutexes_slowly
,&m1
,&m2
,&locked
,&release
);
118 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
120 boost::thread
t2(lock_pair
,&m2
,&m1
);
121 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(1)));
125 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(1)));
130 BOOST_AUTO_TEST_CASE(test_lock_five_uncontended
)
132 boost::mutex m1
,m2
,m3
,m4
,m5
;
134 boost::unique_lock
<boost::mutex
> l1(m1
,boost::defer_lock
),
135 l2(m2
,boost::defer_lock
),
136 l3(m3
,boost::defer_lock
),
137 l4(m4
,boost::defer_lock
),
138 l5(m5
,boost::defer_lock
);
140 BOOST_CHECK(!l1
.owns_lock());
141 BOOST_CHECK(!l2
.owns_lock());
142 BOOST_CHECK(!l3
.owns_lock());
143 BOOST_CHECK(!l4
.owns_lock());
144 BOOST_CHECK(!l5
.owns_lock());
146 boost::lock(l1
,l2
,l3
,l4
,l5
);
148 BOOST_CHECK(l1
.owns_lock());
149 BOOST_CHECK(l2
.owns_lock());
150 BOOST_CHECK(l3
.owns_lock());
151 BOOST_CHECK(l4
.owns_lock());
152 BOOST_CHECK(l5
.owns_lock());
155 void lock_five_mutexes_slowly(boost::mutex
* m1
,boost::mutex
* m2
,boost::mutex
* m3
,boost::mutex
* m4
,boost::mutex
* m5
,
156 wait_data
* locked
,wait_data
* quit
)
158 boost::lock_guard
<boost::mutex
> l1(*m1
);
159 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
160 boost::lock_guard
<boost::mutex
> l2(*m2
);
161 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
162 boost::lock_guard
<boost::mutex
> l3(*m3
);
163 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
164 boost::lock_guard
<boost::mutex
> l4(*m4
);
165 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
166 boost::lock_guard
<boost::mutex
> l5(*m5
);
171 void lock_five(boost::mutex
* m1
,boost::mutex
* m2
,boost::mutex
* m3
,boost::mutex
* m4
,boost::mutex
* m5
)
173 boost::lock(*m1
,*m2
,*m3
,*m4
,*m5
);
181 BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order
)
183 boost::mutex m1
,m2
,m3
,m4
,m5
;
187 boost::thread
t(lock_five_mutexes_slowly
,&m1
,&m2
,&m3
,&m4
,&m5
,&locked
,&release
);
188 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
190 boost::thread
t2(lock_five
,&m1
,&m2
,&m3
,&m4
,&m5
);
191 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
195 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
200 BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order
)
202 boost::mutex m1
,m2
,m3
,m4
,m5
;
206 boost::thread
t(lock_five_mutexes_slowly
,&m1
,&m2
,&m3
,&m4
,&m5
,&locked
,&release
);
207 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
209 boost::thread
t2(lock_five
,&m5
,&m1
,&m4
,&m2
,&m3
);
210 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
214 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
219 void lock_n(boost::mutex
* mutexes
,unsigned count
)
221 boost::lock(mutexes
,mutexes
+count
);
222 for(unsigned i
=0;i
<count
;++i
)
229 BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order
)
231 unsigned const num_mutexes
=10;
233 boost::mutex mutexes
[num_mutexes
];
237 boost::thread
t(lock_five_mutexes_slowly
,&mutexes
[6],&mutexes
[3],&mutexes
[8],&mutexes
[0],&mutexes
[2],&locked
,&release
);
238 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
240 boost::thread
t2(lock_n
,mutexes
,num_mutexes
);
241 BOOST_CHECK(locked
.timed_wait(boost::posix_time::seconds(3)));
245 BOOST_CHECK(t2
.timed_join(boost::posix_time::seconds(3)));
282 struct is_mutex_type
<dummy_mutex
>
284 BOOST_STATIC_CONSTANT(bool, value
= true);
290 BOOST_AUTO_TEST_CASE(test_lock_five_in_range
)
292 unsigned const num_mutexes
=5;
293 dummy_mutex mutexes
[num_mutexes
];
295 boost::lock(mutexes
,mutexes
+num_mutexes
);
297 for(unsigned i
=0;i
<num_mutexes
;++i
)
299 BOOST_CHECK(mutexes
[i
].is_locked
);
303 class dummy_iterator
:
304 public std::iterator
<std::forward_iterator_tag
,
310 explicit dummy_iterator(dummy_mutex
* p_
):
314 bool operator==(dummy_iterator
const& other
) const
319 bool operator!=(dummy_iterator
const& other
) const
324 bool operator<(dummy_iterator
const& other
) const
329 dummy_mutex
& operator*() const
334 dummy_mutex
* operator->() const
339 dummy_iterator
operator++(int)
341 dummy_iterator
temp(*this);
346 dummy_iterator
& operator++()
355 BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator
)
357 unsigned const num_mutexes
=5;
358 dummy_mutex mutexes
[num_mutexes
];
360 boost::lock(dummy_iterator(mutexes
),dummy_iterator(mutexes
+num_mutexes
));
362 for(unsigned i
=0;i
<num_mutexes
;++i
)
364 BOOST_CHECK(mutexes
[i
].is_locked
);
373 BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex
)
375 unsigned const num_mutexes
=10;
376 dummy_mutex2 mutexes
[num_mutexes
];
378 boost::lock(mutexes
,mutexes
+num_mutexes
);
380 for(unsigned i
=0;i
<num_mutexes
;++i
)
382 BOOST_CHECK(mutexes
[i
].is_locked
);
386 BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended
)
390 int const res
=boost::try_lock(m1
,m2
);
392 BOOST_CHECK(res
==-1);
393 BOOST_CHECK(m1
.is_locked
);
394 BOOST_CHECK(m2
.is_locked
);
396 BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked
)
401 boost::unique_lock
<dummy_mutex
> l1(m1
,boost::defer_lock
),
402 l2(m2
,boost::defer_lock
);
404 int const res
=boost::try_lock(l1
,l2
);
407 BOOST_CHECK(m1
.is_locked
);
408 BOOST_CHECK(!m2
.is_locked
);
409 BOOST_CHECK(!l1
.owns_lock());
410 BOOST_CHECK(!l2
.owns_lock());
412 BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked
)
417 boost::unique_lock
<dummy_mutex
> l1(m1
,boost::defer_lock
),
418 l2(m2
,boost::defer_lock
);
420 int const res
=boost::try_lock(l1
,l2
);
423 BOOST_CHECK(!m1
.is_locked
);
424 BOOST_CHECK(m2
.is_locked
);
425 BOOST_CHECK(!l1
.owns_lock());
426 BOOST_CHECK(!l2
.owns_lock());
429 BOOST_AUTO_TEST_CASE(test_try_lock_three
)
431 int const num_mutexes
=3;
433 for(int i
=-1;i
<num_mutexes
;++i
)
435 dummy_mutex mutexes
[num_mutexes
];
441 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
442 l2(mutexes
[1],boost::defer_lock
),
443 l3(mutexes
[2],boost::defer_lock
);
445 int const res
=boost::try_lock(l1
,l2
,l3
);
448 for(int j
=0;j
<num_mutexes
;++j
)
450 if((i
==j
) || (i
==-1))
452 BOOST_CHECK(mutexes
[j
].is_locked
);
456 BOOST_CHECK(!mutexes
[j
].is_locked
);
461 BOOST_CHECK(l1
.owns_lock());
462 BOOST_CHECK(l2
.owns_lock());
463 BOOST_CHECK(l3
.owns_lock());
467 BOOST_CHECK(!l1
.owns_lock());
468 BOOST_CHECK(!l2
.owns_lock());
469 BOOST_CHECK(!l3
.owns_lock());
474 BOOST_AUTO_TEST_CASE(test_try_lock_four
)
476 int const num_mutexes
=4;
478 for(int i
=-1;i
<num_mutexes
;++i
)
480 dummy_mutex mutexes
[num_mutexes
];
486 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
487 l2(mutexes
[1],boost::defer_lock
),
488 l3(mutexes
[2],boost::defer_lock
),
489 l4(mutexes
[3],boost::defer_lock
);
491 int const res
=boost::try_lock(l1
,l2
,l3
,l4
);
494 for(int j
=0;j
<num_mutexes
;++j
)
496 if((i
==j
) || (i
==-1))
498 BOOST_CHECK(mutexes
[j
].is_locked
);
502 BOOST_CHECK(!mutexes
[j
].is_locked
);
507 BOOST_CHECK(l1
.owns_lock());
508 BOOST_CHECK(l2
.owns_lock());
509 BOOST_CHECK(l3
.owns_lock());
510 BOOST_CHECK(l4
.owns_lock());
514 BOOST_CHECK(!l1
.owns_lock());
515 BOOST_CHECK(!l2
.owns_lock());
516 BOOST_CHECK(!l3
.owns_lock());
517 BOOST_CHECK(!l4
.owns_lock());
522 BOOST_AUTO_TEST_CASE(test_try_lock_five
)
524 int const num_mutexes
=5;
526 for(int i
=-1;i
<num_mutexes
;++i
)
528 dummy_mutex mutexes
[num_mutexes
];
534 boost::unique_lock
<dummy_mutex
> l1(mutexes
[0],boost::defer_lock
),
535 l2(mutexes
[1],boost::defer_lock
),
536 l3(mutexes
[2],boost::defer_lock
),
537 l4(mutexes
[3],boost::defer_lock
),
538 l5(mutexes
[4],boost::defer_lock
);
540 int const res
=boost::try_lock(l1
,l2
,l3
,l4
,l5
);
543 for(int j
=0;j
<num_mutexes
;++j
)
545 if((i
==j
) || (i
==-1))
547 BOOST_CHECK(mutexes
[j
].is_locked
);
551 BOOST_CHECK(!mutexes
[j
].is_locked
);
556 BOOST_CHECK(l1
.owns_lock());
557 BOOST_CHECK(l2
.owns_lock());
558 BOOST_CHECK(l3
.owns_lock());
559 BOOST_CHECK(l4
.owns_lock());
560 BOOST_CHECK(l5
.owns_lock());
564 BOOST_CHECK(!l1
.owns_lock());
565 BOOST_CHECK(!l2
.owns_lock());
566 BOOST_CHECK(!l3
.owns_lock());
567 BOOST_CHECK(!l4
.owns_lock());
568 BOOST_CHECK(!l5
.owns_lock());