blob: d842a627bebb410d92f4738dab56ca0939d555ac [file] [log] [blame]
//
// detail/op_queue.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// 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_ASIO_DETAIL_OP_QUEUE_HPP
#define BOOST_ASIO_DETAIL_OP_QUEUE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
template <typename Operation>
class op_queue;
class op_queue_access
{
public:
template <typename Operation>
static Operation* next(Operation* o)
{
return static_cast<Operation*>(o->next_);
}
template <typename Operation1, typename Operation2>
static void next(Operation1*& o1, Operation2* o2)
{
o1->next_ = o2;
}
template <typename Operation>
static void destroy(Operation* o)
{
o->destroy();
}
template <typename Operation>
static Operation*& front(op_queue<Operation>& q)
{
return q.front_;
}
template <typename Operation>
static Operation*& back(op_queue<Operation>& q)
{
return q.back_;
}
};
template <typename Operation>
class op_queue
: private noncopyable
{
public:
// Constructor.
op_queue()
: front_(0),
back_(0)
{
}
// Destructor destroys all operations.
~op_queue()
{
while (Operation* op = front_)
{
pop();
op_queue_access::destroy(op);
}
}
// Get the operation at the front of the queue.
Operation* front()
{
return front_;
}
// Pop an operation from the front of the queue.
void pop()
{
if (front_)
{
Operation* tmp = front_;
front_ = op_queue_access::next(front_);
if (front_ == 0)
back_ = 0;
op_queue_access::next(tmp, static_cast<Operation*>(0));
}
}
// Push an operation on to the back of the queue.
void push(Operation* h)
{
op_queue_access::next(h, static_cast<Operation*>(0));
if (back_)
{
op_queue_access::next(back_, h);
back_ = h;
}
else
{
front_ = back_ = h;
}
}
// Push all operations from another queue on to the back of the queue. The
// source queue may contain operations of a derived type.
template <typename OtherOperation>
void push(op_queue<OtherOperation>& q)
{
if (Operation* other_front = op_queue_access::front(q))
{
if (back_)
op_queue_access::next(back_, other_front);
else
front_ = other_front;
back_ = op_queue_access::back(q);
op_queue_access::front(q) = 0;
op_queue_access::back(q) = 0;
}
}
// Whether the queue is empty.
bool empty() const
{
return front_ == 0;
}
private:
friend class op_queue_access;
// The front of the queue.
Operation* front_;
// The back of the queue.
Operation* back_;
};
} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_DETAIL_OP_QUEUE_HPP