diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index cd69bfa5..407db4ad 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -33,7 +33,7 @@ project boost/fiber lib boost_fiber : barrier.cpp condition.cpp - detail/worker_fiber.cpp + detail/fiber_base.cpp detail/scheduler.cpp detail/spinlock.cpp fiber.cpp diff --git a/doc/attributes.qbk b/doc/attributes.qbk index 1a687a25..9f30a2c4 100644 --- a/doc/attributes.qbk +++ b/doc/attributes.qbk @@ -14,7 +14,7 @@ fibers's context. { std::size_t size; flag_unwind_t do_unwind; - flag_fpu_t preserve_fpu; + flag_fpu_t preserve_fpu_; attributes() BOOST_NOEXCEPT; @@ -22,13 +22,13 @@ fibers's context. explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT; - explicit attributes( flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT; + explicit attributes( flag_fpu_t preserve_fpu) BOOST_NOEXCEPT; explicit attributes( std::size_t size_, flag_unwind_t do_unwind_) BOOST_NOEXCEPT; - explicit attributes( std::size_t size_, flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT; + explicit attributes( std::size_t size_, flag_fpu_t preserve_fpu) BOOST_NOEXCEPT; - explicit attributes( flag_unwind_t do_unwind_, flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT; + explicit attributes( flag_unwind_t do_unwind_, flag_fpu_t preserve_fpu) BOOST_NOEXCEPT; }; [member_heading attributes..attributes] @@ -54,9 +54,9 @@ and FPU registers are preserved.]] [[Throws:] [Nothing.]] ] -[heading `attributes( flag_fpu_t preserve_fpu)`] +[heading `attributes( flag_fpu_t preserve_fpu_)`] [variablelist -[[Effects:] [Argument `preserve_fpu` determines if FPU registers have to be +[[Effects:] [Argument `preserve_fpu_` determines if FPU registers have to be preserved if a `context` switches. The default stacksize is used for the inner `context` and the stack will be unwound after termination.]] [[Throws:] [Nothing.]] @@ -69,16 +69,16 @@ FPU registers preserved during each `context` switch.]] [[Throws:] [Nothing.]] ] -[heading `attributes( std::size_t size, flag_fpu_t preserve_fpu)`] +[heading `attributes( std::size_t size, flag_fpu_t preserve_fpu_)`] [variablelist -[[Effects:] [Arguments `size` and `preserve_fpu` are given by the user. +[[Effects:] [Arguments `size` and `preserve_fpu_` are given by the user. The stack is automatically unwound after fiber terminates.]] [[Throws:] [Nothing.]] ] -[heading `attributes( flag_unwind_t do_unwind, flag_fpu_t preserve_fpu)`] +[heading `attributes( flag_unwind_t do_unwind, flag_fpu_t preserve_fpu_)`] [variablelist -[[Effects:] [Arguments `do_unwind` and `preserve_fpu` are given by the user. +[[Effects:] [Arguments `do_unwind` and `preserve_fpu_` are given by the user. The stack gets a default value of `ctx::default_stacksize()`.]] [[Throws:] [Nothing.]] ] diff --git a/examples/cpp03/Jamfile.v2 b/examples/cpp03/Jamfile.v2 index 22b73ec6..9bc8fdbe 100644 --- a/examples/cpp03/Jamfile.v2 +++ b/examples/cpp03/Jamfile.v2 @@ -39,17 +39,16 @@ exe ping_pong : ping_pong.cpp ; exe segmented_stack : segmented_stack.cpp ; exe simple : simple.cpp test_fiber.cpp ; exe migrate_fibers - : migration/migrate_fibers.cpp - migration/workstealing_round_robin.cpp - ; - + : migration/migrate_fibers.cpp + migration/workstealing_round_robin.cpp + ; + exe asio/daytime_client : asio/daytime_client.cpp ; exe asio/daytime_client2 : asio/daytime_client2.cpp ; exe asio/echo_client : asio/echo_client.cpp ; exe asio/echo_client2 : asio/echo_client2.cpp ; exe asio/echo_server : asio/echo_server.cpp ; exe asio/echo_server2 : asio/echo_server2.cpp ; - exe asio/publish_subscribe/server : asio/publish_subscribe/server.cpp ; exe asio/publish_subscribe/publisher : asio/publish_subscribe/publisher.cpp ; exe asio/publish_subscribe/subscriber : asio/publish_subscribe/subscriber.cpp ; diff --git a/examples/cpp03/asio/publish_subscribe/server.cpp b/examples/cpp03/asio/publish_subscribe/server.cpp index f3c3a2e2..be357c7e 100644 --- a/examples/cpp03/asio/publish_subscribe/server.cpp +++ b/examples/cpp03/asio/publish_subscribe/server.cpp @@ -194,6 +194,7 @@ public: cond_.wait( lk); std::string data( data_); lk.unlock(); + std::cout << "subscriber::run(): '" << data << std::endl; // message '' terminates subscription if ( "" == data) break; @@ -206,7 +207,11 @@ public: socket_, boost::asio::buffer( data, data.size() ), yield[ec]); - if ( ec) throw std::runtime_error("publishing message failed"); + if ( ec == boost::asio::error::eof) + break; //connection closed cleanly by peer + else if ( ec) + throw boost::system::system_error( ec); //some other error + std::cout << "subscriber::run(): '" << data << " written" << std::endl; } } catch ( std::exception const& e) diff --git a/examples/cpp03/migration/workstealing_round_robin.cpp b/examples/cpp03/migration/workstealing_round_robin.cpp index 7617cc11..363b22d2 100644 --- a/examples/cpp03/migration/workstealing_round_robin.cpp +++ b/examples/cpp03/migration/workstealing_round_robin.cpp @@ -13,17 +13,17 @@ #endif void -workstealing_round_robin::awakened( boost::fibers::detail::worker_fiber * f) +workstealing_round_robin::awakened( boost::fibers::detail::fiber_base * f) { boost::mutex::scoped_lock lk( mtx_); rqueue_.push_back( f); } -boost::fibers::detail::worker_fiber * +boost::fibers::detail::fiber_base * workstealing_round_robin::pick_next() { boost::mutex::scoped_lock lk( mtx_); - boost::fibers::detail::worker_fiber * f = 0; + boost::fibers::detail::fiber_base * f = 0; if ( ! rqueue_.empty() ) { f = rqueue_.front(); @@ -33,7 +33,7 @@ workstealing_round_robin::pick_next() } void -workstealing_round_robin::priority( boost::fibers::detail::worker_fiber * f, int prio) BOOST_NOEXCEPT +workstealing_round_robin::priority( boost::fibers::detail::fiber_base * f, int prio) BOOST_NOEXCEPT { BOOST_ASSERT( f); @@ -46,7 +46,7 @@ boost::fibers::fiber workstealing_round_robin::steal() BOOST_NOEXCEPT { boost::mutex::scoped_lock lk( mtx_); - boost::fibers::detail::worker_fiber * f = 0; + boost::fibers::detail::fiber_base * f = 0; if ( ! rqueue_.empty() ) { f = rqueue_.back(); diff --git a/examples/cpp03/migration/workstealing_round_robin.hpp b/examples/cpp03/migration/workstealing_round_robin.hpp index c9373c31..a9396105 100644 --- a/examples/cpp03/migration/workstealing_round_robin.hpp +++ b/examples/cpp03/migration/workstealing_round_robin.hpp @@ -11,10 +11,7 @@ #include #include -#include -#include -#include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -28,17 +25,17 @@ class workstealing_round_robin : public boost::fibers::sched_algorithm { private: - typedef std::deque< boost::fibers::detail::worker_fiber * > rqueue_t; + typedef std::deque< boost::fibers::detail::fiber_base * > rqueue_t; boost::mutex mtx_; rqueue_t rqueue_; public: - virtual void awakened( boost::fibers::detail::worker_fiber *); + virtual void awakened( boost::fibers::detail::fiber_base *); - virtual boost::fibers::detail::worker_fiber * pick_next(); + virtual boost::fibers::detail::fiber_base * pick_next(); - virtual void priority( boost::fibers::detail::worker_fiber *, int) BOOST_NOEXCEPT; + virtual void priority( boost::fibers::detail::fiber_base *, int) BOOST_NOEXCEPT; boost::fibers::fiber steal(); }; diff --git a/examples/cpp11/future.cpp b/examples/cpp11/future.cpp deleted file mode 100644 index 9b0256ed..00000000 --- a/examples/cpp11/future.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include - -#include -#include - -#include - -inline -int fn( std::string const& str, int n) -{ - for ( int i = 0; i < n; ++i) - { - std::cout << i << ": " << str << std::endl; - boost::this_fiber::yield(); - } - - return n; -} - -void start() -{ - boost::fibers::future< int > fi( - boost::fibers::async( fn, "abc", 5) ); - fi.wait(); - std::cout << "fn() returned " << fi.get() << std::endl; -} - -int main() -{ - try - { - boost::fibers::fiber( start).join(); - std::cout << "done." << std::endl; - - 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; -} diff --git a/include/boost/fiber/algorithm.hpp b/include/boost/fiber/algorithm.hpp index 9eae1236..0f6d820b 100644 --- a/include/boost/fiber/algorithm.hpp +++ b/include/boost/fiber/algorithm.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -28,11 +28,11 @@ struct sched_algorithm { virtual ~sched_algorithm() {} - virtual void awakened( detail::worker_fiber *) = 0; + virtual void awakened( detail::fiber_base *) = 0; - virtual detail::worker_fiber * pick_next() = 0; + virtual detail::fiber_base * pick_next() = 0; - virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT = 0; + virtual void priority( detail::fiber_base *, int) BOOST_NOEXCEPT = 0; }; }} diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp index 180a1765..eeedb9eb 100644 --- a/include/boost/fiber/condition.hpp +++ b/include/boost/fiber/condition.hpp @@ -72,71 +72,40 @@ public: template< typename LockType > void wait( LockType & lt) { - detail::fiber_base * n( fm_active() ); + detail::fiber_base * f( fm_active() ); try { - if ( n) - { - // lock spinlock - unique_lock< detail::spinlock > lk( splk_); + // lock spinlock + unique_lock< detail::spinlock > lk( splk_); - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - // store this fiber in waiting-queue - // in order notify (resume) this fiber later - waiting_.push_back( n); + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + // store this fiber in waiting-queue + // in order notify (resume) this fiber later + waiting_.push_back( f); - // unlock external - lt.unlock(); + // unlock external + lt.unlock(); - // suspend this fiber - // locked spinlock will be released if this fiber - // was stored inside schedulers's waiting-queue - fm_wait( lk); + // suspend this fiber + // locked spinlock will be released if this fiber + // was stored inside schedulers's waiting-queue + fm_wait( lk); - // this fiber was notified and resumed - // check if fiber was interrupted - this_fiber::interruption_point(); + // this fiber was notified and resumed + // check if fiber was interrupted + this_fiber::interruption_point(); - // lock external again before returning - lt.lock(); - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - // lock spinlock - unique_lock< detail::spinlock > lk( splk_); - - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - // store this main-notifier in waiting-queue - // in order to be notified later - waiting_.push_back( n); - - // unlock external - lt.unlock(); - - // release spinlock - lk.unlock(); - - // loop until main-notifier gets notified - while ( ! n->is_ready() ) - // run scheduler - fm_run(); - - // lock external again before returning - lt.lock(); - } + // lock external again before returning + lt.lock(); } catch (...) { unique_lock< detail::spinlock > lk( splk_); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) + std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); + if ( waiting_.end() != i) { // remove fiber from waiting-list - waiting_.erase( wit ); + waiting_.erase( i); } throw; } @@ -149,17 +118,15 @@ public: chrono::high_resolution_clock::time_point timeout_time( detail::convert_tp( timeout_time_) ); - detail::fiber_base * n( fm_active() ); + detail::fiber_base * f( fm_active() ); try { - if ( n) - { // lock spinlock unique_lock< detail::spinlock > lk( splk_); // store this fiber in waiting-queue // in order notify (resume) this fiber later - waiting_.push_back( n); + waiting_.push_back( f); // unlock external lt.unlock(); @@ -172,7 +139,7 @@ public: // this fiber was not notified before timeout // lock spinlock again unique_lock< detail::spinlock > lk( splk_); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); + std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), f); if (wit != waiting_.end()) { // remove fiber from waiting-list @@ -187,60 +154,15 @@ public: // lock external again before returning lt.lock(); - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - // lock spinlock - unique_lock< detail::spinlock > lk( splk_); - - // store this fiber in order to be notified later - waiting_.push_back( n); - - // unlock external - lt.unlock(); - - // release spinlock - lk.unlock(); - - // loop until main-notifier gets notified - while ( ! n->is_ready() ) - { - // check timepoint - if ( ! ( chrono::high_resolution_clock::now() < timeout_time) ) - { - // timeout happend before notified - // lock spinlock - unique_lock< detail::spinlock > lk( splk_); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) - { - // remove fiber from waiting-list - waiting_.erase(wit); - } - - status = cv_status::timeout; - break; - } - // run scheduler - fm_run(); - } - - // lock external again before returning - lt.lock(); - } } catch (...) { unique_lock< detail::spinlock > lk( splk_); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) + std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); + if ( waiting_.end() != i) { // remove fiber from waiting-list - waiting_.erase( wit ); + waiting_.erase( i); } throw; } diff --git a/include/boost/fiber/detail/fiber_base.hpp b/include/boost/fiber/detail/fiber_base.hpp index 00e11eb6..840d2b8e 100644 --- a/include/boost/fiber/detail/fiber_base.hpp +++ b/include/boost/fiber/detail/fiber_base.hpp @@ -7,16 +7,24 @@ #ifndef BOOST_FIBERS_DETAIL_FIBER_BASE_H #define BOOST_FIBERS_DETAIL_FIBER_BASE_H -//#include #include #include +#include +#include #include #include +#include #include +#include +#include +#include #include #include +#include +#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -33,6 +41,48 @@ namespace detail { class BOOST_FIBERS_DECL fiber_base : private noncopyable { +private: + enum state_t + { + READY = 0, + RUNNING, + WAITING, + TERMINATED + }; + + struct BOOST_FIBERS_DECL fss_data + { + void * vp; + fss_cleanup_function::ptr_t cleanup_function; + + fss_data() : + vp( 0), cleanup_function( 0) + {} + + fss_data( void * vp_, fss_cleanup_function::ptr_t const& fn) : + vp( vp_), cleanup_function( fn) + { BOOST_ASSERT( cleanup_function); } + + void do_cleanup() + { ( * cleanup_function)( vp); } + }; + + typedef std::map< uintptr_t, fss_data > fss_data_t; + + atomic< std::size_t > use_count_; + context::fcontext_t ctx_; + fss_data_t fss_data_; + fiber_base * nxt_; + chrono::high_resolution_clock::time_point tp_; + atomic< state_t > state_; + atomic< int > flags_; + atomic< int > priority_; + spinlock splk_; + std::vector< fiber_base * > waiting_; + +protected: + exception_ptr except_; + public: class id { @@ -83,16 +133,149 @@ public: { return 0 == impl_; } }; - fiber_base() + fiber_base( context::fcontext_t ctx) : + use_count_( 1), // allocated on stack + ctx_( ctx), + fss_data_(), + nxt_( 0), + tp_( (chrono::high_resolution_clock::time_point::max)() ), + state_( READY), + flags_( 0), + priority_( 0), + waiting_(), + except_() {} - virtual ~fiber_base() {}; + virtual ~fiber_base() + { + BOOST_ASSERT( is_terminated() ); + BOOST_ASSERT( waiting_.empty() ); + } - virtual bool is_ready() const BOOST_NOEXCEPT = 0; + id get_id() const BOOST_NOEXCEPT + { return id( const_cast< fiber_base * >( this) ); } - virtual void set_ready() BOOST_NOEXCEPT = 0; + int priority() const BOOST_NOEXCEPT + { return priority_; } - virtual id get_id() const BOOST_NOEXCEPT = 0; + void priority( int prio) BOOST_NOEXCEPT + { priority_ = prio; } + + bool join( fiber_base *); + + bool interruption_blocked() const BOOST_NOEXCEPT + { return 0 != ( flags_.load() & flag_interruption_blocked); } + + void interruption_blocked( bool blck) BOOST_NOEXCEPT; + + bool interruption_requested() const BOOST_NOEXCEPT + { return 0 != ( flags_.load() & flag_interruption_requested); } + + void request_interruption( bool req) BOOST_NOEXCEPT; + + bool thread_affinity() const BOOST_NOEXCEPT + { return 0 != ( flags_.load() & flag_thread_affinity); } + + void thread_affinity( bool req) BOOST_NOEXCEPT; + + bool is_terminated() const BOOST_NOEXCEPT + { return TERMINATED == state_; } + + bool is_ready() const BOOST_NOEXCEPT + { return READY == state_; } + + bool is_running() const BOOST_NOEXCEPT + { return RUNNING == state_; } + + bool is_waiting() const BOOST_NOEXCEPT + { return WAITING == state_; } + + void set_terminated() BOOST_NOEXCEPT + { + state_t previous = state_.exchange( TERMINATED); + BOOST_ASSERT( RUNNING == previous); + (void)previous; + } + + void set_ready() BOOST_NOEXCEPT + { + state_t previous = state_.exchange( READY); + BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous); + (void)previous; + } + + void set_running() BOOST_NOEXCEPT + { + state_t previous = state_.exchange( RUNNING); + BOOST_ASSERT( READY == previous); + (void)previous; + } + + void set_waiting() BOOST_NOEXCEPT + { + state_t previous = state_.exchange( WAITING); + BOOST_ASSERT( RUNNING == previous); + (void)previous; + } + + void * get_fss_data( void const* vp) const; + + void set_fss_data( + void const* vp, + fss_cleanup_function::ptr_t const& cleanup_fn, + void * data, + bool cleanup_existing); + + exception_ptr get_exception() const BOOST_NOEXCEPT + { return except_; } + + void set_exception( exception_ptr except) BOOST_NOEXCEPT + { except_ = except; } + + void resume( fiber_base * current, bool preserve_fpu_) + { + BOOST_ASSERT( 0 != current); + BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm + + context::jump_fcontext( + & current->ctx_, ctx_, reinterpret_cast< intptr_t >( this), preserve_fpu_); + } + + fiber_base * next() const BOOST_NOEXCEPT + { return nxt_; } + + void next( fiber_base * nxt) BOOST_NOEXCEPT + { nxt_ = nxt; } + + void next_reset() BOOST_NOEXCEPT + { nxt_ = 0; } + + chrono::high_resolution_clock::time_point const& time_point() const BOOST_NOEXCEPT + { return tp_; } + + void time_point( chrono::high_resolution_clock::time_point const& tp) + { tp_ = tp; } + + void time_point_reset() + { tp_ = (chrono::high_resolution_clock::time_point::max)(); } + + void release(); + + virtual void deallocate() = 0; + + friend void intrusive_ptr_add_ref( fiber_base * f) + { ++f->use_count_; } + + friend void intrusive_ptr_release( fiber_base * f) + { + BOOST_ASSERT( 0 != f); + + if ( 0 == --f->use_count_) + { + BOOST_ASSERT( f->is_terminated() ); + f->deallocate(); + } + } }; }}} diff --git a/include/boost/fiber/detail/fifo.hpp b/include/boost/fiber/detail/fifo.hpp index adf5aceb..afae711e 100644 --- a/include/boost/fiber/detail/fifo.hpp +++ b/include/boost/fiber/detail/fifo.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -36,7 +36,7 @@ public: bool empty() const BOOST_NOEXCEPT { return 0 == head_; } - void push( worker_fiber * item) BOOST_NOEXCEPT + void push( fiber_base * item) BOOST_NOEXCEPT { BOOST_ASSERT( 0 != item); BOOST_ASSERT( 0 == item->next() ); @@ -50,11 +50,11 @@ public: } } - worker_fiber * pop() BOOST_NOEXCEPT + fiber_base * pop() BOOST_NOEXCEPT { BOOST_ASSERT( ! empty() ); - worker_fiber * item = head_; + fiber_base * item = head_; head_ = head_->next(); if ( 0 == head_) tail_ = 0; item->next_reset(); @@ -68,8 +68,8 @@ public: } private: - worker_fiber * head_; - worker_fiber * tail_; + fiber_base * head_; + fiber_base * tail_; }; }}} diff --git a/include/boost/fiber/detail/main_fiber.hpp b/include/boost/fiber/detail/main_fiber.hpp index baeeff96..17014c85 100644 --- a/include/boost/fiber/detail/main_fiber.hpp +++ b/include/boost/fiber/detail/main_fiber.hpp @@ -23,29 +23,14 @@ namespace detail { class main_fiber : public fiber_base { public: - static main_fiber * make_pointer( main_fiber & n) { - return & n; + main_fiber() : + fiber_base( 0) // main-fiber represents main-context + { + thread_affinity( true); + set_running(); } - main_fiber() : - fiber_base(), - ready_( false) - {} - - bool is_ready() const BOOST_NOEXCEPT - { return ready_; } - - void set_ready() BOOST_NOEXCEPT - { ready_ = true; } - - id get_id() const BOOST_NOEXCEPT - { return id( const_cast< main_fiber * >( this) ); } - -private: - atomic< bool > ready_; - - main_fiber( main_fiber const&); - main_fiber & operator=( main_fiber const&); + void deallocate() {} }; }}} diff --git a/include/boost/fiber/detail/scheduler.hpp b/include/boost/fiber/detail/scheduler.hpp index 4b9f5c64..e8883c37 100644 --- a/include/boost/fiber/detail/scheduler.hpp +++ b/include/boost/fiber/detail/scheduler.hpp @@ -141,7 +141,7 @@ private: public: template< typename F > - static worker_fiber * extract( F const& f) BOOST_NOEXCEPT + static fiber_base * extract( F const& f) BOOST_NOEXCEPT { return f.impl_.get(); } static fiber_manager * instance() diff --git a/include/boost/fiber/detail/setup.hpp b/include/boost/fiber/detail/setup.hpp deleted file mode 100644 index 7f93d9d3..00000000 --- a/include/boost/fiber/detail/setup.hpp +++ /dev/null @@ -1,80 +0,0 @@ - -// 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_DETAIL_SETUP_H -#define BOOST_FIBERS_DETAIL_SETUP_H - -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename Fn > -struct setup -{ - typedef typename worker_fiber::coro_t coro_t; - - struct dummy {}; - - Fn fn; - typename coro_t::call_type * caller; - worker_fiber * f; - -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - setup( Fn fn_, - coro_t::call_type * caller_) : - fn( boost::forward< Fn >( fn_) ), - caller( caller_), - f( 0) - { BOOST_ASSERT( 0 != caller); } -#endif - - setup( BOOST_RV_REF( Fn) fn_, - coro_t::call_type * caller_, - typename disable_if< - is_same< typename decay< Fn >::type, setup >, - dummy* - >::type = 0) : -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - fn( fn_), -#else - fn( boost::forward< Fn >( fn_) ), -#endif - caller( caller_), - f( 0) - { BOOST_ASSERT( 0 != caller); } - - worker_fiber * allocate() - { - // enter fiber-fn (trampoline<>) - // and pas this as argument - ( * caller)( this); - // jumped back; move coroutine to worker_fiber - f->caller_ = boost::move( * caller); - return f; - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_SETUP_H diff --git a/include/boost/fiber/detail/trampoline.hpp b/include/boost/fiber/detail/trampoline.hpp deleted file mode 100644 index b9025c7b..00000000 --- a/include/boost/fiber/detail/trampoline.hpp +++ /dev/null @@ -1,92 +0,0 @@ - -// 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_DETAIL_TRAMPOLINE_H -#define BOOST_FIBERS_DETAIL_TRAMPOLINE_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -namespace coro = boost::coroutines; - -template< typename Fn > -void trampoline( typename worker_fiber::coro_t::yield_type & yield) -{ - BOOST_ASSERT( yield); - - void * p( yield.get() ); - BOOST_ASSERT( p); - setup< Fn > * from( static_cast< setup< Fn > * >( p) ); - - // allocate instance of worker-fiber on its stack - worker_fiber f( & yield); - // return address of worker-fiber instance - from->f = & f; - - try - { - // allocate fiber-function on worker-fiber's stack -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - Fn fn( boost::forward< Fn >( from->fn) ); -#else - Fn fn( boost::move( from->fn) ); -#endif - - // after setup return to caller - f.set_running(); - f.suspend(); - - // start executing fiber-function - BOOST_ASSERT( f.is_running() ); - fn(); - BOOST_ASSERT( f.is_running() ); - } - catch ( coro::detail::forced_unwind const&) - { - f.set_terminated(); - f.release(); - throw; - } - catch ( fiber_interrupted const&) - { f.set_exception( current_exception() ); } - catch (...) - { std::terminate(); } - - f.set_terminated(); - f.release(); - f.suspend(); - - BOOST_ASSERT_MSG( false, "fiber already terminated"); -} - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_TRAMPOLINE_H diff --git a/include/boost/fiber/detail/waiting_queue.hpp b/include/boost/fiber/detail/waiting_queue.hpp index e53f9632..06f79bfe 100644 --- a/include/boost/fiber/detail/waiting_queue.hpp +++ b/include/boost/fiber/detail/waiting_queue.hpp @@ -16,7 +16,7 @@ #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -37,7 +37,7 @@ public: bool empty() const BOOST_NOEXCEPT { return 0 == head_; } - void push( worker_fiber * item) BOOST_NOEXCEPT + void push( fiber_base * item) BOOST_NOEXCEPT { BOOST_ASSERT( 0 != item); BOOST_ASSERT( 0 == item->next() ); @@ -46,10 +46,10 @@ public: head_ = tail_ = item; else { - worker_fiber * f = head_, * prev = 0; + fiber_base * f = head_, * prev = 0; do { - worker_fiber * nxt = f->next(); + fiber_base * nxt = f->next(); if ( item->time_point() <= f->time_point() ) { if ( head_ == f) @@ -84,7 +84,7 @@ public: } } - worker_fiber * top() const BOOST_NOEXCEPT + fiber_base * top() const BOOST_NOEXCEPT { BOOST_ASSERT( ! empty() ); @@ -96,11 +96,11 @@ public: { BOOST_ASSERT( sched_algo); - worker_fiber * f = head_, * prev = 0; + fiber_base * f = head_, * prev = 0; chrono::high_resolution_clock::time_point now( chrono::high_resolution_clock::now() ); while ( 0 != f) { - worker_fiber * nxt = f->next(); + fiber_base * nxt = f->next(); if ( fn( f, now) ) { if ( f == head_) @@ -137,8 +137,8 @@ public: } private: - worker_fiber * head_; - worker_fiber * tail_; + fiber_base * head_; + fiber_base * tail_; }; }}} diff --git a/include/boost/fiber/detail/worker_fiber.hpp b/include/boost/fiber/detail/worker_fiber.hpp index ed5c139b..9ec4ed4e 100644 --- a/include/boost/fiber/detail/worker_fiber.hpp +++ b/include/boost/fiber/detail/worker_fiber.hpp @@ -7,28 +7,19 @@ #ifndef BOOST_FIBERS_DETAIL_WORKER_FIBER_H #define BOOST_FIBERS_DETAIL_WORKER_FIBER_H -#include -#include -#include +#include // std::terminate() #include -#include -#include #include #include -#include -#include -#include +#include #include -#include -#include #include #include -#include -#include -#include #include +#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -43,219 +34,87 @@ namespace boost { namespace fibers { namespace detail { -namespace coro = boost::coroutines; - -class BOOST_FIBERS_DECL worker_fiber : public fiber_base +template< typename Fn, typename StackAllocator > +class worker_fiber : public fiber_base { -public: - typedef coro::symmetric_coroutine< - void * - > coro_t; - private: - template< typename Fn > - friend struct setup; + Fn fn_; + StackAllocator salloc_; + stack_context sctx_; - enum state_t + void run_() { - READY = 0, - RUNNING, - WAITING, - TERMINATED - }; - - struct BOOST_FIBERS_DECL fss_data - { - void * vp; - fss_cleanup_function::ptr_t cleanup_function; - - fss_data() : - vp( 0), cleanup_function( 0) + try + { + BOOST_ASSERT( is_running() ); + fn_(); + BOOST_ASSERT( is_running() ); + } +#if 0 + catch( forced_unwind const&) {} - - fss_data( - void * vp_, - fss_cleanup_function::ptr_t const& fn) : - vp( vp_), cleanup_function( fn) - { BOOST_ASSERT( cleanup_function); } - - void do_cleanup() - { ( * cleanup_function)( vp); } - }; - - typedef std::map< uintptr_t, fss_data > fss_data_t; - - static void * null_ptr; - - atomic< std::size_t > use_count_; - fss_data_t fss_data_; - worker_fiber * nxt_; - chrono::high_resolution_clock::time_point tp_; - coro_t::yield_type * callee_; - coro_t::call_type caller_; - atomic< state_t > state_; - atomic< int > flags_; - atomic< int > priority_; - exception_ptr except_; - spinlock splk_; - std::vector< worker_fiber * > waiting_; +#endif + catch( fiber_interrupted const& ) + { + except_ = current_exception(); + } + catch( ... ) + { + std::terminate(); + } + set_terminated(); + release(); // notify joining fibers + fibers::fm_run(); + BOOST_ASSERT_MSG( false, "fiber already terminated"); + } public: - worker_fiber( coro_t::yield_type *); + static void entry_func( intptr_t); - ~worker_fiber(); +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + worker_fiber( Fn fn, void * sp, std::size_t size, + StackAllocator const& salloc, stack_context const& sctx) : + fiber_base( context::make_fcontext( sp, size, & worker_fiber::entry_func) ), + fn_( boost::forward< Fn >( fn) ), + salloc_( salloc), + sctx_( sctx) + {} +#endif - id get_id() const BOOST_NOEXCEPT - { return id( const_cast< worker_fiber * >( this) ); } - - int priority() const BOOST_NOEXCEPT - { return priority_; } - - void priority( int prio) BOOST_NOEXCEPT - { priority_ = prio; } - - bool join( worker_fiber *); - - bool interruption_blocked() const BOOST_NOEXCEPT - { return 0 != ( flags_.load() & flag_interruption_blocked); } - - void interruption_blocked( bool blck) BOOST_NOEXCEPT; - - bool interruption_requested() const BOOST_NOEXCEPT - { return 0 != ( flags_.load() & flag_interruption_requested); } - - void request_interruption( bool req) BOOST_NOEXCEPT; - - bool thread_affinity() const BOOST_NOEXCEPT - { return 0 != ( flags_.load() & flag_thread_affinity); } - - void thread_affinity( bool req) BOOST_NOEXCEPT; - - bool is_terminated() const BOOST_NOEXCEPT - { return TERMINATED == state_; } - - bool is_ready() const BOOST_NOEXCEPT - { return READY == state_; } - - bool is_running() const BOOST_NOEXCEPT - { return RUNNING == state_; } - - bool is_waiting() const BOOST_NOEXCEPT - { return WAITING == state_; } - - void set_terminated() BOOST_NOEXCEPT - { - state_t previous = state_.exchange( TERMINATED); - BOOST_ASSERT( RUNNING == previous); - (void)previous; - } - - void set_ready() BOOST_NOEXCEPT - { - state_t previous = state_.exchange( READY); - BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous); - (void)previous; - } - - void set_running() BOOST_NOEXCEPT - { - state_t previous = state_.exchange( RUNNING); - BOOST_ASSERT( READY == previous); - (void)previous; - } - - void set_waiting() BOOST_NOEXCEPT - { - state_t previous = state_.exchange( WAITING); - BOOST_ASSERT( RUNNING == previous); - (void)previous; - } - - void * get_fss_data( void const* vp) const; - - void set_fss_data( - void const* vp, - fss_cleanup_function::ptr_t const& cleanup_fn, - void * data, - bool cleanup_existing); - - exception_ptr get_exception() const BOOST_NOEXCEPT - { return except_; } - - void set_exception( exception_ptr except) BOOST_NOEXCEPT - { except_ = except; } - - void resume( worker_fiber * f) - { - BOOST_ASSERT( caller_); - BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm - - if ( 0 == f) - { - // called from main-fiber - caller_( null_ptr); - } - else - { - // caller from worker-fiber f - BOOST_ASSERT( f->callee_); - - ( * f->callee_)( caller_, null_ptr); - } - } - - void suspend() - { - BOOST_ASSERT( callee_); - BOOST_ASSERT( * callee_); - - ( * callee_)(); - - BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm - } - - worker_fiber * next() const BOOST_NOEXCEPT - { return nxt_; } - - void next( worker_fiber * nxt) BOOST_NOEXCEPT - { nxt_ = nxt; } - - void next_reset() BOOST_NOEXCEPT - { nxt_ = 0; } - - chrono::high_resolution_clock::time_point const& time_point() const BOOST_NOEXCEPT - { return tp_; } - - void time_point( chrono::high_resolution_clock::time_point const& tp) - { tp_ = tp; } - - void time_point_reset() - { tp_ = (chrono::high_resolution_clock::time_point::max)(); } - - void release(); + worker_fiber( BOOST_RV_REF( Fn) fn, void * sp, std::size_t size, + StackAllocator const& salloc, stack_context const& sctx) : + fiber_base( context::make_fcontext( sp, size, & worker_fiber::entry_func) ), +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + fn_( fn), +#else + fn_( boost::forward< Fn >( fn) ), +#endif + salloc_( salloc), + sctx_( sctx) + {} void deallocate() { - callee_ = 0; - // destroyes coroutine and deallocates stack - coro_t::call_type tmp( boost::move( caller_) ); - } - - friend void intrusive_ptr_add_ref( worker_fiber * f) - { ++f->use_count_; } - - friend void intrusive_ptr_release( worker_fiber * f) - { - BOOST_ASSERT( 0 != f); - - if ( 0 == --f->use_count_) - { - BOOST_ASSERT( f->is_terminated() ); - f->deallocate(); - } + // FIXME: correct? + StackAllocator salloc( salloc_); + stack_context sctx( sctx_); + // call destructor of worker_fiber + this->~worker_fiber(); + // deallocate stack + salloc.deallocate( sctx); } }; +template< typename Fn, typename StackAllocator > +void +worker_fiber< Fn, StackAllocator >::entry_func( intptr_t param) +{ + worker_fiber< Fn, StackAllocator > * f( + reinterpret_cast< worker_fiber< Fn, StackAllocator > * >( param) ); + BOOST_ASSERT( 0 != f); + f->run_(); +} + }}} # if defined(BOOST_MSVC) diff --git a/include/boost/fiber/fiber.hpp b/include/boost/fiber/fiber.hpp index ab995b92..0fb318c8 100644 --- a/include/boost/fiber/fiber.hpp +++ b/include/boost/fiber/fiber.hpp @@ -9,12 +9,11 @@ #include #include -#include +#include // std::terminate() #include #include #include -#include #include #include #include // boost::allocator_arg_t @@ -23,10 +22,10 @@ #include #include -#include -#include +#include #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -40,8 +39,6 @@ namespace boost { namespace fibers { -namespace coro = boost::coroutines; - namespace detail { class scheduler; @@ -53,8 +50,7 @@ class BOOST_FIBERS_DECL fiber : private noncopyable private: friend class detail::scheduler; - typedef detail::worker_fiber base_t; - typedef base_t::coro_t coro_t; + typedef detail::fiber_base base_t; typedef intrusive_ptr< base_t > ptr_t; ptr_t impl_; @@ -65,49 +61,73 @@ private: typedef void ( * fiber_fn)(); template< typename StackAllocator > - void setup_( StackAllocator const& stack_alloc, attributes const& attrs, fiber_fn fn) + base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, fiber_fn fn) { - coro_t::call_type coro( detail::trampoline< fiber_fn >, attrs, stack_alloc); - detail::setup< fiber_fn > s( boost::forward< fiber_fn >( fn), & coro); - impl_.reset( s.allocate() ); - BOOST_ASSERT( impl_); + typedef detail::worker_fiber< fiber_fn, StackAllocator > wrk_t; + + // create a stack-context + stack_context sctx; + // allocate fiber-stack + salloc.allocate( sctx, attrs.size); + BOOST_ASSERT( 0 < sctx.sp); + // reserve space for worker_fiber on top of stack + std::size_t size = sctx.size - sizeof( wrk_t); + void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t); + // placement new for worker_fiber + return new( sp) wrk_t( boost::forward< fiber_fn >( fn), sp, size, salloc, sctx); } #endif #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename StackAllocator, typename Fn > - void setup_( StackAllocator const& stack_alloc, attributes const& attrs, Fn fn) + base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, Fn fn) { - typename coro_t::call_type coro( detail::trampoline< Fn >, attrs, stack_alloc); - detail::setup< Fn > s( boost::forward< Fn >( fn), & coro); - impl_.reset( s.allocate() ); - BOOST_ASSERT( impl_); + typedef detail::worker_fiber< Fn, StackAllocator > wrk_t; + + // create a stack-context + stack_context sctx; + // allocate fiber-stack + salloc.allocate( sctx, attrs.size); + BOOST_ASSERT( 0 < sctx.sp); + // reserve space for worker_fiber on top of stack + std::size_t size = sctx.size - sizeof( wrk_t); + void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t); + // placement new for worker_fiber + return new( sp) wrk_t( boost::forward< Fn >( fn), sp, size, salloc, sctx); } #endif template< typename StackAllocator, typename Fn > - void setup_( StackAllocator const& stack_alloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) + base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) { - typename coro_t::call_type coro( detail::trampoline< Fn >, attrs, stack_alloc); + typedef detail::worker_fiber< Fn, StackAllocator > wrk_t; + + // create a stack-context + stack_context sctx; + // allocate fiber-stack + salloc.allocate( sctx, attrs.size); + BOOST_ASSERT( 0 < sctx.sp); + // reserve space for worker_fiber on top of stack + std::size_t size = sctx.size - sizeof( wrk_t); + void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t); + // placement new for worker_fiber #ifdef BOOST_NO_RVALUE_REFERENCES - detail::setup< Fn > s( fn, & coro); + return new( sp) wrk_t( fn, sp, size, salloc, sctx); #else - detail::setup< Fn > s( boost::forward< Fn >( fn), & coro); + return new( sp) wrk_t( boost::forward< Fn >( fn), sp, size, salloc, sctx); #endif - impl_.reset( s.allocate() ); - BOOST_ASSERT( impl_); } void start_(); public: - typedef detail::worker_fiber::id id; + typedef detail::fiber_base::id id; fiber() BOOST_NOEXCEPT : impl_() {} - explicit fiber( detail::worker_fiber * impl) BOOST_NOEXCEPT : + explicit fiber( detail::fiber_base * impl) BOOST_NOEXCEPT : impl_( impl) {} @@ -116,33 +136,33 @@ public: impl_() { attributes attrs; - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, fn); + stack_allocator salloc; + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } fiber( attributes const& attrs, fiber_fn fn) : impl_() { - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, fn); + stack_allocator salloc; + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } template< typename StackAllocator > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, fiber_fn fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, fiber_fn fn) : impl_() { attributes attrs; - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } template< typename StackAllocator > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, fiber_fn fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, fiber_fn fn) : impl_() { - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } #endif @@ -153,8 +173,8 @@ public: impl_() { attributes attrs; - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, fn); + stack_allocator salloc; + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } @@ -162,25 +182,25 @@ public: fiber( attributes const& attrs, Fn fn) : impl_() { - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, fn); + stack_allocator salloc; + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } template< typename StackAllocator, typename Fn > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, Fn fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, Fn fn) : impl_() { attributes attrs; - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } template< typename StackAllocator, typename Fn > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, Fn fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, Fn fn) : impl_() { - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); start_(); } #endif @@ -190,11 +210,11 @@ public: impl_() { attributes attrs; - stack_allocator stack_alloc; + stack_allocator salloc; #ifdef BOOST_NO_RVALUE_REFERENCES - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); #else - setup_( stack_alloc, attrs, boost::forward< Fn >( fn) ); + impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) ); #endif start_(); } @@ -203,36 +223,36 @@ public: fiber( attributes const& attrs, BOOST_RV_REF( Fn) fn) : impl_() { - stack_allocator stack_alloc; + stack_allocator salloc; #ifdef BOOST_NO_RVALUE_REFERENCES - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); #else - setup_( stack_alloc, attrs, boost::forward< Fn >( fn) ); + impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) ); #endif start_(); } template< typename StackAllocator, typename Fn > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, BOOST_RV_REF( Fn) fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, BOOST_RV_REF( Fn) fn) : impl_() { attributes attrs; #ifdef BOOST_NO_RVALUE_REFERENCES - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); #else - setup_( stack_alloc, attrs, boost::forward< Fn >( fn) ); + impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) ); #endif start_(); } template< typename StackAllocator, typename Fn > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) : + fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) : impl_() { #ifdef BOOST_NO_RVALUE_REFERENCES - setup_( stack_alloc, attrs, fn); + impl_.reset( make_fiber_( salloc, attrs, fn) ); #else - setup_( stack_alloc, attrs, boost::forward< Fn >( fn) ); + impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) ); #endif start_(); } @@ -243,8 +263,9 @@ public: impl_() { attributes attrs; - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ); + stack_allocator salloc; + impl_.reset( + make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) ); start_(); } @@ -252,26 +273,29 @@ public: fiber( attributes const& attrs, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) : impl_() { - stack_allocator stack_alloc; - setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ); + stack_allocator salloc; + impl_.reset( + make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) ); start_(); } template< typename StackAllocator, typename Fn, class ... Args > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) : + fiber( boost::allocator_arg_t, StackAllocator salloc, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) : impl_() { attributes attrs; - setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ); + impl_.reset( + make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) ); start_(); } template< typename StackAllocator, typename Fn, class ... Args > - fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, + fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) : impl_() { - setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ); + impl_.reset( + make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) ); start_(); } #endif diff --git a/include/boost/fiber/fiber_manager.hpp b/include/boost/fiber/fiber_manager.hpp index e991f38e..98c3b13c 100644 --- a/include/boost/fiber/fiber_manager.hpp +++ b/include/boost/fiber/fiber_manager.hpp @@ -16,11 +16,10 @@ #include #include #include +#include #include #include #include -#include -#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -42,21 +41,22 @@ struct fiber_manager : private noncopyable typedef detail::waiting_queue wqueue_t; - scoped_ptr< sched_algorithm > def_algo_; - sched_algorithm * sched_algo_; - wqueue_t wqueue_; - - chrono::high_resolution_clock::duration wait_interval_; - detail::worker_fiber * active_fiber_; + scoped_ptr< sched_algorithm > def_algo; + sched_algorithm * sched_algo; + wqueue_t wqueue; + bool preserve_fpu; + detail::main_fiber main_fiber_; + chrono::high_resolution_clock::duration wait_interval; + detail::fiber_base * active_fiber; }; -void fm_resume_( detail::worker_fiber *); +void fm_resume_( detail::fiber_base *); void fm_set_sched_algo( sched_algorithm *); -void fm_spawn( detail::worker_fiber *); +void fm_spawn( detail::fiber_base *); -void fm_priority( detail::worker_fiber *, int) BOOST_NOEXCEPT; +void fm_priority( detail::fiber_base *, int) BOOST_NOEXCEPT; void fm_wait_interval( chrono::high_resolution_clock::duration const&) BOOST_NOEXCEPT; template< typename Rep, typename Period > @@ -65,9 +65,9 @@ void fm_wait_interval( chrono::duration< Rep, Period > const& wait_interval) BOO chrono::high_resolution_clock::duration fm_wait_interval() BOOST_NOEXCEPT; -void fm_join( detail::worker_fiber *); +void fm_join( detail::fiber_base *); -detail::worker_fiber * fm_active() BOOST_NOEXCEPT; +detail::fiber_base * fm_active() BOOST_NOEXCEPT; void fm_run(); @@ -96,7 +96,10 @@ void fm_yield(); chrono::high_resolution_clock::time_point fm_next_wakeup(); -void fm_migrate( detail::worker_fiber *); +void fm_migrate( detail::fiber_base *); + +bool fm_preserve_fpu_(); +void fm_preserve_fpu_( bool); }} diff --git a/include/boost/fiber/mutex.hpp b/include/boost/fiber/mutex.hpp index 33c60a9f..a10c850f 100644 --- a/include/boost/fiber/mutex.hpp +++ b/include/boost/fiber/mutex.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -40,7 +40,7 @@ private: detail::spinlock splk_; state_t state_; - detail::worker_fiber::id owner_; + detail::fiber_base::id owner_; std::deque< detail::fiber_base * > waiting_; bool lock_if_unlocked_(); diff --git a/include/boost/fiber/recursive_mutex.hpp b/include/boost/fiber/recursive_mutex.hpp index 607337f6..03effd33 100644 --- a/include/boost/fiber/recursive_mutex.hpp +++ b/include/boost/fiber/recursive_mutex.hpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include @@ -43,7 +43,7 @@ private: detail::spinlock splk_; state_t state_; - detail::worker_fiber::id owner_; + detail::fiber_base::id owner_; std::size_t count_; std::deque< detail::fiber_base * > waiting_; diff --git a/include/boost/fiber/recursive_timed_mutex.hpp b/include/boost/fiber/recursive_timed_mutex.hpp index b740b92a..20706ef8 100644 --- a/include/boost/fiber/recursive_timed_mutex.hpp +++ b/include/boost/fiber/recursive_timed_mutex.hpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -45,7 +45,7 @@ private: detail::spinlock splk_; state_t state_; - detail::worker_fiber::id owner_; + detail::fiber_base::id owner_; std::size_t count_; std::deque< detail::fiber_base * > waiting_; diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp index 09f7d5ef..532f6e56 100644 --- a/include/boost/fiber/round_robin.hpp +++ b/include/boost/fiber/round_robin.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -33,11 +33,11 @@ private: rqueue_t rqueue_; public: - virtual void awakened( detail::worker_fiber *); + virtual void awakened( detail::fiber_base *); - virtual detail::worker_fiber * pick_next(); + virtual detail::fiber_base * pick_next(); - virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT; + virtual void priority( detail::fiber_base *, int) BOOST_NOEXCEPT; }; }} diff --git a/include/boost/fiber/stack_context.hpp b/include/boost/fiber/stack_context.hpp new file mode 100644 index 00000000..a65bce33 --- /dev/null +++ b/include/boost/fiber/stack_context.hpp @@ -0,0 +1,32 @@ + +// 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_STACK_CONTEXT_H +#define BOOST_FIBERS_STACK_CONTEXT_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace fibers { + +typedef coroutines::stack_context stack_context; + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_FIBERS_STACK_CONTEXT_H diff --git a/include/boost/fiber/timed_mutex.hpp b/include/boost/fiber/timed_mutex.hpp index 819645e4..dfb502bf 100644 --- a/include/boost/fiber/timed_mutex.hpp +++ b/include/boost/fiber/timed_mutex.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -42,7 +42,7 @@ private: detail::spinlock splk_; state_t state_; - detail::worker_fiber::id owner_; + detail::fiber_base::id owner_; std::deque< detail::fiber_base * > waiting_; bool lock_if_unlocked_(); diff --git a/performance/fiber/overhead_detach.cpp b/performance/fiber/overhead_detach.cpp index 6ed13315..830f524f 100644 --- a/performance/fiber/overhead_detach.cpp +++ b/performance/fiber/overhead_detach.cpp @@ -26,7 +26,7 @@ #define DETACH(z, n, _) \ boost::fibers::fiber(boost::allocator_arg, stack_alloc, attrs, worker).detach(); -boost::coroutines::flag_fpu_t preserve_fpu = boost::coroutines::fpu_not_preserved; +boost::coroutines::flag_fpu_t preserve_fpu_ = boost::coroutines::fpu_not_preserved; boost::coroutines::flag_unwind_t unwind_stack = boost::coroutines::no_stack_unwind; bool prealloc = false; bool preserve = false; @@ -37,7 +37,7 @@ void worker() {} template< typename StackAllocator > duration_type measure( duration_type overhead, StackAllocator const& stack_alloc) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( boost::allocator_arg, stack_alloc, attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -90,7 +90,7 @@ int main( int argc, char * argv[]) return EXIT_SUCCESS; } - if ( preserve) preserve_fpu = boost::coroutines::fpu_preserved; + if ( preserve) preserve_fpu_ = boost::coroutines::fpu_preserved; if ( unwind) unwind_stack = boost::coroutines::stack_unwind; duration_type overhead = overhead_clock(); diff --git a/performance/fiber/overhead_future.cpp b/performance/fiber/overhead_future.cpp index 4b4e7247..d5c46d47 100644 --- a/performance/fiber/overhead_future.cpp +++ b/performance/fiber/overhead_future.cpp @@ -23,7 +23,7 @@ #define JOBS BOOST_PP_LIMIT_REPEAT #endif -boost::coroutines::flag_fpu_t preserve_fpu = boost::coroutines::fpu_not_preserved; +boost::coroutines::flag_fpu_t preserve_fpu_ = boost::coroutines::fpu_not_preserved; boost::coroutines::flag_unwind_t unwind_stack = boost::coroutines::no_stack_unwind; bool prealloc = false; bool preserve = false; @@ -43,7 +43,7 @@ void test_future( boost::fibers::attributes const& attrs, StackAllocator const& template< typename StackAllocator > duration_type measure( duration_type overhead, StackAllocator const& stack_alloc) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); test_future( attrs, stack_alloc); time_point_type start( clock_type::now() ); @@ -96,7 +96,7 @@ int main( int argc, char * argv[]) return EXIT_SUCCESS; } - if ( preserve) preserve_fpu = boost::coroutines::fpu_preserved; + if ( preserve) preserve_fpu_ = boost::coroutines::fpu_preserved; if ( unwind) unwind_stack = boost::coroutines::stack_unwind; duration_type overhead = overhead_clock(); diff --git a/performance/fiber/overhead_join.cpp b/performance/fiber/overhead_join.cpp index 929e292c..c700d1d9 100644 --- a/performance/fiber/overhead_join.cpp +++ b/performance/fiber/overhead_join.cpp @@ -26,7 +26,7 @@ #define JOIN(z, n, _) \ boost::fibers::fiber(boost::allocator_arg, stack_alloc, attrs, worker).join(); -boost::coroutines::flag_fpu_t preserve_fpu = boost::coroutines::fpu_not_preserved; +boost::coroutines::flag_fpu_t preserve_fpu_ = boost::coroutines::fpu_not_preserved; boost::coroutines::flag_unwind_t unwind_stack = boost::coroutines::no_stack_unwind; bool prealloc = false; bool preserve = false; @@ -37,7 +37,7 @@ void worker() {} template< typename StackAllocator > duration_type measure( duration_type overhead, StackAllocator const& stack_alloc) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( boost::allocator_arg, stack_alloc, attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -90,7 +90,7 @@ int main( int argc, char * argv[]) return EXIT_SUCCESS; } - if ( preserve) preserve_fpu = boost::coroutines::fpu_preserved; + if ( preserve) preserve_fpu_ = boost::coroutines::fpu_preserved; if ( unwind) unwind_stack = boost::coroutines::stack_unwind; duration_type overhead = overhead_clock(); diff --git a/performance/fiber/overhead_yield.cpp b/performance/fiber/overhead_yield.cpp index 344a453e..db860118 100644 --- a/performance/fiber/overhead_yield.cpp +++ b/performance/fiber/overhead_yield.cpp @@ -25,7 +25,7 @@ #define JOIN(z, n, _) \ boost::fibers::fiber( attrs, worker).join(); -boost::coroutines::flag_fpu_t preserve_fpu = boost::coroutines::fpu_not_preserved; +boost::coroutines::flag_fpu_t preserve_fpu_ = boost::coroutines::fpu_not_preserved; boost::coroutines::flag_unwind_t unwind_stack = boost::coroutines::no_stack_unwind; bool prealloc = false; bool preserve = false; @@ -36,7 +36,7 @@ void worker() duration_type measure( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -75,7 +75,7 @@ int main( int argc, char * argv[]) return EXIT_SUCCESS; } - if ( preserve) preserve_fpu = boost::coroutines::fpu_preserved; + if ( preserve) preserve_fpu_ = boost::coroutines::fpu_preserved; if ( unwind) unwind_stack = boost::coroutines::stack_unwind; duration_type overhead = overhead_clock(); diff --git a/performance/fiber/scale_join.cpp b/performance/fiber/scale_join.cpp index 83983412..fc24e938 100644 --- a/performance/fiber/scale_join.cpp +++ b/performance/fiber/scale_join.cpp @@ -21,14 +21,14 @@ #define JOIN(z, n, _) \ BOOST_PP_CAT(f,n) .join(); -boost::coroutines::flag_fpu_t preserve_fpu = boost::coroutines::fpu_not_preserved; +boost::coroutines::flag_fpu_t preserve_fpu_ = boost::coroutines::fpu_not_preserved; boost::coroutines::flag_unwind_t unwind_stack = boost::coroutines::no_stack_unwind; void worker() {} duration_type measure10( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -45,7 +45,7 @@ duration_type measure10( duration_type overhead) duration_type measure50( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -62,7 +62,7 @@ duration_type measure50( duration_type overhead) duration_type measure100( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -79,7 +79,7 @@ duration_type measure100( duration_type overhead) duration_type measure500( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -96,7 +96,7 @@ duration_type measure500( duration_type overhead) duration_type measure1000( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -113,7 +113,7 @@ duration_type measure1000( duration_type overhead) duration_type measure5000( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); @@ -130,7 +130,7 @@ duration_type measure5000( duration_type overhead) duration_type measure10000( duration_type overhead) { - boost::fibers::attributes attrs( unwind_stack, preserve_fpu); + boost::fibers::attributes attrs( unwind_stack, preserve_fpu_); boost::fibers::fiber( attrs, worker).join(); time_point_type start( clock_type::now() ); diff --git a/src/condition.cpp b/src/condition.cpp index 6b624346..982a838a 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -26,18 +26,18 @@ condition::~condition() void condition::notify_one() { - detail::fiber_base * n = 0; + detail::fiber_base * f( 0); unique_lock< detail::spinlock > lk( splk_); // get one waiting fiber if ( ! waiting_.empty() ) { - n = waiting_.front(); + f = waiting_.front(); waiting_.pop_front(); } lk.unlock(); // notify waiting fiber - if ( n) n->set_ready(); + if ( f) f->set_ready(); } void @@ -53,10 +53,10 @@ condition::notify_all() // notify all waiting fibers while ( ! waiting.empty() ) { - detail::fiber_base * n( waiting.front() ); + detail::fiber_base * f( waiting.front() ); waiting.pop_front(); - BOOST_ASSERT( n); - n->set_ready(); + BOOST_ASSERT( f); + f->set_ready(); } } diff --git a/src/detail/worker_fiber.cpp b/src/detail/fiber_base.cpp similarity index 70% rename from src/detail/worker_fiber.cpp rename to src/detail/fiber_base.cpp index c7fa9f5f..0b545627 100644 --- a/src/detail/worker_fiber.cpp +++ b/src/detail/fiber_base.cpp @@ -4,7 +4,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include "boost/fiber/detail/worker_fiber.hpp" +#include "boost/fiber/detail/fiber_base.hpp" #include @@ -23,35 +23,12 @@ namespace boost { namespace fibers { namespace detail { -void * worker_fiber::null_ptr = 0; - -worker_fiber::worker_fiber( coro_t::yield_type * callee) : - fiber_base(), - use_count_( 1), // allocated on stack - fss_data_(), - nxt_( 0), - tp_( (chrono::high_resolution_clock::time_point::max)() ), - callee_( callee), - caller_(), - state_( READY), - flags_( 0), - priority_( 0), - except_(), - waiting_() -{ BOOST_ASSERT( callee_); } - -worker_fiber::~worker_fiber() -{ - BOOST_ASSERT( is_terminated() ); - BOOST_ASSERT( waiting_.empty() ); -} - void -worker_fiber::release() +fiber_base::release() { BOOST_ASSERT( is_terminated() ); - std::vector< worker_fiber * > waiting; + std::vector< fiber_base * > waiting; // get all waiting fibers splk_.lock(); @@ -59,7 +36,7 @@ worker_fiber::release() splk_.unlock(); // notify all waiting fibers - BOOST_FOREACH( worker_fiber * p, waiting) + BOOST_FOREACH( fiber_base * p, waiting) { p->set_ready(); } // release all fiber-specific-pointers @@ -68,7 +45,7 @@ worker_fiber::release() } bool -worker_fiber::join( worker_fiber * p) +fiber_base::join( fiber_base * p) { unique_lock< spinlock > lk( splk_); if ( is_terminated() ) return false; @@ -77,7 +54,7 @@ worker_fiber::join( worker_fiber * p) } void -worker_fiber::interruption_blocked( bool blck) BOOST_NOEXCEPT +fiber_base::interruption_blocked( bool blck) BOOST_NOEXCEPT { if ( blck) flags_ |= flag_interruption_blocked; @@ -86,7 +63,7 @@ worker_fiber::interruption_blocked( bool blck) BOOST_NOEXCEPT } void -worker_fiber::request_interruption( bool req) BOOST_NOEXCEPT +fiber_base::request_interruption( bool req) BOOST_NOEXCEPT { if ( req) flags_ |= flag_interruption_requested; @@ -95,7 +72,7 @@ worker_fiber::request_interruption( bool req) BOOST_NOEXCEPT } void -worker_fiber::thread_affinity( bool req) BOOST_NOEXCEPT +fiber_base::thread_affinity( bool req) BOOST_NOEXCEPT { if ( req) flags_ |= flag_thread_affinity; @@ -104,7 +81,7 @@ worker_fiber::thread_affinity( bool req) BOOST_NOEXCEPT } void * -worker_fiber::get_fss_data( void const* vp) const +fiber_base::get_fss_data( void const* vp) const { uintptr_t key( reinterpret_cast< uintptr_t >( vp) ); fss_data_t::const_iterator i( fss_data_.find( key) ); @@ -113,7 +90,7 @@ worker_fiber::get_fss_data( void const* vp) const } void -worker_fiber::set_fss_data( +fiber_base::set_fss_data( void const* vp, fss_cleanup_function::ptr_t const& cleanup_fn, void * data, bool cleanup_existing) diff --git a/src/fiber_manager.cpp b/src/fiber_manager.cpp index dfa234e6..00d8c61c 100644 --- a/src/fiber_manager.cpp +++ b/src/fiber_manager.cpp @@ -30,7 +30,7 @@ namespace boost { namespace fibers { -bool fetch_ready( detail::worker_fiber * f, chrono::high_resolution_clock::time_point const& now) +bool fetch_ready( detail::fiber_base * f, chrono::high_resolution_clock::time_point const& now) { BOOST_ASSERT( ! f->is_running() ); BOOST_ASSERT( ! f->is_terminated() ); @@ -43,51 +43,50 @@ bool fetch_ready( detail::worker_fiber * f, chrono::high_resolution_clock::time_ } fiber_manager::fiber_manager() BOOST_NOEXCEPT : - def_algo_( new round_robin() ), - sched_algo_( def_algo_.get() ), - wqueue_(), - wait_interval_( chrono::milliseconds( 10) ), - active_fiber_( 0) + def_algo( new round_robin() ), + sched_algo( def_algo.get() ), + wqueue(), + preserve_fpu( false), + main_fiber_(), + wait_interval( chrono::milliseconds( 10) ), + active_fiber( & main_fiber_) {} fiber_manager::~fiber_manager() BOOST_NOEXCEPT { // fibers will be destroyed (stack-unwinding) // if last reference goes out-of-scope - // therefore destructing fm->wqueue_ && rqueue_ + // therefore destructing fm->wqueue && rqueue_ // will destroy the fibers in this scheduler // if not referenced on other places - while ( ! wqueue_.empty() ) + while ( ! wqueue.empty() ) fm_run(); } -void fm_resume_( detail::worker_fiber * f) +void fm_resume_( detail::fiber_base * f) { - volatile fiber_manager * fm = detail::scheduler::instance(); + fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); BOOST_ASSERT( 0 != f); - BOOST_ASSERT( f != fm->active_fiber_); BOOST_ASSERT( f->is_ready() ); // fiber to state_running f->set_running(); + + if ( f == fm->active_fiber) return; + // store active-fiber in local var - detail::worker_fiber * tmp = fm->active_fiber_; + detail::fiber_base * tmp = fm->active_fiber; // assign new fiber to active-fiber - fm->active_fiber_ = f; - // resume active-fiber == start or yield to - fm->active_fiber_->resume( tmp); - // if fiber was migrated to another thread - // the fiber-manger pointer, allocated on the stack, - // is invalid - fm = detail::scheduler::instance(); + fm->active_fiber = f; // if active-fiber is detached and has terminated // the fiber has to be destructed/deallocated - if ( 0 != fm->active_fiber_ && - fm->active_fiber_->is_terminated() ) - intrusive_ptr_release( fm->active_fiber_); - fm->active_fiber_ = tmp; + BOOST_ASSERT( 0 != tmp); + if ( tmp->is_terminated() ) + intrusive_ptr_release( tmp); + // resume active-fiber == start or yield to + fm->active_fiber->resume( tmp, fm->preserve_fpu); } void fm_set_sched_algo( sched_algorithm * algo) @@ -96,8 +95,8 @@ void fm_set_sched_algo( sched_algorithm * algo) BOOST_ASSERT( 0 != fm); - fm->sched_algo_ = algo; - fm->def_algo_.reset(); + fm->sched_algo = algo; + fm->def_algo.reset(); } chrono::high_resolution_clock::time_point fm_next_wakeup() @@ -106,38 +105,38 @@ chrono::high_resolution_clock::time_point fm_next_wakeup() BOOST_ASSERT( 0 != fm); - if ( fm->wqueue_.empty() ) - return chrono::high_resolution_clock::now() + fm->wait_interval_; + if ( fm->wqueue.empty() ) + return chrono::high_resolution_clock::now() + fm->wait_interval; else { //FIXME: search for the closest time_point to now() in waiting-queue - chrono::high_resolution_clock::time_point wakeup( fm->wqueue_.top()->time_point() ); + chrono::high_resolution_clock::time_point wakeup( fm->wqueue.top()->time_point() ); if ( (chrono::high_resolution_clock::time_point::max)() == wakeup) - return chrono::high_resolution_clock::now() + fm->wait_interval_; + return chrono::high_resolution_clock::now() + fm->wait_interval; return wakeup; } } -void fm_spawn( detail::worker_fiber * f) +void fm_spawn( detail::fiber_base * f) { fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); BOOST_ASSERT( 0 != f); BOOST_ASSERT( f->is_ready() ); - BOOST_ASSERT( f != fm->active_fiber_); + BOOST_ASSERT( f != fm->active_fiber); - fm->sched_algo_->awakened( f); + fm->sched_algo->awakened( f); } -void fm_priority( detail::worker_fiber * f, +void fm_priority( detail::fiber_base * f, int prio) BOOST_NOEXCEPT { fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); - fm->sched_algo_->priority( f, prio); + fm->sched_algo->priority( f, prio); } void fm_wait_interval( chrono::high_resolution_clock::duration const& wait_interval) BOOST_NOEXCEPT @@ -146,7 +145,7 @@ void fm_wait_interval( chrono::high_resolution_clock::duration const& wait_inter BOOST_ASSERT( 0 != fm); - fm->wait_interval_ = wait_interval; + fm->wait_interval = wait_interval; } chrono::high_resolution_clock::duration fm_wait_interval() BOOST_NOEXCEPT @@ -155,7 +154,7 @@ chrono::high_resolution_clock::duration fm_wait_interval() BOOST_NOEXCEPT BOOST_ASSERT( 0 != fm); - return fm->wait_interval_; + return fm->wait_interval; } void fm_run() @@ -164,22 +163,20 @@ void fm_run() BOOST_ASSERT( 0 != fm); - // move all fibers witch are ready (state_ready) - // from waiting-queue to the runnable-queue - fm->wqueue_.move_to( fm->sched_algo_, fetch_ready); + for (;;) + { + // move all fibers witch are ready (state_ready) + // from waiting-queue to the runnable-queue + fm->wqueue.move_to( fm->sched_algo, fetch_ready); - // pop new fiber from ready-queue which is not complete - // (example: fiber in ready-queue could be canceled by active-fiber) - detail::worker_fiber * f( fm->sched_algo_->pick_next() ); - if ( f) - { - BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in ready-queue"); - fm_resume_( f); - } - else - { - if ( fm->active_fiber_) - fm->active_fiber_->suspend(); + // pop new fiber from ready-queue + detail::fiber_base * f( fm->sched_algo->pick_next() ); + if ( f) + { + BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in ready-queue"); + fm_resume_( f); + return; + } else { // no fibers ready to run; the thread should sleep @@ -201,20 +198,21 @@ bool fm_wait_until( chrono::high_resolution_clock::time_point const& timeout_tim fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); - BOOST_ASSERT( 0 != fm->active_fiber_); - BOOST_ASSERT( fm->active_fiber_->is_running() ); + BOOST_ASSERT( 0 != fm->active_fiber); + BOOST_ASSERT( fm->active_fiber->is_running() ); chrono::high_resolution_clock::time_point start( chrono::high_resolution_clock::now() ); // set active-fiber to state_waiting - fm->active_fiber_->set_waiting(); + fm->active_fiber->set_waiting(); // release lock lk.unlock(); - // push active-fiber to fm->wqueue_ - fm->active_fiber_->time_point( timeout_time); - fm->wqueue_.push( fm->active_fiber_); - // suspend active-fiber - fm->active_fiber_->suspend(); + // push active-fiber to fm->wqueue + fm->active_fiber->time_point( timeout_time); + fm->wqueue.push( fm->active_fiber); + // switch to another fiber + fm_run(); + // fiber is resumed return chrono::high_resolution_clock::now() < timeout_time; } @@ -224,61 +222,53 @@ void fm_yield() fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); - BOOST_ASSERT( 0 != fm->active_fiber_); - BOOST_ASSERT( fm->active_fiber_->is_running() ); + BOOST_ASSERT( 0 != fm->active_fiber); + BOOST_ASSERT( fm->active_fiber->is_running() ); // set active-fiber to state_waiting - fm->active_fiber_->set_ready(); - // push active-fiber to fm->wqueue_ - fm->wqueue_.push( fm->active_fiber_); - // suspend active-fiber - fm->active_fiber_->suspend(); + fm->active_fiber->set_ready(); + // push active-fiber to fm->wqueue + fm->wqueue.push( fm->active_fiber); + // switch to another fiber + fm_run(); + // fiber is resumed } -void fm_join( detail::worker_fiber * f) +void fm_join( detail::fiber_base * f) { fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); BOOST_ASSERT( 0 != f); - BOOST_ASSERT( f != fm->active_fiber_); + BOOST_ASSERT( f != fm->active_fiber); - if ( fm->active_fiber_) - { - // set active-fiber to state_waiting - fm->active_fiber_->set_waiting(); - // push active-fiber to fm->wqueue_ - fm->wqueue_.push( fm->active_fiber_); - // add active-fiber to joinig-list of f - if ( ! f->join( fm->active_fiber_) ) - // f must be already terminated therefore we set - // active-fiber to state_ready - // FIXME: better state_running and no suspend - fm->active_fiber_->set_ready(); - // suspend active-fiber - fm->active_fiber_->suspend(); - } - else - { - while ( ! f->is_terminated() ) - // yield this thread if scheduler did not - // resumed some fibers in the previous round - fm_run(); - } + // set active-fiber to state_waiting + fm->active_fiber->set_waiting(); + // push active-fiber to fm->wqueue + fm->wqueue.push( fm->active_fiber); + // add active-fiber to joinig-list of f + if ( ! f->join( fm->active_fiber) ) + // f must be already terminated therefore we set + // active-fiber to state_ready + // FIXME: better state_running and no suspend + fm->active_fiber->set_ready(); + // switch to another fiber + fm_run(); + // fiber is resumed BOOST_ASSERT( f->is_terminated() ); } -detail::worker_fiber * fm_active() BOOST_NOEXCEPT +detail::fiber_base * fm_active() BOOST_NOEXCEPT { fiber_manager * fm = detail::scheduler::instance(); BOOST_ASSERT( 0 != fm); - return fm->active_fiber_; + return fm->active_fiber; } -void fm_migrate( detail::worker_fiber * f) +void fm_migrate( detail::fiber_base * f) { BOOST_ASSERT( 0 != f); BOOST_ASSERT( f->is_ready() ); @@ -287,6 +277,24 @@ void fm_migrate( detail::worker_fiber * f) fm_run(); } +bool fm_preserve_fpu_() +{ + fiber_manager * fm = detail::scheduler::instance(); + + BOOST_ASSERT( 0 != fm); + + return fm->preserve_fpu; +} + +void fm_preserve_fpu_( bool preserve_fpu_) +{ + fiber_manager * fm = detail::scheduler::instance(); + + BOOST_ASSERT( 0 != fm); + + fm->preserve_fpu == preserve_fpu_; +} + }} #ifdef BOOST_HAS_ABI_HEADERS diff --git a/src/interruption.cpp b/src/interruption.cpp index 0a06b212..85a13302 100644 --- a/src/interruption.cpp +++ b/src/interruption.cpp @@ -10,6 +10,7 @@ #include +#include "boost/fiber/detail/fiber_base.hpp" #include "boost/fiber/detail/interrupt_flags.hpp" #include "boost/fiber/fiber_manager.hpp" #include "boost/fiber/exceptions.hpp" @@ -50,13 +51,13 @@ restore_interruption::~restore_interruption() BOOST_NOEXCEPT bool interruption_enabled() BOOST_NOEXCEPT { - fibers::detail::worker_fiber * f = fibers::fm_active(); + fibers::detail::fiber_base * f = fibers::fm_active(); return 0 != f && ! f->interruption_blocked(); } bool interruption_requested() BOOST_NOEXCEPT { - fibers::detail::worker_fiber * f = fibers::fm_active(); + fibers::detail::fiber_base * f = fibers::fm_active(); if ( 0 == f) return false; return f->interruption_requested(); } diff --git a/src/mutex.cpp b/src/mutex.cpp index 0caa32ca..0145716f 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -47,45 +47,19 @@ mutex::~mutex() void mutex::lock() { - detail::fiber_base * n( fm_active() ); - if ( 0 != n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); + unique_lock< detail::spinlock > lk( splk_); - if ( lock_if_unlocked_() ) return; + if ( lock_if_unlocked_() ) return; - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); - // suspend this fiber - fm_wait( lk); - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( lock_if_unlocked_() ) return; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - // run scheduler - fm_run(); - } + // suspend this fiber + fm_wait( lk); } } @@ -109,16 +83,16 @@ mutex::unlock() BOOST_ASSERT( this_fiber::get_id() == owner_); unique_lock< detail::spinlock > lk( splk_); - detail::fiber_base * n = 0; + detail::fiber_base * f( 0); if ( ! waiting_.empty() ) { - n = waiting_.front(); + f = waiting_.front(); waiting_.pop_front(); } - owner_ = detail::worker_fiber::id(); + owner_ = detail::fiber_base::id(); state_ = UNLOCKED; lk.unlock(); - if ( n) n->set_ready(); + if ( f) f->set_ready(); } }} diff --git a/src/recursive_mutex.cpp b/src/recursive_mutex.cpp index 7cefa7a7..862811b8 100644 --- a/src/recursive_mutex.cpp +++ b/src/recursive_mutex.cpp @@ -58,45 +58,19 @@ recursive_mutex::~recursive_mutex() void recursive_mutex::lock() { - detail::fiber_base * n( fm_active() ); - if ( 0 != n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); + unique_lock< detail::spinlock > lk( splk_); - if ( lock_if_unlocked_() ) return; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); + if ( lock_if_unlocked_() ) return; - // suspend this fiber - fm_wait( lk); - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( lock_if_unlocked_() ) return; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - // run scheduler - fm_run(); - } + // suspend this fiber + fm_wait( lk); } } @@ -120,19 +94,19 @@ recursive_mutex::unlock() BOOST_ASSERT( this_fiber::get_id() == owner_); unique_lock< detail::spinlock > lk( splk_); - detail::fiber_base * n = 0; + detail::fiber_base * f( 0); if ( 0 == --count_) { if ( ! waiting_.empty() ) { - n = waiting_.front(); + f = waiting_.front(); waiting_.pop_front(); } - owner_ = detail::worker_fiber::id(); + owner_ = detail::fiber_base::id(); state_ = UNLOCKED; lk.unlock(); - if ( n) n->set_ready(); + if ( f) f->set_ready(); } } diff --git a/src/recursive_timed_mutex.cpp b/src/recursive_timed_mutex.cpp index 9ff6e868..6c36750d 100644 --- a/src/recursive_timed_mutex.cpp +++ b/src/recursive_timed_mutex.cpp @@ -58,45 +58,19 @@ recursive_timed_mutex::~recursive_timed_mutex() void recursive_timed_mutex::lock() { - detail::fiber_base * n( fm_active() ); - if ( 0 != n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); + unique_lock< detail::spinlock > lk( splk_); - if ( lock_if_unlocked_() ) return; + if ( lock_if_unlocked_() ) return; - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); - // suspend this fiber - fm_wait( lk); - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( lock_if_unlocked_() ) return; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - // run scheduler - fm_run(); - } + // suspend this fiber + fm_wait( lk); } } @@ -116,75 +90,32 @@ recursive_timed_mutex::try_lock() bool recursive_timed_mutex::try_lock_until( chrono::high_resolution_clock::time_point const& timeout_time) { - detail::fiber_base * n( fm_active() ); - if ( n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) + unique_lock< detail::spinlock > lk( splk_); + + if ( chrono::high_resolution_clock::now() > timeout_time) + return false; + + if ( lock_if_unlocked_() ) return true; + + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); + + // suspend this fiber until notified or timed-out + if ( ! fm_wait_until( timeout_time, lk) ) { - unique_lock< detail::spinlock > lk( splk_); - - if ( chrono::high_resolution_clock::now() > timeout_time) - return false; - - if ( lock_if_unlocked_() ) return true; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - - // suspend this fiber until notified or timed-out - if ( ! fm_wait_until( timeout_time, lk) ) + lk.lock(); + std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); + if ( waiting_.end() != i) { - lk.lock(); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) - { - // remove fiber from waiting-list - waiting_.erase( wit ); - } - lk.unlock(); - return false; + // remove fiber from waiting-list + waiting_.erase( i); } - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( chrono::high_resolution_clock::now() > timeout_time) - return false; - - if ( lock_if_unlocked_() ) return true; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - { - if ( chrono::high_resolution_clock::now() > timeout_time) - { - lk.lock(); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) - { - // remove fiber from waiting-list - waiting_.erase( wit ); - } - lk.unlock(); - return false; - } - // run scheduler - fm_run(); - } + return false; } } } @@ -196,19 +127,19 @@ recursive_timed_mutex::unlock() BOOST_ASSERT( this_fiber::get_id() == owner_); unique_lock< detail::spinlock > lk( splk_); - detail::fiber_base * n = 0; + detail::fiber_base * f( 0); if ( 0 == --count_) { if ( ! waiting_.empty() ) { - n = waiting_.front(); + f = waiting_.front(); waiting_.pop_front(); } - owner_ = detail::worker_fiber::id(); + owner_ = detail::fiber_base::id(); state_ = UNLOCKED; lk.unlock(); - if ( n) n->set_ready(); + if ( f) f->set_ready(); } } diff --git a/src/round_robin.cpp b/src/round_robin.cpp index bf398da5..59c6d14b 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -16,24 +16,24 @@ namespace boost { namespace fibers { void -round_robin::awakened( detail::worker_fiber * f) +round_robin::awakened( detail::fiber_base * f) { BOOST_ASSERT( 0 != f); rqueue_.push( f); } -detail::worker_fiber * +detail::fiber_base * round_robin::pick_next() { - detail::worker_fiber * victim = 0; + detail::fiber_base * victim = 0; if ( ! rqueue_.empty() ) victim = rqueue_.pop(); return victim; } void -round_robin::priority( detail::worker_fiber * f, int prio) BOOST_NOEXCEPT +round_robin::priority( detail::fiber_base * f, int prio) BOOST_NOEXCEPT { BOOST_ASSERT( f); diff --git a/src/timed_mutex.cpp b/src/timed_mutex.cpp index 21d651a9..5be13537 100644 --- a/src/timed_mutex.cpp +++ b/src/timed_mutex.cpp @@ -47,45 +47,19 @@ timed_mutex::~timed_mutex() void timed_mutex::lock() { - detail::fiber_base * n( fm_active() ); - if ( n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); + unique_lock< detail::spinlock > lk( splk_); - if ( lock_if_unlocked_() ) return; + if ( lock_if_unlocked_() ) return; - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); - // suspend this fiber - fm_wait( lk); - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( lock_if_unlocked_() ) return; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - // run scheduler - fm_run(); - } + // suspend this fiber + fm_wait( lk); } } @@ -105,75 +79,32 @@ timed_mutex::try_lock() bool timed_mutex::try_lock_until( chrono::high_resolution_clock::time_point const& timeout_time) { - detail::fiber_base * n( fm_active() ); - if ( n) + detail::fiber_base * f( fm_active() ); + for (;;) { - for (;;) + unique_lock< detail::spinlock > lk( splk_); + + if ( chrono::high_resolution_clock::now() > timeout_time) + return false; + + if ( lock_if_unlocked_() ) return true; + + // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); + waiting_.push_back( f); + + // suspend this fiber until notified or timed-out + if ( ! fm_wait_until( timeout_time, lk) ) { - unique_lock< detail::spinlock > lk( splk_); - - if ( chrono::high_resolution_clock::now() > timeout_time) - return false; - - if ( lock_if_unlocked_() ) return true; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); - - // suspend this fiber until notified or timed-out - if ( ! fm_wait_until( timeout_time, lk) ) + lk.lock(); + std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); + if ( waiting_.end() != i) { - lk.lock(); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) - { - // remove fiber from waiting-list - waiting_.erase( wit ); - } - lk.unlock(); - return false; + // remove fiber from waiting-list + waiting_.erase( i); } - } - } - else - { - // notification for main-fiber - detail::main_fiber mf; - n = & mf; - - for (;;) - { - unique_lock< detail::spinlock > lk( splk_); - - if ( chrono::high_resolution_clock::now() > timeout_time) - return false; - - if ( lock_if_unlocked_() ) return true; - - // store this fiber in order to be notified later - BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); - waiting_.push_back( n); lk.unlock(); - - // wait until main-fiber gets notified - while ( ! n->is_ready() ) - { - if ( chrono::high_resolution_clock::now() > timeout_time) - { - lk.lock(); - std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); - if (wit != waiting_.end()) - { - // remove fiber from waiting-list - waiting_.erase( wit ); - } - lk.unlock(); - return false; - } - // run scheduler - fm_run(); - } + return false; } } } @@ -185,17 +116,17 @@ timed_mutex::unlock() BOOST_ASSERT( this_fiber::get_id() == owner_); unique_lock< detail::spinlock > lk( splk_); - detail::fiber_base * n = 0; + detail::fiber_base * f( 0); if ( ! waiting_.empty() ) { - n = waiting_.front(); + f = waiting_.front(); waiting_.pop_front(); } - owner_ = detail::worker_fiber::id(); + owner_ = detail::fiber_base::id(); state_ = UNLOCKED; lk.unlock(); - if ( n) n->set_ready(); + if ( f) f->set_ready(); } }}