1 // 2 // detail/op_queue.hpp 3 // ~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_DETAIL_OP_QUEUE_HPP 12 #define BOOST_ASIO_DETAIL_OP_QUEUE_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/noncopyable.hpp> 19 20 #include <boost/asio/detail/push_options.hpp> 21 22 namespace boost { 23 namespace asio { 24 namespace detail { 25 26 template <typename Operation> 27 class op_queue; 28 29 class op_queue_access 30 { 31 public: 32 template <typename Operation> next(Operation * o)33 static Operation* next(Operation* o) 34 { 35 return static_cast<Operation*>(o->next_); 36 } 37 38 template <typename Operation1, typename Operation2> next(Operation1 * & o1,Operation2 * o2)39 static void next(Operation1*& o1, Operation2* o2) 40 { 41 o1->next_ = o2; 42 } 43 44 template <typename Operation> destroy(Operation * o)45 static void destroy(Operation* o) 46 { 47 o->destroy(); 48 } 49 50 template <typename Operation> front(op_queue<Operation> & q)51 static Operation*& front(op_queue<Operation>& q) 52 { 53 return q.front_; 54 } 55 56 template <typename Operation> back(op_queue<Operation> & q)57 static Operation*& back(op_queue<Operation>& q) 58 { 59 return q.back_; 60 } 61 }; 62 63 template <typename Operation> 64 class op_queue 65 : private noncopyable 66 { 67 public: 68 // Constructor. op_queue()69 op_queue() 70 : front_(0), 71 back_(0) 72 { 73 } 74 75 // Destructor destroys all operations. ~op_queue()76 ~op_queue() 77 { 78 while (Operation* op = front_) 79 { 80 pop(); 81 op_queue_access::destroy(op); 82 } 83 } 84 85 // Get the operation at the front of the queue. front()86 Operation* front() 87 { 88 return front_; 89 } 90 91 // Pop an operation from the front of the queue. pop()92 void pop() 93 { 94 if (front_) 95 { 96 Operation* tmp = front_; 97 front_ = op_queue_access::next(front_); 98 if (front_ == 0) 99 back_ = 0; 100 op_queue_access::next(tmp, static_cast<Operation*>(0)); 101 } 102 } 103 104 // Push an operation on to the back of the queue. push(Operation * h)105 void push(Operation* h) 106 { 107 op_queue_access::next(h, static_cast<Operation*>(0)); 108 if (back_) 109 { 110 op_queue_access::next(back_, h); 111 back_ = h; 112 } 113 else 114 { 115 front_ = back_ = h; 116 } 117 } 118 119 // Push all operations from another queue on to the back of the queue. The 120 // source queue may contain operations of a derived type. 121 template <typename OtherOperation> push(op_queue<OtherOperation> & q)122 void push(op_queue<OtherOperation>& q) 123 { 124 if (Operation* other_front = op_queue_access::front(q)) 125 { 126 if (back_) 127 op_queue_access::next(back_, other_front); 128 else 129 front_ = other_front; 130 back_ = op_queue_access::back(q); 131 op_queue_access::front(q) = 0; 132 op_queue_access::back(q) = 0; 133 } 134 } 135 136 // Whether the queue is empty. empty() const137 bool empty() const 138 { 139 return front_ == 0; 140 } 141 142 // Test whether an operation is already enqueued. is_enqueued(Operation * o) const143 bool is_enqueued(Operation* o) const 144 { 145 return op_queue_access::next(o) != 0 || back_ == o; 146 } 147 148 private: 149 friend class op_queue_access; 150 151 // The front of the queue. 152 Operation* front_; 153 154 // The back of the queue. 155 Operation* back_; 156 }; 157 158 } // namespace detail 159 } // namespace asio 160 } // namespace boost 161 162 #include <boost/asio/detail/pop_options.hpp> 163 164 #endif // BOOST_ASIO_DETAIL_OP_QUEUE_HPP 165