reactor_op_queue.hpp 6.5 KB

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