Chris@16
|
1 //
|
Chris@16
|
2 // detail/reactor_op_queue.hpp
|
Chris@16
|
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
Chris@16
|
4 //
|
Chris@101
|
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
Chris@16
|
6 //
|
Chris@16
|
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 //
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
|
Chris@16
|
12 #define BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/asio/detail/config.hpp>
|
Chris@16
|
19 #include <boost/asio/detail/hash_map.hpp>
|
Chris@16
|
20 #include <boost/asio/detail/noncopyable.hpp>
|
Chris@16
|
21 #include <boost/asio/detail/op_queue.hpp>
|
Chris@16
|
22 #include <boost/asio/detail/reactor_op.hpp>
|
Chris@16
|
23 #include <boost/asio/error.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/asio/detail/push_options.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost {
|
Chris@16
|
28 namespace asio {
|
Chris@16
|
29 namespace detail {
|
Chris@16
|
30
|
Chris@16
|
31 template <typename Descriptor>
|
Chris@16
|
32 class reactor_op_queue
|
Chris@16
|
33 : private noncopyable
|
Chris@16
|
34 {
|
Chris@16
|
35 public:
|
Chris@101
|
36 typedef Descriptor key_type;
|
Chris@101
|
37
|
Chris@101
|
38 struct mapped_type : op_queue<reactor_op>
|
Chris@101
|
39 {
|
Chris@101
|
40 mapped_type() {}
|
Chris@101
|
41 mapped_type(const mapped_type&) {}
|
Chris@101
|
42 void operator=(const mapped_type&) {}
|
Chris@101
|
43 };
|
Chris@101
|
44
|
Chris@101
|
45 typedef typename hash_map<key_type, mapped_type>::value_type value_type;
|
Chris@101
|
46 typedef typename hash_map<key_type, mapped_type>::iterator iterator;
|
Chris@101
|
47
|
Chris@16
|
48 // Constructor.
|
Chris@16
|
49 reactor_op_queue()
|
Chris@16
|
50 : operations_()
|
Chris@16
|
51 {
|
Chris@16
|
52 }
|
Chris@16
|
53
|
Chris@101
|
54 // Obtain iterators to all registered descriptors.
|
Chris@101
|
55 iterator begin() { return operations_.begin(); }
|
Chris@101
|
56 iterator end() { return operations_.end(); }
|
Chris@101
|
57
|
Chris@16
|
58 // Add a new operation to the queue. Returns true if this is the only
|
Chris@16
|
59 // operation for the given descriptor, in which case the reactor's event
|
Chris@16
|
60 // demultiplexing function call may need to be interrupted and restarted.
|
Chris@16
|
61 bool enqueue_operation(Descriptor descriptor, reactor_op* op)
|
Chris@16
|
62 {
|
Chris@16
|
63 std::pair<iterator, bool> entry =
|
Chris@101
|
64 operations_.insert(value_type(descriptor, mapped_type()));
|
Chris@101
|
65 entry.first->second.push(op);
|
Chris@16
|
66 return entry.second;
|
Chris@16
|
67 }
|
Chris@16
|
68
|
Chris@101
|
69 // Cancel all operations associated with the descriptor identified by the
|
Chris@101
|
70 // supplied iterator. Any operations pending for the descriptor will be
|
Chris@101
|
71 // cancelled. Returns true if any operations were cancelled, in which case
|
Chris@101
|
72 // the reactor's event demultiplexing function may need to be interrupted and
|
Chris@101
|
73 // restarted.
|
Chris@101
|
74 bool cancel_operations(iterator i, op_queue<operation>& ops,
|
Chris@16
|
75 const boost::system::error_code& ec =
|
Chris@16
|
76 boost::asio::error::operation_aborted)
|
Chris@16
|
77 {
|
Chris@16
|
78 if (i != operations_.end())
|
Chris@16
|
79 {
|
Chris@101
|
80 while (reactor_op* op = i->second.front())
|
Chris@16
|
81 {
|
Chris@16
|
82 op->ec_ = ec;
|
Chris@101
|
83 i->second.pop();
|
Chris@16
|
84 ops.push(op);
|
Chris@16
|
85 }
|
Chris@16
|
86 operations_.erase(i);
|
Chris@16
|
87 return true;
|
Chris@16
|
88 }
|
Chris@16
|
89
|
Chris@16
|
90 return false;
|
Chris@16
|
91 }
|
Chris@16
|
92
|
Chris@101
|
93 // Cancel all operations associated with the descriptor. Any operations
|
Chris@101
|
94 // pending for the descriptor will be cancelled. Returns true if any
|
Chris@101
|
95 // operations were cancelled, in which case the reactor's event
|
Chris@101
|
96 // demultiplexing function may need to be interrupted and restarted.
|
Chris@101
|
97 bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
|
Chris@101
|
98 const boost::system::error_code& ec =
|
Chris@101
|
99 boost::asio::error::operation_aborted)
|
Chris@101
|
100 {
|
Chris@101
|
101 return this->cancel_operations(operations_.find(descriptor), ops, ec);
|
Chris@101
|
102 }
|
Chris@101
|
103
|
Chris@16
|
104 // Whether there are no operations in the queue.
|
Chris@16
|
105 bool empty() const
|
Chris@16
|
106 {
|
Chris@16
|
107 return operations_.empty();
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 // Determine whether there are any operations associated with the descriptor.
|
Chris@16
|
111 bool has_operation(Descriptor descriptor) const
|
Chris@16
|
112 {
|
Chris@16
|
113 return operations_.find(descriptor) != operations_.end();
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@101
|
116 // Perform the operations corresponding to the descriptor identified by the
|
Chris@101
|
117 // supplied iterator. Returns true if there are still unfinished operations
|
Chris@101
|
118 // queued for the descriptor.
|
Chris@101
|
119 bool perform_operations(iterator i, op_queue<operation>& ops)
|
Chris@16
|
120 {
|
Chris@16
|
121 if (i != operations_.end())
|
Chris@16
|
122 {
|
Chris@101
|
123 while (reactor_op* op = i->second.front())
|
Chris@16
|
124 {
|
Chris@16
|
125 if (op->perform())
|
Chris@16
|
126 {
|
Chris@101
|
127 i->second.pop();
|
Chris@16
|
128 ops.push(op);
|
Chris@16
|
129 }
|
Chris@16
|
130 else
|
Chris@16
|
131 {
|
Chris@16
|
132 return true;
|
Chris@16
|
133 }
|
Chris@16
|
134 }
|
Chris@16
|
135 operations_.erase(i);
|
Chris@16
|
136 }
|
Chris@16
|
137 return false;
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@101
|
140 // Perform the operations corresponding to the descriptor. Returns true if
|
Chris@101
|
141 // there are still unfinished operations queued for the descriptor.
|
Chris@101
|
142 bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
|
Chris@16
|
143 {
|
Chris@101
|
144 return this->perform_operations(operations_.find(descriptor), ops);
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 // Get all operations owned by the queue.
|
Chris@16
|
148 void get_all_operations(op_queue<operation>& ops)
|
Chris@16
|
149 {
|
Chris@101
|
150 iterator i = operations_.begin();
|
Chris@16
|
151 while (i != operations_.end())
|
Chris@16
|
152 {
|
Chris@101
|
153 iterator op_iter = i++;
|
Chris@101
|
154 ops.push(op_iter->second);
|
Chris@16
|
155 operations_.erase(op_iter);
|
Chris@16
|
156 }
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@16
|
159 private:
|
Chris@16
|
160 // The operations that are currently executing asynchronously.
|
Chris@101
|
161 hash_map<key_type, mapped_type> operations_;
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 } // namespace detail
|
Chris@16
|
165 } // namespace asio
|
Chris@16
|
166 } // namespace boost
|
Chris@16
|
167
|
Chris@16
|
168 #include <boost/asio/detail/pop_options.hpp>
|
Chris@16
|
169
|
Chris@16
|
170 #endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
|