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