|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57673 - in sandbox/fiber: boost/fiber boost/fiber/detail libs/fiber/examples libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-15 03:18:21
Author: olli
Date: 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
New Revision: 57673
URL: http://svn.boost.org/trac/boost/changeset/57673
Log:
- join() op. + unut test and example added
Added:
sandbox/fiber/libs/fiber/examples/join.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_join.cpp (contents, props changed)
Text files modified:
sandbox/fiber/boost/fiber/bounded_fifo.hpp | 116 +++++++++++++++++++-------------------
sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp | 30 +++++++--
sandbox/fiber/boost/fiber/fiber.hpp | 2
sandbox/fiber/boost/fiber/scheduler.hpp | 2
sandbox/fiber/boost/fiber/unbounded_fifo.hpp | 50 ++++++++--------
sandbox/fiber/libs/fiber/examples/Jamfile.v2 | 1
sandbox/fiber/libs/fiber/src/fiber.cpp | 4 +
sandbox/fiber/libs/fiber/src/scheduler.cpp | 7 ++
sandbox/fiber/libs/fiber/src/scheduler_impl.cpp | 119 +++++++++++++++++++++++++++------------
sandbox/fiber/libs/fiber/test/Jamfile.v2 | 1
10 files changed, 204 insertions(+), 128 deletions(-)
Modified: sandbox/fiber/boost/fiber/bounded_fifo.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/bounded_fifo.hpp (original)
+++ sandbox/fiber/boost/fiber/bounded_fifo.hpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -187,30 +187,30 @@
not_empty_cond_.notify_one();
}
- void put(
- T const& t,
- posix_time::time_duration const& rel_time)
- {
- typename node::sptr_t new_node( new node);
- {
- mutex::scoped_lock lk( tail_mtx_);
-
- if ( full_() )
- {
- while ( active_() && full_() )
- if ( ! not_full_cond_.timed_wait( lk, rel_time) )
- throw std::runtime_error("timed out");
- }
- if ( ! active_() )
- throw std::runtime_error("queue is not active");
-
- tail_->va = t;
- tail_->next = new_node;
- tail_ = new_node;
- detail::atomic_fetch_add( & count_, 1);
- }
- not_empty_cond_.notify_one();
- }
+// void put(
+// T const& t,
+// posix_time::time_duration const& rel_time)
+// {
+// typename node::sptr_t new_node( new node);
+// {
+// mutex::scoped_lock lk( tail_mtx_);
+//
+// if ( full_() )
+// {
+// while ( active_() && full_() )
+// if ( ! not_full_cond_.timed_wait( lk, rel_time) )
+// throw std::runtime_error("timed out");
+// }
+// if ( ! active_() )
+// throw std::runtime_error("queue is not active");
+//
+// tail_->va = t;
+// tail_->next = new_node;
+// tail_ = new_node;
+// detail::atomic_fetch_add( & count_, 1);
+// }
+// not_empty_cond_.notify_one();
+// }
bool take( value_type & va)
{
@@ -244,40 +244,40 @@
return va;
}
- bool take(
- value_type & va,
- posix_time::time_duration const& rel_time)
- {
- mutex::scoped_lock lk( head_mtx_);
- bool empty = empty_();
- if ( ! active_() && empty)
- return false;
- if ( empty)
- {
- try
- {
- while ( active_() && empty_() )
- if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
- return false;
- }
- catch ( fiber_interrupted const&)
- { return false; }
- }
- if ( ! active_() && empty_() )
- return false;
- swap( va, head_->va);
- pop_head_();
- if ( size_() <= lwm_)
- {
- if ( lwm_ == hwm_)
- not_full_cond_.notify_one();
- else
- // more than one producer could be waiting
- // for submiting an action object
- not_full_cond_.notify_all();
- }
- return va;
- }
+// bool take(
+// value_type & va,
+// posix_time::time_duration const& rel_time)
+// {
+// mutex::scoped_lock lk( head_mtx_);
+// bool empty = empty_();
+// if ( ! active_() && empty)
+// return false;
+// if ( empty)
+// {
+// try
+// {
+// while ( active_() && empty_() )
+// if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+// return false;
+// }
+// catch ( fiber_interrupted const&)
+// { return false; }
+// }
+// if ( ! active_() && empty_() )
+// return false;
+// swap( va, head_->va);
+// pop_head_();
+// if ( size_() <= lwm_)
+// {
+// if ( lwm_ == hwm_)
+// not_full_cond_.notify_one();
+// else
+// // more than one producer could be waiting
+// // for submiting an action object
+// not_full_cond_.notify_all();
+// }
+// return va;
+// }
bool try_take( value_type & va)
{
Modified: sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp (original)
+++ sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -26,13 +26,27 @@
class BOOST_FIBER_DECL scheduler_impl : private noncopyable
{
private:
- typedef std::map< fiber::id, fiber > container;
- typedef std::list< fiber::id > runnable_queue;
- typedef std::queue< fiber::id > terminated_queue;
-
- fiber master_;
- fiber::id f_id_;
- container fibers_;
+ struct schedulable
+ {
+ fiber f;
+ std::list< fiber::id > waiting;
+
+ schedulable() :
+ f(), waiting()
+ {}
+
+ schedulable( fiber f_) :
+ f( f_), waiting()
+ {}
+ };
+
+ typedef std::map< fiber::id, schedulable > container;
+ typedef std::list< fiber::id > runnable_queue;
+ typedef std::queue< fiber::id > terminated_queue;
+
+ fiber master_;
+ fiber::id f_id_;
+ container fibers_;
runnable_queue runnable_fibers_;
terminated_queue terminated_fibers_;
@@ -61,6 +75,8 @@
void re_schedule( fiber::id const&);
+ void join( fiber::id const&);
+
bool run();
bool empty();
Modified: sandbox/fiber/boost/fiber/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/fiber.hpp (original)
+++ sandbox/fiber/boost/fiber/fiber.hpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -197,6 +197,8 @@
void suspend();
void resume();
+
+ void join();
};
class fiber::id
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -75,6 +75,8 @@
static void re_schedule( fiber::id const&);
+ static void join( fiber::id const&);
+
detail::scheduler_impl * access_();
public:
Modified: sandbox/fiber/boost/fiber/unbounded_fifo.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/unbounded_fifo.hpp (original)
+++ sandbox/fiber/boost/fiber/unbounded_fifo.hpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -143,31 +143,31 @@
return va;
}
- bool take(
- value_type & va,
- posix_time::time_duration const& rel_time)
- {
- mutex::scoped_lock lk( head_mtx_);
- bool empty = empty_();
- if ( ! active_() && empty)
- return false;
- if ( empty)
- {
- try
- {
- while ( active_() && empty_() )
- if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
- return false;
- }
- catch ( fiber_interrupted const&)
- { return false; }
- }
- if ( ! active_() && empty_() )
- return false;
- swap( va, head_->va);
- pop_head_();
- return va;
- }
+// bool take(
+// value_type & va,
+// posix_time::time_duration const& rel_time)
+// {
+// mutex::scoped_lock lk( head_mtx_);
+// bool empty = empty_();
+// if ( ! active_() && empty)
+// return false;
+// if ( empty)
+// {
+// try
+// {
+// while ( active_() && empty_() )
+// if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+// return false;
+// }
+// catch ( fiber_interrupted const&)
+// { return false; }
+// }
+// if ( ! active_() && empty_() )
+// return false;
+// swap( va, head_->va);
+// pop_head_();
+// return va;
+// }
bool try_take( value_type & va)
{
Modified: sandbox/fiber/libs/fiber/examples/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/examples/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/examples/Jamfile.v2 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -24,6 +24,7 @@
;
exe suspend : suspend.cpp ;
+exe join : join.cpp ;
exe cancel : cancel.cpp ;
exe simple : simple.cpp ;
exe simple_mt : simple_mt.cpp ;
Added: sandbox/fiber/libs/fiber/examples/join.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/join.cpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -0,0 +1,71 @@
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/system/system_error.hpp>
+
+#include <boost/fiber.hpp>
+
+int value1 = 0;
+int value2 = 0;
+
+void fn_1()
+{
+ for ( int i = 0; i < 5; ++i)
+ {
+ ++value1;
+ std::cout << "fn_1() increment value1 " << value1 << std::endl;
+ boost::this_fiber::yield();
+ }
+}
+
+void fn_2( boost::fiber f)
+{
+ for ( int i = 0; i < 5; ++i)
+ {
+ ++value2;
+ std::cout << "fn_2() increment value2 " << value2 << std::endl;
+ if ( i == 1)
+ {
+ std::cout << "fn_2() join fiber " << f.get_id() << std::endl;
+ f.join();
+ std::cout << "fn_2() fiber " << f.get_id() << " joined" << std::endl;
+ }
+ boost::this_fiber::yield();
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::fibers::scheduler sched;
+
+ boost::fiber f( fn_1);
+ sched.submit_fiber( f);
+ sched.make_fiber( fn_2, f);
+
+ std::cout << "start" << std::endl;
+ std::cout << "fiber to be joined " << f.get_id() << std::endl;
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ std::cout << "finish: value1 == " << value1 << ", value2 == " << value2 << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( boost::system::system_error const& e)
+ { std::cerr << "system_error: " << e.code().value() << std::endl; }
+ catch ( boost::fibers::scheduler_error const& e)
+ { std::cerr << "scheduler_error: " << e.what() << std::endl; }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch (...)
+ { std::cerr << "unhandled exception" << std::endl; }
+ return EXIT_FAILURE;
+}
Modified: sandbox/fiber/libs/fiber/src/fiber.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber.cpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -135,6 +135,10 @@
fiber::resume()
{ scheduler::resume_fiber( get_id() ); }
+void
+fiber::join()
+{ scheduler::join( get_id() ); }
+
}}
#include <boost/config/abi_suffix.hpp>
Modified: sandbox/fiber/libs/fiber/src/scheduler.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler.cpp (original)
+++ sandbox/fiber/libs/fiber/src/scheduler.cpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -101,6 +101,13 @@
impl->re_schedule( f_id);
}
+void
+scheduler::join( fiber::id const& f_id)
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ impl->join( f_id);
+}
+
detail::scheduler_impl *
scheduler::access_()
{
Modified: sandbox/fiber/libs/fiber/src/scheduler_impl.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler_impl.cpp (original)
+++ sandbox/fiber/libs/fiber/src/scheduler_impl.cpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -9,6 +9,7 @@
#include <utility>
#include <boost/assert.hpp>
+#include <boost/foreach.hpp>
#include <boost/fiber/detail/fiber_info.hpp>
#include <boost/fiber/detail/move.hpp>
@@ -56,12 +57,13 @@
scheduler_impl::add_fiber( fiber f)
{
if ( ! f) throw fiber_moved();
+
fiber::id id( f.get_id() );
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
BOOST_ASSERT( STATE_NOT_STARTED == f.info_->state);
f.info_->state = STATE_READY;
- std::pair< std::map< fiber::id, fiber >::iterator, bool > result(
- fibers_.insert( std::make_pair( id, f) ) );
+ std::pair< std::map< fiber::id, schedulable >::iterator, bool > result(
+ fibers_.insert( std::make_pair( id, schedulable( f) ) ) );
if ( ! result.second) throw scheduler_error("inserting fiber failed");
runnable_fibers_.push_back( result.first->first);
}
@@ -73,30 +75,50 @@
void
scheduler_impl::yield_active_fiber()
{
- BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].info_->state) );
- BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].info_->state);
- fibers_[f_id_].info_->state = STATE_READY;
+ BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].f.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].f.info_->state);
+
+ fibers_[f_id_].f.info_->state = STATE_READY;
+
runnable_fibers_.push_back( f_id_);
- fibers_[f_id_].switch_to_( master_);
+ fibers_[f_id_].f.switch_to_( master_);
}
void
scheduler_impl::cancel_active_fiber()
{
- BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].info_->state) );
- BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].info_->state);
- fibers_[f_id_].info_->state = STATE_TERMINATED;
+ BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].f.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].f.info_->state);
+
+ fibers_[f_id_].f.info_->state = STATE_TERMINATED;
+
terminated_fibers_.push( f_id_);
- fibers_[f_id_].switch_to_( master_);
+
+ BOOST_FOREACH( fiber::id f_id__, fibers_[f_id_].waiting)
+ {
+ fiber f__( fibers_[f_id__].f);
+ BOOST_ASSERT( HAS_STATE_WAITING( f__.info_->state) );
+ f__.info_->state &= ~STATE_WAITING;
+ if ( ( HAS_STATE_READY( f__.info_->state) || HAS_STATE_RUNNING( f__.info_->state) )
+ && ! HAS_STATE_SUSPENDED( f__.info_->state) )
+ {
+ f__.info_->state = STATE_READY;
+ runnable_fibers_.push_back( f__.get_id() );
+ }
+ }
+ fibers_[f_id_].waiting.clear();
+
+ fibers_[f_id_].f.switch_to_( master_);
}
void
scheduler_impl::suspend_active_fiber()
{
- BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].info_->state) );
- BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].info_->state);
- fibers_[f_id_].info_->state |= STATE_SUSPENDED;
- fibers_[f_id_].switch_to_( master_);
+ BOOST_ASSERT( ! HAS_STATE_MASTER( fibers_[f_id_].f.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].f.info_->state);
+
+ fibers_[f_id_].f.info_->state |= STATE_SUSPENDED;
+ fibers_[f_id_].f.switch_to_( master_);
}
void
@@ -104,7 +126,7 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) return;
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
@@ -112,6 +134,20 @@
HAS_STATE_NOT_STARTED( f.info_->state) )
return;
+ BOOST_FOREACH( fiber::id f_id__, fibers_[f_id].waiting)
+ {
+ fiber f__( fibers_[f_id__].f);
+ BOOST_ASSERT( HAS_STATE_WAITING( f__.info_->state) );
+ f__.info_->state &= ~STATE_WAITING;
+ if ( ( HAS_STATE_READY( f__.info_->state) || HAS_STATE_RUNNING( f__.info_->state) )
+ && ! HAS_STATE_SUSPENDED( f__.info_->state) )
+ {
+ f__.info_->state = STATE_READY;
+ runnable_fibers_.push_back( f__.get_id() );
+ }
+ }
+ fibers_[f_id].waiting.clear();
+
if ( HAS_STATE_READY( f.info_->state) )
{
f.info_->state = STATE_TERMINATED;
@@ -140,7 +176,7 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) return;
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
@@ -160,10 +196,7 @@
f.switch_to_( master_);
}
else if ( HAS_STATE_WAITING( f.info_->state) )
- {
f.info_->state |= STATE_SUSPENDED;
- // TODO: remove from waiting-queue
- }
else
BOOST_ASSERT( ! "should never reached");
}
@@ -173,25 +206,18 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) return;
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
if ( HAS_STATE_SUSPENDED( f.info_->state) )
{
f.info_->state &= ~STATE_SUSPENDED;
- switch ( f.info_->state)
+ if ( ( HAS_STATE_READY( f.info_->state) || HAS_STATE_RUNNING( f.info_->state) )
+ && ! HAS_STATE_WAITING( f.info_->state) )
{
- case STATE_READY:
- case STATE_RUNNING:
f.info_->state = STATE_READY;
runnable_fibers_.push_back( f.get_id() );
- break;
- case STATE_WAITING:
- // TODO: put it into the waiting-queue
- break;
- default:
- BOOST_ASSERT( ! "should never reached");
}
}
}
@@ -201,7 +227,7 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) throw scheduler_error("fiber not found");
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
@@ -213,7 +239,7 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) throw scheduler_error("fiber not found");
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
@@ -226,7 +252,7 @@
{
container::iterator i = fibers_.find( f_id);
if ( i == fibers_.end() ) return;
- fiber f( i->second);
+ fiber f( i->second.f);
BOOST_ASSERT( f);
BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
@@ -234,24 +260,41 @@
// runnable_fibers + re-insert
}
+void
+scheduler_impl::join( fiber::id const& f_id)
+{
+ container::iterator i = fibers_.find( f_id);
+ if ( i == fibers_.end() ) return;
+ fiber f( i->second.f);
+ BOOST_ASSERT( f);
+ BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
+
+ fibers_[f_id].waiting.push_back( f_id_);
+ fibers_[f_id_].f.info_->state |= STATE_WAITING;
+ fibers_[f_id_].f.switch_to_( master_);
+}
+
bool
scheduler_impl::run()
{
bool result( false);
if ( ! runnable_fibers_.empty() )
{
- f_id_ = runnable_fibers_.front();
- BOOST_ASSERT( fibers_[f_id_].info_->state == STATE_READY);
- fibers_[f_id_].info_->state = STATE_RUNNING;
- master_.switch_to_( fibers_[f_id_]);
+ fiber f( fibers_[runnable_fibers_.front()].f);
+ f_id_ = f.get_id();
+ BOOST_ASSERT( f.info_->state == STATE_READY);
+ f.info_->state = STATE_RUNNING;
+ master_.switch_to_( f);
runnable_fibers_.pop_front();
result = true;
}
while ( ! terminated_fibers_.empty() )
{
- BOOST_ASSERT( STATE_TERMINATED == fibers_[terminated_fibers_.front()].info_->state);
- fibers_.erase( terminated_fibers_.front() );
+ fiber f( fibers_[terminated_fibers_.front()].f);
terminated_fibers_.pop();
+ BOOST_ASSERT( STATE_TERMINATED == f.info_->state);
+ BOOST_ASSERT( fibers_[f.get_id()].waiting.empty() );
+ fibers_.erase( f.get_id() );
result = true;
}
return result;
Modified: sandbox/fiber/libs/fiber/test/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/test/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/test/Jamfile.v2 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -31,6 +31,7 @@
[ fiber-test test_cancel ]
[ fiber-test test_suspended ]
[ fiber-test test_priority ]
+ [ fiber-test test_join ]
[ fiber-test test_mutex ]
[ fiber-test test_auto_reset_event ]
[ fiber-test test_manual_reset_event ]
Added: sandbox/fiber/libs/fiber/test/test_join.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_join.cpp 2009-11-15 03:18:19 EST (Sun, 15 Nov 2009)
@@ -0,0 +1,300 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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)
+
+#include <sstream>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value1 = 0;
+int value2 = 0;
+int value3 = 0;
+
+void fn_1()
+{
+ for ( int i = 0; i < 5; ++i)
+ {
+ ++value1;
+ boost::this_fiber::yield();
+ }
+}
+
+void fn_2( boost::fiber f)
+{
+ for ( int i = 0; i < 5; ++i)
+ {
+ ++value2;
+ if ( i == 1) f.join();
+ boost::this_fiber::yield();
+ }
+}
+
+void fn_3( boost::fiber f)
+{
+ for ( int i = 0; i < 5; ++i)
+ {
+ ++value3;
+ if ( i == 3) f.cancel();
+ boost::this_fiber::yield();
+ }
+}
+
+void test_case_1()
+{
+ value1 = 0;
+ value2 = 0;
+
+ boost::fibers::scheduler sched;
+
+ boost::fiber f( fn_1);
+ sched.submit_fiber( f);
+ sched.make_fiber( fn_2, f);
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 3, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 4, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ BOOST_CHECK( ! sched.run() );
+ BOOST_CHECK( sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+}
+
+void test_case_2()
+{
+ value1 = 0;
+ value2 = 0;
+ value3 = 0;
+
+ boost::fibers::scheduler sched;
+
+ boost::fiber f( fn_1);
+ sched.submit_fiber( f);
+ sched.make_fiber( fn_2, f);
+ sched.make_fiber( fn_3, f);
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+ BOOST_CHECK_EQUAL( 0, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+ BOOST_CHECK_EQUAL( 0, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+ BOOST_CHECK_EQUAL( 0, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+ BOOST_CHECK_EQUAL( 1, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+ BOOST_CHECK_EQUAL( 1, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 1, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 2, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 2, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 3, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 3, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 4, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 4, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 3, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 3, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 4, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+
+ BOOST_CHECK( ! sched.run() );
+ BOOST_CHECK( sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 4, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+ BOOST_CHECK_EQUAL( 5, value3);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: join test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+ test->add( BOOST_TEST_CASE( & test_case_2) );
+
+ return test;
+}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk