reactor_op_queue.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //
  2. // detail/reactor_op_queue.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2013 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. // Constructor.
  31. reactor_op_queue()
  32. : operations_()
  33. {
  34. }
  35. // Add a new operation to the queue. Returns true if this is the only
  36. // operation for the given descriptor, in which case the reactor's event
  37. // demultiplexing function call may need to be interrupted and restarted.
  38. bool enqueue_operation(Descriptor descriptor, reactor_op* op)
  39. {
  40. typedef typename operations_map::iterator iterator;
  41. typedef typename operations_map::value_type value_type;
  42. std::pair<iterator, bool> entry =
  43. operations_.insert(value_type(descriptor, operations()));
  44. entry.first->second.op_queue_.push(op);
  45. return entry.second;
  46. }
  47. // Cancel all operations associated with the descriptor. Any operations
  48. // pending for the descriptor will be notified that they have been cancelled
  49. // next time perform_cancellations is called. Returns true if any operations
  50. // were cancelled, in which case the reactor's event demultiplexing function
  51. // may need to be interrupted and restarted.
  52. bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
  53. const boost::system::error_code& ec =
  54. boost::asio::error::operation_aborted)
  55. {
  56. typename operations_map::iterator i = operations_.find(descriptor);
  57. if (i != operations_.end())
  58. {
  59. while (reactor_op* op = i->second.op_queue_.front())
  60. {
  61. op->ec_ = ec;
  62. i->second.op_queue_.pop();
  63. ops.push(op);
  64. }
  65. operations_.erase(i);
  66. return true;
  67. }
  68. return false;
  69. }
  70. // Whether there are no operations in the queue.
  71. bool empty() const
  72. {
  73. return operations_.empty();
  74. }
  75. // Determine whether there are any operations associated with the descriptor.
  76. bool has_operation(Descriptor descriptor) const
  77. {
  78. return operations_.find(descriptor) != operations_.end();
  79. }
  80. // Perform the operations corresponding to the descriptor. Returns true if
  81. // there are still unfinished operations queued for the descriptor.
  82. bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
  83. {
  84. typename operations_map::iterator i = operations_.find(descriptor);
  85. if (i != operations_.end())
  86. {
  87. while (reactor_op* op = i->second.op_queue_.front())
  88. {
  89. if (op->perform())
  90. {
  91. i->second.op_queue_.pop();
  92. ops.push(op);
  93. }
  94. else
  95. {
  96. return true;
  97. }
  98. }
  99. operations_.erase(i);
  100. }
  101. return false;
  102. }
  103. // Fill a descriptor set with the descriptors corresponding to each active
  104. // operation. The op_queue is used only when descriptors fail to be added to
  105. // the descriptor set.
  106. template <typename Descriptor_Set>
  107. void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops)
  108. {
  109. typename operations_map::iterator i = operations_.begin();
  110. while (i != operations_.end())
  111. {
  112. Descriptor descriptor = i->first;
  113. ++i;
  114. if (!descriptors.set(descriptor))
  115. {
  116. boost::system::error_code ec(error::fd_set_failure);
  117. cancel_operations(descriptor, ops, ec);
  118. }
  119. }
  120. }
  121. // Perform the operations corresponding to the ready file descriptors
  122. // contained in the given descriptor set.
  123. template <typename Descriptor_Set>
  124. void perform_operations_for_descriptors(
  125. const Descriptor_Set& descriptors, op_queue<operation>& ops)
  126. {
  127. typename operations_map::iterator i = operations_.begin();
  128. while (i != operations_.end())
  129. {
  130. typename operations_map::iterator op_iter = i++;
  131. if (descriptors.is_set(op_iter->first))
  132. {
  133. while (reactor_op* op = op_iter->second.op_queue_.front())
  134. {
  135. if (op->perform())
  136. {
  137. op_iter->second.op_queue_.pop();
  138. ops.push(op);
  139. }
  140. else
  141. {
  142. break;
  143. }
  144. }
  145. if (op_iter->second.op_queue_.empty())
  146. operations_.erase(op_iter);
  147. }
  148. }
  149. }
  150. // Get all operations owned by the queue.
  151. void get_all_operations(op_queue<operation>& ops)
  152. {
  153. typename operations_map::iterator i = operations_.begin();
  154. while (i != operations_.end())
  155. {
  156. typename operations_map::iterator op_iter = i++;
  157. ops.push(op_iter->second.op_queue_);
  158. operations_.erase(op_iter);
  159. }
  160. }
  161. private:
  162. struct operations
  163. {
  164. operations() {}
  165. operations(const operations&) {}
  166. void operator=(const operations&) {}
  167. // The operations waiting on the desccriptor.
  168. op_queue<reactor_op> op_queue_;
  169. };
  170. // The type for a map of operations.
  171. typedef hash_map<Descriptor, operations> operations_map;
  172. // The operations that are currently executing asynchronously.
  173. operations_map operations_;
  174. };
  175. } // namespace detail
  176. } // namespace asio
  177. } // namespace boost
  178. #include <boost/asio/detail/pop_options.hpp>
  179. #endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP