From 8e04df986c00f0652b5751dbaea5a956dfff0d2b Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Tue, 22 Oct 2013 19:32:10 +0200 Subject: [PATCH] multithreaded condition_variable --- src/condition.cpp | 3 +- test/Jamfile.v2 | 1 + test/test_condition_mt.cpp | 154 +++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 test/test_condition_mt.cpp diff --git a/src/condition.cpp b/src/condition.cpp index 4d0006b7..83454a39 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -39,8 +39,7 @@ condition::notify_one() lk.unlock(); // notify waiting fiber - if ( n) - n->set_ready(); + if ( n) n->set_ready(); } void diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7f399afe..820aec4d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,4 +38,5 @@ test-suite fibers : [ fiber-test test_fss ] [ fiber-test test_futures ] [ fiber-test test_mutex_mt ] + [ fiber-test test_condition_mt ] ; diff --git a/test/test_condition_mt.cpp b/test/test_condition_mt.cpp new file mode 100644 index 00000000..78e0a7a3 --- /dev/null +++ b/test/test_condition_mt.cpp @@ -0,0 +1,154 @@ + +// 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef boost::chrono::nanoseconds ns; +typedef boost::chrono::milliseconds ms; + +boost::atomic< int > value; + +void notify_one_fn( boost::barrier & b, boost::fibers::condition & cond) +{ + b.wait(); + boost::this_thread::sleep_for( ms( 250) ); + cond.notify_one(); +} + +void notify_all_fn( boost::barrier & b, boost::fibers::condition & cond) +{ + b.wait(); + boost::this_thread::sleep_for( ms( 250) ); + cond.notify_all(); +} + +void wait_fn( + boost::barrier & b, + boost::fibers::mutex & mtx, + boost::fibers::condition & cond) +{ + b.wait(); + boost::fibers::mutex::scoped_lock lk( mtx); + cond.wait( lk); + ++value; +} + +void fn1( boost::barrier & b, boost::fibers::mutex & mtx, boost::fibers::condition & cond) +{ + boost::fibers::round_robin ds; + boost::fibers::set_scheduling_algorithm( & ds); + + boost::fibers::fiber( + boost::bind( + wait_fn, + boost::ref( b), + boost::ref( mtx), + boost::ref( cond) ) ).join(); +} + +void fn2( boost::barrier & b, boost::fibers::condition & cond) +{ + boost::fibers::round_robin ds; + boost::fibers::set_scheduling_algorithm( & ds); + + boost::fibers::fiber( + boost::bind( + notify_one_fn, + boost::ref( b), + boost::ref( cond) ) ).join(); +} + +void fn3( boost::barrier & b, boost::fibers::condition & cond) +{ + boost::fibers::round_robin ds; + boost::fibers::set_scheduling_algorithm( & ds); + + boost::fibers::fiber( + boost::bind( + notify_all_fn, + boost::ref( b), + boost::ref( cond) ) ).join(); +} + +void test_one_waiter_notify_one() +{ + boost::fibers::round_robin ds; + boost::fibers::set_scheduling_algorithm( & ds); + + boost::barrier b( 2); + + value = 0; + boost::fibers::mutex mtx; + boost::fibers::condition cond; + + BOOST_CHECK( 0 == value); + + boost::thread t1(boost::bind( fn1, boost::ref( b), boost::ref( mtx), boost::ref( cond) ) ); + boost::thread t2(boost::bind( fn2, boost::ref( b), boost::ref( cond) ) ); + + BOOST_CHECK( 0 == value); + + t1.join(); + t2.join(); + + BOOST_CHECK( 1 == value); +} + +void test_two_waiter_notify_all() +{ + boost::fibers::round_robin ds; + boost::fibers::set_scheduling_algorithm( & ds); + + boost::barrier b( 3); + + value = 0; + boost::fibers::mutex mtx; + boost::fibers::condition cond; + + BOOST_CHECK( 0 == value); + + boost::thread t1(boost::bind( fn1, boost::ref( b), boost::ref( mtx), boost::ref( cond) ) ); + boost::thread t2(boost::bind( fn1, boost::ref( b), boost::ref( mtx), boost::ref( cond) ) ); + boost::thread t3(boost::bind( fn3, boost::ref( b), boost::ref( cond) ) ); + + BOOST_CHECK( 0 == value); + + t1.join(); + t2.join(); + t3.join(); + + BOOST_CHECK( 2 == value); +} + +boost::unit_test::test_suite * init_unit_test_suite( int, char* []) +{ + boost::unit_test::test_suite * test = + BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition test suite"); + + test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) ); + test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) ); + + return test; +}