123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- // Copyright Oliver Kowalke 2013.
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // This test is based on the tests of Boost.Thread
- #include <chrono>
- #include <cstdlib>
- #include <iostream>
- #include <map>
- #include <mutex>
- #include <stdexcept>
- #include <vector>
- #include <boost/test/unit_test.hpp>
- #include <boost/fiber/all.hpp>
- typedef std::chrono::nanoseconds ns;
- typedef std::chrono::milliseconds ms;
- int value1 = 0;
- int value2 = 0;
- template< typename M >
- void fn1( M & mtx) {
- typedef M mutex_type;
- typename std::unique_lock< mutex_type > lk( mtx);
- ++value1;
- for ( int i = 0; i < 3; ++i)
- boost::this_fiber::yield();
- }
- template< typename M >
- void fn2( M & mtx) {
- typedef M mutex_type;
- ++value2;
- typename std::unique_lock< mutex_type > lk( mtx);
- ++value2;
- }
- void fn3( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- m.lock();
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
- }
- void fn4( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- while ( ! m.try_lock() );
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
- }
- void fn5( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK( m.try_lock_for(ms(300)+ms(2000)) == true);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
- }
- void fn6( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_for(ms(250)) == false);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
- }
- void fn7( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5ms
- }
- void fn8( boost::fibers::timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- ns d = t1 - t0 - ms(250);
- ns r = ns(5000000)+ms(2000); // within 6ms
- BOOST_CHECK(d < r); // within 6ms
- }
- void fn9( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- m.lock();
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.lock();
- m.unlock();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ms(2500)+ms(2000)); // within 2.5 ms
- }
- void fn10( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- while (!m.try_lock()) ;
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock());
- m.unlock();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
- }
- void fn11( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_for(ms(300)+ms(1000)) == true);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock());
- m.unlock();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
- }
- void fn12( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_for(ms(250)) == false);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ms(5000)+ms(2000)); // within 5 ms
- }
- void fn13( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
- }
- void fn14( boost::fibers::recursive_timed_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
- }
- void fn15( boost::fibers::recursive_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- m.lock();
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.lock();
- m.unlock();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
- }
- void fn16( boost::fibers::recursive_mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- while (!m.try_lock());
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- BOOST_CHECK(m.try_lock());
- m.unlock();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
- }
- void fn17( boost::fibers::mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- m.lock();
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
- }
- void fn18( boost::fibers::mutex & m) {
- std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
- while (!m.try_lock()) ;
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- m.unlock();
- ns d = t1 - t0 - ms(250);
- BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
- }
- template< typename M >
- struct test_lock {
- typedef M mutex_type;
- typedef typename std::unique_lock< M > lock_type;
- void operator()() {
- mutex_type mtx;
- // Test the lock's constructors.
- {
- lock_type lk(mtx, std::defer_lock);
- BOOST_CHECK(!lk);
- }
- lock_type lk(mtx);
- BOOST_CHECK(lk ? true : false);
- // Test the lock and unlock methods.
- lk.unlock();
- BOOST_CHECK(!lk);
- lk.lock();
- BOOST_CHECK(lk ? true : false);
- }
- };
- template< typename M >
- struct test_exclusive {
- typedef M mutex_type;
- typedef typename std::unique_lock< M > lock_type;
- void operator()() {
- value1 = 0;
- value2 = 0;
- BOOST_CHECK_EQUAL( 0, value1);
- BOOST_CHECK_EQUAL( 0, value2);
- mutex_type mtx;
- boost::fibers::fiber f1( boost::fibers::launch::post, & fn1< mutex_type >, std::ref( mtx) );
- boost::fibers::fiber f2( boost::fibers::launch::post, & fn2< mutex_type >, std::ref( mtx) );
- BOOST_ASSERT( f1.joinable() );
- BOOST_ASSERT( f2.joinable() );
- f1.join();
- f2.join();
- BOOST_CHECK_EQUAL( 1, value1);
- BOOST_CHECK_EQUAL( 2, value2);
- }
- };
- template< typename M >
- struct test_recursive_lock {
- typedef M mutex_type;
- typedef typename std::unique_lock< M > lock_type;
- void operator()() {
- mutex_type mx;
- lock_type lock1(mx);
- lock_type lock2(mx);
- }
- };
- void do_test_mutex() {
- test_lock< boost::fibers::mutex >()();
- test_exclusive< boost::fibers::mutex >()();
- {
- boost::fibers::mutex mtx;
- mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn17, std::ref( mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- mtx.unlock();
- f.join();
- }
- {
- boost::fibers::mutex mtx;
- mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn18, std::ref( mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- mtx.unlock();
- f.join();
- }
- }
- void test_mutex() {
- boost::fibers::fiber( boost::fibers::launch::post, & do_test_mutex).join();
- }
- void do_test_recursive_mutex() {
- test_lock< boost::fibers::recursive_mutex >()();
- test_exclusive< boost::fibers::recursive_mutex >()();
- test_recursive_lock< boost::fibers::recursive_mutex >()();
- {
- boost::fibers::recursive_mutex mtx;
- mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn15, std::ref( mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_mutex mtx;
- mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn16, std::ref( mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- mtx.unlock();
- f.join();
- }
- }
- void test_recursive_mutex() {
- boost::fibers::fiber( boost::fibers::launch::post, do_test_recursive_mutex).join();
- }
- void do_test_timed_mutex() {
- test_lock< boost::fibers::timed_mutex >()();
- test_exclusive< boost::fibers::timed_mutex >()();
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn6, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(300) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn7, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn8, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(300) + ms(1000) );
- timed_mtx.unlock();
- f.join();
- }
- }
- void test_timed_mutex() {
- boost::fibers::fiber( boost::fibers::launch::post, & do_test_timed_mutex).join();
- }
- void do_test_recursive_timed_mutex() {
- test_lock< boost::fibers::recursive_timed_mutex >()();
- test_exclusive< boost::fibers::recursive_timed_mutex >()();
- test_recursive_lock< boost::fibers::recursive_timed_mutex >()();
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn9, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn10, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn11, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn12, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(400) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn13, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(250) );
- timed_mtx.unlock();
- f.join();
- }
- {
- boost::fibers::recursive_timed_mutex timed_mtx;
- timed_mtx.lock();
- boost::fibers::fiber f( boost::fibers::launch::post, & fn14, std::ref( timed_mtx) );
- boost::this_fiber::sleep_for( ms(300) );
- timed_mtx.unlock();
- f.join();
- }
- }
- void test_recursive_timed_mutex() {
- boost::fibers::fiber( boost::fibers::launch::post, & do_test_recursive_timed_mutex).join();
- }
- boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
- boost::unit_test::test_suite * test =
- BOOST_TEST_SUITE("Boost.Fiber: mutex test suite");
- test->add( BOOST_TEST_CASE( & test_mutex) );
- test->add( BOOST_TEST_CASE( & test_recursive_mutex) );
- test->add( BOOST_TEST_CASE( & test_timed_mutex) );
- test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );
- return test;
- }
|