2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-18 01:52:24 +00:00

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.
This commit is contained in:
Nat Goodspeed
2014-11-11 07:42:56 -05:00
parent 12fe326c6f
commit 2bffbddeaa

View File

@@ -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<worker_fiber*>(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<worker_fiber*>(*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<worker_fiber*>(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<worker_fiber*>(head_), * prev = 0;
chrono::high_resolution_clock::time_point now( chrono::high_resolution_clock::now() );
while ( 0 != f)
{
worker_fiber * nxt = static_cast<worker_fiber*>(f->nxt_);
if ( fn( f, now) )
{
if ( f == head_)
if ( f == static_cast<worker_fiber*>(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_;
};
}}}