Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58268 - in sandbox/fiber: boost boost/fiber libs/fiber/build libs/fiber/doc libs/fiber/examples libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-12-10 11:20:28


Author: olli
Date: 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
New Revision: 58268
URL: http://svn.boost.org/trac/boost/changeset/58268

Log:
- barrier and spin_barrier added
- test for barrier and spin_barrier added
- example for spin_barrier and sync. of fibers running
  in different schedulers and different threads added
- example for unbounded_buffer and sync. of fibers running
  in different schedulers and different threads added

Added:
   sandbox/fiber/boost/fiber/barrier.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin_barrier.hpp (contents, props changed)
   sandbox/fiber/libs/fiber/examples/barrier_mt.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/examples/ping_pong_mt.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/barrier.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_barrier.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_barrier.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_barrier.cpp (contents, props changed)
Text files modified:
   sandbox/fiber/boost/fiber.hpp | 2 ++
   sandbox/fiber/boost/fiber/round_robin.hpp | 4 ++--
   sandbox/fiber/boost/fiber/scheduler.hpp | 2 +-
   sandbox/fiber/boost/fiber/strategy.hpp | 2 ++
   sandbox/fiber/libs/fiber/build/Jamfile.v2 | 4 ++++
   sandbox/fiber/libs/fiber/doc/todo.qbk | 14 ++++++--------
   sandbox/fiber/libs/fiber/examples/Jamfile.v2 | 4 +++-
   sandbox/fiber/libs/fiber/src/round_robin.cpp | 20 +++++++++++---------
   sandbox/fiber/libs/fiber/test/Jamfile.v2 | 6 ++++--
   9 files changed, 35 insertions(+), 23 deletions(-)

Modified: sandbox/fiber/boost/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber.hpp (original)
+++ sandbox/fiber/boost/fiber.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -8,6 +8,7 @@
 #define BOOST_FIBER_H
 
 #include <boost/fiber/auto_reset_event.hpp>
+#include <boost/fiber/barrier.hpp>
 #include <boost/fiber/bounded_fifo.hpp>
 #include <boost/fiber/condition.hpp>
 #include <boost/fiber/count_down_event.hpp>
@@ -18,6 +19,7 @@
 #include <boost/fiber/mutex.hpp>
 #include <boost/fiber/scheduler.hpp>
 #include <boost/fiber/spin_auto_reset_event.hpp>
+#include <boost/fiber/spin_barrier.hpp>
 #include <boost/fiber/spin_condition.hpp>
 #include <boost/fiber/spin_count_down_event.hpp>
 #include <boost/fiber/spin_manual_reset_event.hpp>

Added: sandbox/fiber/boost/fiber/barrier.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/barrier.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,46 @@
+
+// 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)
+
+#ifndef BOOST_FIBERS_BARRIER_H
+#define BOOST_FIBERS_BARRIER_H
+
+#include <stdexcept>
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/condition.hpp>
+#include <boost/fiber/mutex.hpp>
+#include <boost/fiber/scheduler.hpp>
+
+namespace boost {
+namespace fibers {
+
+class barrier : private noncopyable
+{
+private:
+ uint32_t initial_;
+ uint32_t current_;
+ bool cycle_;
+ mutex mtx_;
+ condition cond_;
+
+public:
+ template< typename Strategy >
+ barrier( scheduler< Strategy > & sched, uint32_t initial) :
+ initial_( initial),
+ current_( initial_),
+ cycle_( true),
+ mtx_( sched),
+ cond_( sched)
+ { if ( initial == 0) throw std::invalid_argument("invalid barrier count"); }
+
+ bool wait();
+};
+
+}}
+
+#endif // BOOST_FIBERS_BARRIER_H

Modified: sandbox/fiber/boost/fiber/round_robin.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/round_robin.hpp (original)
+++ sandbox/fiber/boost/fiber/round_robin.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -67,8 +67,6 @@
 public:
         round_robin();
 
- ~round_robin();
-
         void add( fiber);
 
         void join( fiber::id const&);
@@ -95,6 +93,8 @@
 
         void migrate( fiber);
 
+ void detach_all();
+
         bool run();
 
         bool empty();

Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -55,7 +55,7 @@
         {}
 
         ~scheduler()
