From 38aa1f436670582c18a2f4466de4d53ea062169d Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Tue, 22 Sep 2015 19:04:48 +0200 Subject: [PATCH] support of detaching fibers added --- include/boost/fiber/fiber.hpp | 2 ++ src/fiber.cpp | 9 ++++++ test/test_condition.cpp | 20 +++++++++---- test/test_fiber.cpp | 55 +++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/include/boost/fiber/fiber.hpp b/include/boost/fiber/fiber.hpp index 18da78ae..0e2aaba9 100644 --- a/include/boost/fiber/fiber.hpp +++ b/include/boost/fiber/fiber.hpp @@ -103,6 +103,8 @@ public: void join(); void interrupt() noexcept; + + void detach() noexcept; }; inline diff --git a/src/fiber.cpp b/src/fiber.cpp index 53861ea6..7b7a74ca 100644 --- a/src/fiber.cpp +++ b/src/fiber.cpp @@ -49,6 +49,15 @@ fiber::interrupt() noexcept { context::active()->set_ready( impl_.get() ); } +void +fiber::detach() noexcept { + if ( ! joinable() ) { + throw fiber_resource_error( static_cast< int >( std::errc::invalid_argument), + "boost fiber: fiber not joinable"); + } + impl_.reset(); +} + }} #ifdef BOOST_HAS_ABI_HEADERS diff --git a/test/test_condition.cpp b/test/test_condition.cpp index 29fdba0d..c858d14f 100644 --- a/test/test_condition.cpp +++ b/test/test_condition.cpp @@ -80,12 +80,22 @@ void wait_fn( } void test_condition_wait_is_a_interruption_point() { - condition_test_data data; - boost::fibers::fiber f( & condition_test_fiber, &data); + { + condition_test_data data; + boost::fibers::fiber f( & condition_test_fiber, &data); - f.interrupt(); - f.join(); - BOOST_CHECK_EQUAL(data.awoken,0); + f.interrupt(); + f.join(); + BOOST_CHECK_EQUAL(data.awoken,0); + } + { + condition_test_data data; + boost::fibers::fiber f( & condition_test_fiber, &data); + boost::this_fiber::yield(); + f.interrupt(); + f.join(); + BOOST_CHECK_EQUAL(data.awoken,0); + } } void test_one_waiter_notify_one() { diff --git a/test/test_fiber.cpp b/test/test_fiber.cpp index 403c48e7..850e6b56 100644 --- a/test/test_fiber.cpp +++ b/test/test_fiber.cpp @@ -83,6 +83,38 @@ public: } }; +class detachable { +private: + int alive_count_; + +public: + static int alive_count; + static bool was_running; + + detachable() : + alive_count_( 1) { + ++alive_count; + } + + detachable( detachable const& g) : + alive_count_( g.alive_count_) { + ++alive_count; + } + + ~detachable() { + alive_count_ = 0; + --alive_count; + } + + void operator()() { + BOOST_CHECK_EQUAL(1, alive_count_); + was_running = true; + } +}; + +int detachable::alive_count = 0; +bool detachable::was_running = false; + void fn1() { value1 = 1; } @@ -385,6 +417,28 @@ void test_sleep_until_is_interruption_point() { BOOST_CHECK(interrupted); } +void test_detach() { + { + boost::fibers::fiber f( (detachable()) ); + BOOST_CHECK( f.joinable() ); + f.detach(); + BOOST_CHECK( ! f.joinable() ); + boost::this_fiber::sleep_for( std::chrono::milliseconds(250) ); + BOOST_CHECK( detachable::was_running); + BOOST_CHECK_EQUAL( 0, detachable::alive_count); + } + { + boost::fibers::fiber f( (detachable()) ); + BOOST_CHECK( f.joinable() ); + boost::this_fiber::yield(); + f.detach(); + BOOST_CHECK( ! f.joinable() ); + boost::this_fiber::sleep_for( std::chrono::milliseconds(250) ); + BOOST_CHECK( detachable::was_running); + BOOST_CHECK_EQUAL( 0, detachable::alive_count); + } +} + boost::unit_test::test_suite * init_unit_test_suite( int, char* []) { boost::unit_test::test_suite * test = BOOST_TEST_SUITE("Boost.Fiber: fiber test suite"); @@ -405,6 +459,7 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* []) { test->add( BOOST_TEST_CASE( & test_fiber_interrupt_at_join) ); test->add( BOOST_TEST_CASE( & test_sleep_for_is_interruption_point) ); test->add( BOOST_TEST_CASE( & test_sleep_until_is_interruption_point) ); + test->add( BOOST_TEST_CASE( & test_detach) ); return test; }