2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-01-31 08:12:08 +00:00
Files
fiber/examples/migrate_fibers.cpp
2014-03-25 17:45:56 +01:00

126 lines
3.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 <cstdio>
#include <sstream>
#include <string>
#include <boost/atomic.hpp>
#include <boost/assert.hpp>
#include <boost/thread.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/all.hpp>
#include "workstealing_round_robin.hpp"
#define MAXCOUNT 10
boost::atomic< bool > fini( false);
boost::fibers::future< int > fibonacci( int);
int fibonacci_( int n)
{
boost::this_fiber::yield();
int res = 1;
if ( 0 != n && 1 != n)
{
boost::fibers::future< int > f1 = fibonacci( n - 1);
boost::fibers::future< int > f2 = fibonacci( n - 2);
res = f1.get() + f2.get();
}
return res;
}
boost::fibers::future< int > fibonacci( int n)
{
boost::fibers::packaged_task< int() > pt( boost::bind( fibonacci_, n) );
boost::fibers::future< int > f( pt.get_future() );
boost::fibers::fiber( boost::move( pt) ).detach();
return boost::move( f);
}
int create_fiber( int n)
{
return fibonacci( n).get();
}
void fn_create_fibers( workstealing_round_robin * ds, boost::barrier * b)
{
boost::fibers::set_scheduling_algorithm( ds);
b->wait();
int n = 10;
int result = boost::fibers::async( boost::bind( create_fiber, n) ).get();
BOOST_ASSERT( 89 == result);
fprintf( stderr, "fibonacci(%d) = %d", n, result);
fini = true;
}
void fn_migrate_fibers( workstealing_round_robin * other_ds, boost::barrier * b, int * count)
{
BOOST_ASSERT( other_ds);
b->wait();
while ( ! fini)
{
// To guarantee progress, we must ensure that
// threads that have work to do are not unreasonably delayed by (thief) threads
// which are idle except for task-stealing.
// This call yields the thief s processor to another thread, allowing
// descheduled threads to regain a processor and make progress.
boost::this_thread::yield();
boost::fibers::fiber f( other_ds->steal() );
if ( f)
{
++( * count);
boost::fibers::migrate( f);
f.detach();
}
boost::this_fiber::yield();
}
}
int main()
{
try
{
for ( int i = 0; i < MAXCOUNT; ++i) {
fprintf(stderr, "%d. ", i);
fini = false;
int count = 0;
workstealing_round_robin * ds = new workstealing_round_robin();
boost::barrier b( 2);
boost::thread t1( boost::bind( fn_create_fibers, ds, &b) );
boost::thread t2( boost::bind( fn_migrate_fibers, ds, &b, &count) );
t1.join();
t2.join();
fprintf(stderr, ", %d fibers stolen\n", count);
delete ds;
}
return EXIT_SUCCESS;
}
catch ( std::exception const& e)
{ std::cerr << "exception: " << e.what() << std::endl; }
catch (...)
{ std::cerr << "unhandled exception" << std::endl; }
return EXIT_FAILURE;
}