2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // This test is based on the tests of Boost.Thread
17 #include <boost/test/unit_test.hpp>
19 #include <boost/fiber/all.hpp>
21 typedef std::chrono::nanoseconds ns
;
22 typedef std::chrono::milliseconds ms
;
27 template< typename M
>
30 typename
std::unique_lock
< mutex_type
> lk( mtx
);
32 for ( int i
= 0; i
< 3; ++i
)
33 boost::this_fiber::yield();
36 template< typename M
>
40 typename
std::unique_lock
< mutex_type
> lk( mtx
);
44 void fn3( boost::fibers::timed_mutex
& m
) {
45 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
47 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
49 ns d
= t1
- t0
- ms(250);
50 BOOST_CHECK(d
< ns(2500000)+ms(2000)); // within 2.5 ms
53 void fn4( boost::fibers::timed_mutex
& m
) {
54 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
55 while ( ! m
.try_lock() );
56 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
58 ns d
= t1
- t0
- ms(250);
59 BOOST_CHECK(d
< ns(50000000)+ms(2000)); // within 50 ms
62 void fn5( boost::fibers::timed_mutex
& m
) {
63 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
64 BOOST_CHECK( m
.try_lock_for(ms(300)+ms(2000)) == true);
65 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
67 ns d
= t1
- t0
- ms(250);
68 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5 ms
71 void fn6( boost::fibers::timed_mutex
& m
) {
72 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
73 BOOST_CHECK(m
.try_lock_for(ms(250)) == false);
74 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
75 ns d
= t1
- t0
- ms(250);
76 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5 ms
79 void fn7( boost::fibers::timed_mutex
& m
) {
80 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
81 BOOST_CHECK(m
.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
82 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
84 ns d
= t1
- t0
- ms(250);
85 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5ms
88 void fn8( boost::fibers::timed_mutex
& m
) {
89 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
90 BOOST_CHECK(m
.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
91 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
92 ns d
= t1
- t0
- ms(250);
93 ns r
= ns(5000000)+ms(2000); // within 6ms
94 BOOST_CHECK(d
< r
); // within 6ms
97 void fn9( boost::fibers::recursive_timed_mutex
& m
) {
98 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
100 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
104 ns d
= t1
- t0
- ms(250);
105 BOOST_CHECK(d
< ms(2500)+ms(2000)); // within 2.5 ms
108 void fn10( boost::fibers::recursive_timed_mutex
& m
) {
109 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
110 while (!m
.try_lock()) ;
111 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
112 BOOST_CHECK(m
.try_lock());
115 ns d
= t1
- t0
- ms(250);
116 BOOST_CHECK(d
< ns(50000000)+ms(2000)); // within 50 ms
119 void fn11( boost::fibers::recursive_timed_mutex
& m
) {
120 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
121 BOOST_CHECK(m
.try_lock_for(ms(300)+ms(1000)) == true);
122 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
123 BOOST_CHECK(m
.try_lock());
126 ns d
= t1
- t0
- ms(250);
127 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5 ms
130 void fn12( boost::fibers::recursive_timed_mutex
& m
) {
131 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
132 BOOST_CHECK(m
.try_lock_for(ms(250)) == false);
133 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
134 ns d
= t1
- t0
- ms(250);
135 BOOST_CHECK(d
< ms(5000)+ms(2000)); // within 5 ms
138 void fn13( boost::fibers::recursive_timed_mutex
& m
) {
139 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
140 BOOST_CHECK(m
.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
141 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
143 ns d
= t1
- t0
- ms(250);
144 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5 ms
147 void fn14( boost::fibers::recursive_timed_mutex
& m
) {
148 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
149 BOOST_CHECK(m
.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
150 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
151 ns d
= t1
- t0
- ms(250);
152 BOOST_CHECK(d
< ns(5000000)+ms(2000)); // within 5 ms
155 void fn15( boost::fibers::recursive_mutex
& m
) {
156 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
158 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
162 ns d
= t1
- t0
- ms(250);
163 BOOST_CHECK(d
< ns(2500000)+ms(2000)); // within 2.5 ms
166 void fn16( boost::fibers::recursive_mutex
& m
) {
167 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
168 while (!m
.try_lock());
169 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
170 BOOST_CHECK(m
.try_lock());
173 ns d
= t1
- t0
- ms(250);
174 BOOST_CHECK(d
< ns(50000000)+ms(2000)); // within 50 ms
177 void fn17( boost::fibers::mutex
& m
) {
178 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
180 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
182 ns d
= t1
- t0
- ms(250);
183 BOOST_CHECK(d
< ns(2500000)+ms(2000)); // within 2.5 ms
186 void fn18( boost::fibers::mutex
& m
) {
187 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
188 while (!m
.try_lock()) ;
189 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
191 ns d
= t1
- t0
- ms(250);
192 BOOST_CHECK(d
< ns(50000000)+ms(2000)); // within 50 ms
195 template< typename M
>
197 typedef M mutex_type
;
198 typedef typename
std::unique_lock
< M
> lock_type
;
203 // Test the lock's constructors.
205 lock_type
lk(mtx
, std::defer_lock
);
209 BOOST_CHECK(lk
? true : false);
211 // Test the lock and unlock methods.
215 BOOST_CHECK(lk
? true : false);
219 template< typename M
>
220 struct test_exclusive
{
221 typedef M mutex_type
;
222 typedef typename
std::unique_lock
< M
> lock_type
;
227 BOOST_CHECK_EQUAL( 0, value1
);
228 BOOST_CHECK_EQUAL( 0, value2
);
231 boost::fibers::fiber
f1( boost::fibers::launch::post
, & fn1
< mutex_type
>, std::ref( mtx
) );
232 boost::fibers::fiber
f2( boost::fibers::launch::post
, & fn2
< mutex_type
>, std::ref( mtx
) );
233 BOOST_ASSERT( f1
.joinable() );
234 BOOST_ASSERT( f2
.joinable() );
238 BOOST_CHECK_EQUAL( 1, value1
);
239 BOOST_CHECK_EQUAL( 2, value2
);
243 template< typename M
>
244 struct test_recursive_lock
{
245 typedef M mutex_type
;
246 typedef typename
std::unique_lock
< M
> lock_type
;
255 void do_test_mutex() {
256 test_lock
< boost::fibers::mutex
>()();
257 test_exclusive
< boost::fibers::mutex
>()();
260 boost::fibers::mutex mtx
;
262 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn17
, std::ref( mtx
) );
263 boost::this_fiber::sleep_for( ms(250) );
269 boost::fibers::mutex mtx
;
271 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn18
, std::ref( mtx
) );
272 boost::this_fiber::sleep_for( ms(250) );
279 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_mutex
).join();
282 void do_test_recursive_mutex() {
283 test_lock
< boost::fibers::recursive_mutex
>()();
284 test_exclusive
< boost::fibers::recursive_mutex
>()();
285 test_recursive_lock
< boost::fibers::recursive_mutex
>()();
288 boost::fibers::recursive_mutex mtx
;
290 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn15
, std::ref( mtx
) );
291 boost::this_fiber::sleep_for( ms(250) );
297 boost::fibers::recursive_mutex mtx
;
299 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn16
, std::ref( mtx
) );
300 boost::this_fiber::sleep_for( ms(250) );
306 void test_recursive_mutex() {
307 boost::fibers::fiber( boost::fibers::launch::post
, do_test_recursive_mutex
).join();
310 void do_test_timed_mutex() {
311 test_lock
< boost::fibers::timed_mutex
>()();
312 test_exclusive
< boost::fibers::timed_mutex
>()();
315 boost::fibers::timed_mutex timed_mtx
;
317 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn3
, std::ref( timed_mtx
) );
318 boost::this_fiber::sleep_for( ms(250) );
324 boost::fibers::timed_mutex timed_mtx
;
326 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn4
, std::ref( timed_mtx
) );
327 boost::this_fiber::sleep_for( ms(250) );
333 boost::fibers::timed_mutex timed_mtx
;
335 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn5
, std::ref( timed_mtx
) );
336 boost::this_fiber::sleep_for( ms(250) );
342 boost::fibers::timed_mutex timed_mtx
;
344 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn6
, std::ref( timed_mtx
) );
345 boost::this_fiber::sleep_for( ms(300) );
351 boost::fibers::timed_mutex timed_mtx
;
353 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn7
, std::ref( timed_mtx
) );
354 boost::this_fiber::sleep_for( ms(250) );
360 boost::fibers::timed_mutex timed_mtx
;
362 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn8
, std::ref( timed_mtx
) );
363 boost::this_fiber::sleep_for( ms(300) + ms(1000) );
369 void test_timed_mutex() {
370 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_timed_mutex
).join();
373 void do_test_recursive_timed_mutex() {
374 test_lock
< boost::fibers::recursive_timed_mutex
>()();
375 test_exclusive
< boost::fibers::recursive_timed_mutex
>()();
376 test_recursive_lock
< boost::fibers::recursive_timed_mutex
>()();
379 boost::fibers::recursive_timed_mutex timed_mtx
;
381 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn9
, std::ref( timed_mtx
) );
382 boost::this_fiber::sleep_for( ms(250) );
388 boost::fibers::recursive_timed_mutex timed_mtx
;
390 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn10
, std::ref( timed_mtx
) );
391 boost::this_fiber::sleep_for( ms(250) );
397 boost::fibers::recursive_timed_mutex timed_mtx
;
399 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn11
, std::ref( timed_mtx
) );
400 boost::this_fiber::sleep_for( ms(250) );
406 boost::fibers::recursive_timed_mutex timed_mtx
;
408 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn12
, std::ref( timed_mtx
) );
409 boost::this_fiber::sleep_for( ms(400) );
415 boost::fibers::recursive_timed_mutex timed_mtx
;
417 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn13
, std::ref( timed_mtx
) );
418 boost::this_fiber::sleep_for( ms(250) );
424 boost::fibers::recursive_timed_mutex timed_mtx
;
426 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn14
, std::ref( timed_mtx
) );
427 boost::this_fiber::sleep_for( ms(300) );
433 void test_recursive_timed_mutex() {
434 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_recursive_timed_mutex
).join();
437 boost::unit_test::test_suite
* init_unit_test_suite( int, char* []) {
438 boost::unit_test::test_suite
* test
=
439 BOOST_TEST_SUITE("Boost.Fiber: mutex test suite");
441 test
->add( BOOST_TEST_CASE( & test_mutex
) );
442 test
->add( BOOST_TEST_CASE( & test_recursive_mutex
) );
443 test
->add( BOOST_TEST_CASE( & test_timed_mutex
) );
444 test
->add( BOOST_TEST_CASE( & test_recursive_timed_mutex
) );