diff --git a/include/boost/fiber/detail/ws_queue.hpp b/include/boost/fiber/detail/ws_queue.hpp new file mode 100644 index 00000000..54c5e4c8 --- /dev/null +++ b/include/boost/fiber/detail/ws_queue.hpp @@ -0,0 +1,63 @@ + +// Copyright Oliver Kowalke 2013. +// 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_WS_QUEUE_H +#define BOOST_FIBERS_DETAIL_WS_QUEUE_H + +#include + +#include +#include + +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace fibers { +namespace detail { + +class ws_queue +{ +private: + typedef std::deque< fiber_base::ptr_t > queue_t; + + spinlock splk_; + queue_t queue_; + +public: + ws_queue() : + splk_(), + queue_() + {} + + void push( fiber_base::ptr_t const& f) + { + unique_lock< spinlock > lk( splk_); + queue_.push_back( f); + } + + bool try_pop( fiber_base::ptr_t & f) + { + unique_lock< spinlock > lk( splk_); + if ( queue_.empty() ) return false; + f.swap( queue_.front() ); + queue_.pop_front(); + return true; + } +}; + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_FIBERS_DETAIL_WS_QUEUE_H diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp index 254af941..f7ada302 100644 --- a/include/boost/fiber/round_robin.hpp +++ b/include/boost/fiber/round_robin.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifdef BOOST_HAS_ABI_HEADERS @@ -50,12 +51,10 @@ private: }; typedef std::deque< schedulable > wqueue_t; - typedef std::deque< detail::fiber_base::ptr_t > rqueue_t; detail::fiber_base::ptr_t active_fiber_; wqueue_t wqueue_; - rqueue_t rqueue_; - detail::spinlock splk_; + detail::ws_queue rqueue_; public: round_robin() BOOST_NOEXCEPT; diff --git a/src/round_robin.cpp b/src/round_robin.cpp index 3c9674a5..b7fe52a5 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -31,8 +31,7 @@ namespace fibers { round_robin::round_robin() BOOST_NOEXCEPT : active_fiber_(), wqueue_(), - rqueue_(), - splk_() + rqueue_() {} round_robin::~round_robin() BOOST_NOEXCEPT @@ -87,10 +86,7 @@ round_robin::run() if ( f->interruption_requested() ) f->set_ready(); if ( f->is_ready() ) - { - unique_lock< detail::spinlock > lk( splk_); - rqueue_.push_back( f); - } + rqueue_.push( f); else wqueue.push_back( s); } // exchange local with global waiting queue @@ -101,12 +97,7 @@ round_robin::run() detail::fiber_base::ptr_t f; do { - unique_lock< detail::spinlock > lk( splk_); - if ( rqueue_.empty() ) return false; - f.swap( rqueue_.front() ); - rqueue_.pop_front(); - lk.unlock(); - + if ( ! rqueue_.try_pop( f) ) return false; if ( f->is_ready() ) break; else BOOST_ASSERT_MSG( false, "fiber with invalid state in ready-queue"); } @@ -223,15 +214,7 @@ fiber round_robin::steal_from() { detail::fiber_base::ptr_t f; - - unique_lock< detail::spinlock > lk( splk_); - if ( ! rqueue_.empty() ) - { - f.swap( rqueue_.back() ); - rqueue_.pop_back(); - } - lk.unlock(); - + if ( ! rqueue_.try_pop( f) ) return fiber(); return fiber( f); }