- {}
+ { strategy_->detach_all(); }
 
         bool run()
         { return strategy_->run(); }

Added: sandbox/fiber/boost/fiber/spin_barrier.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_barrier.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,36 @@
+
+// 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)
+
+#ifndef BOOST_FIBERS_SPIN_BARRIER_H
+#define BOOST_FIBERS_SPIN_BARRIER_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/spin_condition.hpp>
+#include <boost/fiber/spin_mutex.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_barrier : private noncopyable
+{
+private:
+ uint32_t initial_;
+ uint32_t current_;
+ bool cycle_;
+ spin_mutex mtx_;
+ spin_condition cond_;
+
+public:
+ spin_barrier( uint32_t);
+
+ bool wait();
+};
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_BARRIER_H

Modified: sandbox/fiber/boost/fiber/strategy.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/strategy.hpp (original)
+++ sandbox/fiber/boost/fiber/strategy.hpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -179,6 +179,8 @@
 
         virtual void migrate( fiber) = 0;
 
+ virtual void detach_all() = 0;
+
         virtual bool run() = 0;
 
         virtual bool empty() = 0;

Modified: sandbox/fiber/libs/fiber/build/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/build/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/build/Jamfile.v2 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -42,6 +42,7 @@
 alias fiber_sources
     : ## win32 sources ##
         auto_reset_event.cpp
+ barrier.cpp
         condition.cpp
         count_down_event.cpp
         fiber.cpp
@@ -51,6 +52,7 @@
         mutex.cpp
         round_robin.cpp
         spin_auto_reset_event.cpp
+ spin_barrier.cpp
         spin_condition.cpp
         spin_count_down_event.cpp
         spin_manual_reset_event.cpp
@@ -63,6 +65,7 @@
 alias fiber_sources
     : ## posix sources ##
         auto_reset_event.cpp
+ barrier.cpp
         condition.cpp
         count_down_event.cpp
         fiber.cpp
@@ -72,6 +75,7 @@
         mutex.cpp
         round_robin.cpp
         spin_auto_reset_event.cpp
+ spin_barrier.cpp
         spin_condition.cpp
         spin_count_down_event.cpp
         spin_manual_reset_event.cpp

Modified: sandbox/fiber/libs/fiber/doc/todo.qbk
==============================================================================
--- sandbox/fiber/libs/fiber/doc/todo.qbk (original)
+++ sandbox/fiber/libs/fiber/doc/todo.qbk 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -9,18 +9,16 @@
 
 [section:todo Todo]
 
-* replace spin-waiting in mutex, condition- and event-variables
-
-* improve implementation of atomic-ops
+* provide a future and task class
 
-* replace system calls related to fiber switching (like swapcontext()) by assembler
+* provide a barrier class
 
-* explicit migration of fiber between schedulers (== between threads)
+* provide an scheduler which deals with priorities
 
-* improve scheduling algorithm (take priorities into acount)
+* improve implementation of atomic-ops
 
-* provide a future and task class
+* replace system calls related to fiber switching (like swapcontext()) by assembler
 
-* provide a barrier class
+* replace thread_specific_ptr by an specialiced implementation for fiber (interusive_ptr)
 
 [endsect]

Modified: sandbox/fiber/libs/fiber/examples/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/examples/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/examples/Jamfile.v2 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -24,10 +24,12 @@
     ;
 
 exe at_exit : at_exit.cpp ;
+exe barrier_mt : barrier_mt.cpp ;
 exe cancel : cancel.cpp ;
 exe future : future.cpp ;
 exe interrupt : interrupt.cpp ;
 exe join : join.cpp ;
-exe ping_pong : ping_pong.cpp ;
 exe migrate_mt : migrate_mt.cpp ;
+exe ping_pong_mt : ping_pong_mt.cpp ;
+exe ping_pong : ping_pong.cpp ;
 exe simple : simple.cpp ;

