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