diff options
Diffstat (limited to 'lib/asio/detail/op_queue.hpp')
-rw-r--r-- | lib/asio/detail/op_queue.hpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/asio/detail/op_queue.hpp b/lib/asio/detail/op_queue.hpp new file mode 100644 index 0000000..6219f79 --- /dev/null +++ b/lib/asio/detail/op_queue.hpp @@ -0,0 +1,162 @@ +// +// detail/op_queue.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 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 ASIO_DETAIL_OP_QUEUE_HPP +#define ASIO_DETAIL_OP_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +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; + } + + // Test whether an operation is already enqueued. + bool is_enqueued(Operation* o) const + { + return op_queue_access::next(o) != 0 || back_ == o; + } + +private: + friend class op_queue_access; + + // The front of the queue. + Operation* front_; + + // The back of the queue. + Operation* back_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_OP_QUEUE_HPP |