Added: sandbox/fiber/libs/fiber/examples/barrier_mt.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/barrier_mt.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,156 @@
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#include <boost/assert.hpp>
+#include <boost/ref.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/fiber.hpp>
+
+int value1 = 0;
+int value2 = 0;
+
+inline
+void fn1( boost::fibers::spin_barrier & b)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+ std::stringstream fss;
+ fss << boost::this_fiber::get_id();
+
+ fprintf( stderr, "start fn1 fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+
+ ++value1;
+ fprintf( stderr, "fn1 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value1);
+
+ fprintf( stderr, "fn1 fiber %s in thread %s before wait for barrier\n", fss.str().c_str(), tss.str().c_str());
+ b.wait();
+ fprintf( stderr, "fn1 fiber %s in thread %s after wait for barrier\n", fss.str().c_str(), tss.str().c_str());
+
+ ++value1;
+ fprintf( stderr, "fn1 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value1);
+
+ ++value1;
+ fprintf( stderr, "fn1 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value1);
+
+ ++value1;
+ fprintf( stderr, "fn1 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value1);
+
+ ++value1;
+ fprintf( stderr, "fn1 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value1);
+
+ fprintf( stderr, "end fn1 fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+}
+
+inline
+void fn2( boost::fibers::spin_barrier & b)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+ std::stringstream fss;
+ fss << boost::this_fiber::get_id();
+
+ fprintf( stderr, "start fn2 fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+
+ ++value2;
+ fprintf( stderr, "fn2 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value2);
+
+ ++value2;
+ fprintf( stderr, "fn2 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value2);
+
+ ++value2;
+ fprintf( stderr, "fn2 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value2);
+
+ ++value2;
+ fprintf( stderr, "fn2 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value2);
+
+ fprintf( stderr, "fn2 fiber %s in thread %s before wait for barrier\n", fss.str().c_str(), tss.str().c_str());
+ b.wait();
+ fprintf( stderr, "fn2 fiber %s in thread %s after wait for barrier\n", fss.str().c_str(), tss.str().c_str());
+
+ ++value2;
+ fprintf( stderr, "fn2 fiber %s in thread %s increment %d\n", fss.str().c_str(), tss.str().c_str(), value2);
+
+ fprintf( stderr, "end fn2 fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+}
+
+void f(
+ boost::barrier & tb,
+ boost::fibers::spin_barrier & fb)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+
+ fprintf( stderr, "start thread %s\n", tss.str().c_str() );
+
+ boost::fibers::scheduler<> sched;
+
+ sched.make_fiber( & fn1, boost::ref( fb) );
+
+ tb.wait();
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ fprintf( stderr, "end thread %s\n", tss.str().c_str() );
+}
+
+void g(
+ boost::barrier & tb,
+ boost::fibers::spin_barrier & fb)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+
+ fprintf( stderr, "start thread %s\n", tss.str().c_str() );
+
+ boost::fibers::scheduler<> sched;
+
+ sched.make_fiber( & fn2, boost::ref( fb) );
+
+ tb.wait();
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ fprintf( stderr, "end thread %s\n", tss.str().c_str() );
+}
+
+int main()
+{
+ try
+ {
+ boost::barrier tb( 2);
+ boost::fibers::spin_barrier fb( 2);
+
+ std::cout << "start" << std::endl;
+
+ boost::thread th1( boost::bind( & f, boost::ref( tb), boost::ref( fb) ) );
+ boost::thread th2( boost::bind( & g, boost::ref( tb), boost::ref( fb) ) );
+
+ th1.join();
+ th2.join();
+
+ std::cout << "finish" << 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;
+}

Added: sandbox/fiber/libs/fiber/examples/ping_pong_mt.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/ping_pong_mt.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,158 @@
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#include <boost/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/ref.hpp>
+#include <boost/optional.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/fiber.hpp>
+
+typedef boost::fibers::unbounded_fifo< std::string, boost::fibers::spin_mutex > fifo_t;
+typedef boost::intrusive_ptr< fifo_t > fifo_ptr_t;
+
+inline
+void ping(
+ fifo_ptr_t & recv_buf,
+ fifo_ptr_t & send_buf)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+ std::stringstream fss;
+ fss << boost::this_fiber::get_id();
+
+ fprintf( stderr, "start ping fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+
+ boost::optional< std::string > value;
+
+ send_buf->put("ping");
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "ping fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+
+ send_buf->put("ping");
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "ping fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+
+ send_buf->put("ping");
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "ping fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+
+ send_buf->deactivate();
+
+ fprintf( stderr, "end ping fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+}
+
+inline
+void pong(
+ fifo_ptr_t & recv_buf,
+ fifo_ptr_t & send_buf)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+ std::stringstream fss;
+ fss << boost::this_fiber::get_id();
+
+ fprintf( stderr, "start pong fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+
+ boost::optional< std::string > value;
+
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "pong fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+ send_buf->put("pong");
+
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "pong fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+ send_buf->put("pong");
+
+ BOOST_ASSERT( recv_buf->take( value) );
+ fprintf( stderr, "pong fiber %s in thread %s recevied %s\n", fss.str().c_str(), tss.str().c_str(), value->c_str());
+ value.reset();
+ send_buf->put("pong");
+
+ send_buf->deactivate();
+
+ fprintf( stderr, "end pong fiber %s in thread %s\n", fss.str().c_str(), tss.str().c_str() );
+}
+
+void f(
+ fifo_ptr_t & recv_buf,
+ fifo_ptr_t & send_buf)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+
+ fprintf( stderr, "start thread %s\n", tss.str().c_str() );
+
+ boost::fibers::scheduler<> sched;
+
+ sched.make_fiber( & ping, recv_buf, send_buf);
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ fprintf( stderr, "end thread %s\n", tss.str().c_str() );
+}
+
+void g(
+ fifo_ptr_t & recv_buf,
+ fifo_ptr_t & send_buf)
+{
+ std::stringstream tss;
+ tss << boost::this_thread::get_id();
+
+ fprintf( stderr, "start thread %s\n", tss.str().c_str() );
+
+ boost::fibers::scheduler<> sched;
+
+ sched.make_fiber( & pong, recv_buf, send_buf);
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ fprintf( stderr, "end thread %s\n", tss.str().c_str() );
+}
+
+int main()
+{
+ try
+ {
+ fifo_ptr_t buf1( new fifo_t() );
+ fifo_ptr_t buf2( new fifo_t() );
+
+ std::cout << "start" << std::endl;
+
+ boost::thread th1( boost::bind( & f, buf1, buf2) );
+ boost::thread th2( boost::bind( & g, buf2, buf1) );
+
+ th1.join();
+ th2.join();
+
+ std::cout << "finish" << 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;
+}

Added: sandbox/fiber/libs/fiber/src/barrier.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/barrier.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,34 @@
+
+// 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 "boost/fiber/barrier.hpp"
+
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace fibers {
+
+bool
+barrier::wait()
+{
+ mutex::scoped_lock lk( mtx_);
+ bool cycle( cycle_);
+ if ( 0 == --current_)
+ {
+ cycle_ = ! cycle_;
+ current_ = initial_;
+ cond_.notify_all();
+ return true;
+ }
+ else
+ {
+ while ( cycle == cycle_)
+ cond_.wait( lk);
+ }
+ return false;
+}
+
+}}

Modified: sandbox/fiber/libs/fiber/src/round_robin.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/round_robin.cpp (original)
+++ sandbox/fiber/libs/fiber/src/round_robin.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -27,12 +27,6 @@
         terminated_fibers_()
 {}
 
-round_robin::~round_robin()
-{
- BOOST_FOREACH( fiber_map::value_type va, fibers_)
- { detach( va.second.f); }
-}
-
 void
 round_robin::add( fiber f)
 {
@@ -364,7 +358,7 @@
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! is_master( f) );
         if ( ! in_state_ready( f) || ! s.joining_fibers.empty() )
- throw scheduler_error("fiber can not be released");
+ throw fiber_error("fiber can not be released");
         BOOST_ASSERT( ! s.waiting_on_fiber);
         BOOST_ASSERT( ! s.waiting_on_object);
 
@@ -377,7 +371,8 @@
 void
 round_robin::migrate( fiber f)
 {
- BOOST_ASSERT( f);
+ if ( ! f) throw fiber_moved();
+
         BOOST_ASSERT( in_state_ready( f) );
 
         // attach to this scheduler
@@ -391,12 +386,19 @@
                                 schedulable( f) ) ) );
 
         // check result
- if ( ! result.second) throw scheduler_error("inserting fiber failed");
+ if ( ! result.second) throw scheduler_error("migrating fiber failed");
 
         // put fiber to runnable-queue
         runnable_fibers_.push_back( result.first->first);
 }
 
+void
+round_robin::detach_all()
+{
+ BOOST_FOREACH( fiber_map::value_type va, fibers_)
+ { detach( va.second.f); }
+}
+
 bool
 round_robin::run()
 {

Added: sandbox/fiber/libs/fiber/src/spin_barrier.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_barrier.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,44 @@
+
+// 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 "boost/fiber/spin_barrier.hpp"
+
+#include <stdexcept>
+
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace fibers {
+
+spin_barrier::spin_barrier( uint32_t initial) :
+ initial_( initial),
+ current_( initial_),
+ cycle_( true),
+ mtx_(),
+ cond_()
+{ if ( initial == 0) throw std::invalid_argument("invalid barrier count"); }
+
+bool
+spin_barrier::wait()
+{
+ spin_mutex::scoped_lock lk( mtx_);
+ bool cycle( cycle_);
+ if ( 0 == --current_)
+ {
+ cycle_ = ! cycle_;
+ current_ = initial_;
+ cond_.notify_all();
+ return true;
+ }
+ else
+ {
+ while ( cycle == cycle_)
+ cond_.wait( lk);
+ }
+ return false;
+}
+
+}}

Modified: sandbox/fiber/libs/fiber/test/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/test/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/test/Jamfile.v2 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -35,14 +35,16 @@
     [ fiber-test test_at_exit ]
     [ fiber-test test_mutex ]
     [ fiber-test test_lock ]
+ [ fiber-test test_condition ]
+ [ fiber-test test_barrier ]
     [ fiber-test test_auto_reset_event ]
     [ fiber-test test_manual_reset_event ]
     [ fiber-test test_count_down_event ]
- [ fiber-test test_condition ]
     [ fiber-test test_spin_mutex ]
     [ fiber-test test_spin_lock ]
+ [ fiber-test test_spin_condition ]
+ [ fiber-test test_spin_barrier ]
     [ fiber-test test_spin_auto_reset_event ]
     [ fiber-test test_spin_manual_reset_event ]
     [ fiber-test test_spin_count_down_event ]
- [ fiber-test test_spin_condition ]
     ;

Added: sandbox/fiber/libs/fiber/test/test_barrier.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_barrier.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,145 @@
+
+// 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;
+
+void fn_1( boost::fibers::barrier & b)
+{
+ ++value1;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+}
+
+void fn_2( boost::fibers::barrier & b)
+{
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+}
+
+void test_case_1()
+{
+ value1 = 0;
+ value2 = 0;
+
+ boost::fibers::scheduler<> sched;
+
+ boost::fibers::barrier b( sched, 2);
+ sched.make_fiber( fn_1, boost::ref( b) );
+ sched.make_fiber( fn_2, boost::ref( b) );
+
+ 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( 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( 1, 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( 1, value1);
+ BOOST_CHECK_EQUAL( 3, 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( 4, 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( 4, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ 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( 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);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: barrier test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+
+ return test;
+}

Added: sandbox/fiber/libs/fiber/test/test_spin_barrier.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_barrier.cpp 2009-12-10 11:20:26 EST (Thu, 10 Dec 2009)
@@ -0,0 +1,157 @@
+
+// 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;
+
+void fn_1( boost::fibers::spin_barrier & b)
+{
+ ++value1;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+}
+
+void fn_2( boost::fibers::spin_barrier & b)
+{
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+}
+
+void test_case_1()
+{
+ value1 = 0;
+ value2 = 0;
+
+ boost::fibers::scheduler<> sched;
+
+ boost::fibers::spin_barrier b( 2);
+ sched.make_fiber( fn_1, boost::ref( b) );
+ sched.make_fiber( fn_2, boost::ref( b) );
+
+ 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( 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( 1, 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( 1, 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( 1, value1);
+ BOOST_CHECK_EQUAL( 3, 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( 3, 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( 4, 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( 4, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.empty() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+
+ 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( 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);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: spin_barrier test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+
+ 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