From 2bffbddeaaa9309a70ca19f2a987f8b14c83acf9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Nov 2014 07:42:56 -0500 Subject: [PATCH] Reimplement waiting_queue::push() using pointer-to-pointer trick. Change waiting_queue::head_ from worker_fiber* to fiber_base* for uniformity with worker_fiber::nxt_. This lets push() scan from head_ with a fiber_base**, looking for the right insertion point. Insertion then becomes a couple unconditional assignments. Because push() always scans from head_, tail_ was actually never used. Remove it. --- include/boost/fiber/detail/waiting_queue.hpp | 75 +++++++------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/include/boost/fiber/detail/waiting_queue.hpp b/include/boost/fiber/detail/waiting_queue.hpp index f9125a89..61dcc97e 100644 --- a/include/boost/fiber/detail/waiting_queue.hpp +++ b/include/boost/fiber/detail/waiting_queue.hpp @@ -30,8 +30,7 @@ class waiting_queue : private noncopyable { public: waiting_queue() BOOST_NOEXCEPT : - head_( 0), - tail_( 0) + head_( 0) {} bool empty() const BOOST_NOEXCEPT @@ -42,53 +41,36 @@ public: BOOST_ASSERT( 0 != item); BOOST_ASSERT( 0 == item->nxt_ ); - if ( empty() ) - head_ = tail_ = item; - else - { - worker_fiber * f = head_, * prev = 0; - do - { - worker_fiber * nxt = static_cast(f->nxt_); - if ( item->time_point() <= f->time_point() ) - { - if ( head_ == f) - { - BOOST_ASSERT( 0 == prev); + // Skip past any worker_fibers in the queue whose time_point() is less + // than item->time_point(), looking for the first worker_fiber in the + // queue whose time_point() is at least item->time_point(). Insert + // item before that. In other words, insert item so as to preserve + // ascending order of time_point() values. (Recall that a worker_fiber + // waiting with no timeout uses the maximum time_point value.) - item->nxt_ = f; - head_ = item; - } - else - { - BOOST_ASSERT( 0 != prev); + // We do this by walking the linked list of nxt_ fields with a + // fiber_base**. In other words, first we point to &head_, then to + // &head_->nxt_, then to &head_->nxt_->nxt_ and so forth. When we find + // the item with the right time_point(), we're already pointing to the + // fiber_base* that links it into the list. Insert item right there. - item->nxt_ = f; - prev->nxt_ = item; - } - break; - } - else if ( tail_ == f) - { - BOOST_ASSERT( 0 == nxt); + fiber_base** f = &head_; + for ( ; *f; f = &(*f)->nxt_) + if (item->time_point() <= (static_cast(*f))->time_point()) + break; - tail_->nxt_ = item; - tail_ = item; - break; - } - - prev = f; - f = nxt; - } - while ( 0 != f); - } + // Here, either we reached the end of the list (! *f) or we found a + // (*f) before which to insert 'item'. Break the link at *f and insert + // item. + item->nxt_ = *f; + *f = item; } worker_fiber * top() const BOOST_NOEXCEPT { BOOST_ASSERT( ! empty() ); - return head_; + return static_cast(head_); } template< typename SchedAlgo, typename Fn > @@ -96,28 +78,23 @@ public: { BOOST_ASSERT( sched_algo); - worker_fiber * f = head_, * prev = 0; + worker_fiber * f = static_cast(head_), * prev = 0; chrono::high_resolution_clock::time_point now( chrono::high_resolution_clock::now() ); while ( 0 != f) { worker_fiber * nxt = static_cast(f->nxt_); if ( fn( f, now) ) { - if ( f == head_) + if ( f == static_cast(head_)) { BOOST_ASSERT( 0 == prev); head_ = nxt; - if ( 0 == head_) - tail_ = 0; } else { BOOST_ASSERT( 0 != prev); - if ( 0 == nxt) - tail_ = prev; - prev->nxt_ = nxt; } f->nxt_ = 0; @@ -133,12 +110,10 @@ public: void swap( waiting_queue & other) { std::swap( head_, other.head_); - std::swap( tail_, other.tail_); } private: - worker_fiber * head_; - worker_fiber * tail_; + fiber_base * head_; }; }}}