reactor_op_queue.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //
  2. // detail/reactor_op_queue.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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. // Whether there are no operations in the queue.
  90. bool empty() const
  91. {
  92. return operations_.empty();
  93. }
  94. // Determine whether there are any operations associated with the descriptor.
  95. bool has_operation(Descriptor descriptor) const
  96. {
  97. return operations_.find(descriptor) != operations_.end();
  98. }
  99. // Perform the operations corresponding to the descriptor identified by the
  100. // supplied iterator. Returns true if there are still unfinished operations
  101. // queued for the descriptor.
  102. bool perform_operations(iterator i, op_queue<operation>& ops)
  103. {
  104. if (i != operations_.end())
  105. {
  106. while (reactor_op* op = i->second.front())
  107. {
  108. if (op->perform())
  109. {
  110. i->second.pop();
  111. ops.push(op);
  112. }
  113. else
  114. {
  115. return true;
  116. }
  117. }
  118. operations_.erase(i);
  119. }
  120. return false;
  121. }
  122. // Perform the operations corresponding to the descriptor. Returns true if
  123. // there are still unfinished operations queued for the descriptor.
  124. bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
  125. {
  126. return this->perform_operations(operations_.find(descriptor), ops);
  127. }
  128. // Get all operations owned by the queue.
  129. void get_all_operations(op_queue<operation>& ops)
  130. {
  131. iterator i = operations_.begin();
  132. while (i != operations_.end())
  133. {
  134. iterator op_iter = i++;
  135. ops.push(op_iter->second);
  136. operations_.erase(op_iter);
  137. }
  138. }
  139. private:
  140. // The operations that are currently executing asynchronously.
  141. hash_map<key_type, mapped_type> operations_;
  142. };
  143. } // namespace detail
  144. } // namespace asio
  145. } // namespace boost
  146. #include <boost/asio/detail/pop_options.hpp>
  147. #endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP