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