io_object_executor.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // io_object_executor.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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_IO_OBJECT_EXECUTOR_HPP
  11. #define BOOST_ASIO_DETAIL_IO_OBJECT_EXECUTOR_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/handler_invoke_helpers.hpp>
  17. #include <boost/asio/detail/type_traits.hpp>
  18. #include <boost/asio/io_context.hpp>
  19. #include <boost/asio/detail/push_options.hpp>
  20. namespace boost {
  21. namespace asio {
  22. namespace detail {
  23. // Wrap the (potentially polymorphic) executor so that we can bypass it when
  24. // dispatching on a target executor that has a native I/O implementation.
  25. template <typename Executor>
  26. class io_object_executor
  27. {
  28. public:
  29. io_object_executor(const Executor& ex,
  30. bool native_implementation) BOOST_ASIO_NOEXCEPT
  31. : executor_(ex),
  32. has_native_impl_(native_implementation)
  33. {
  34. }
  35. io_object_executor(const io_object_executor& other) BOOST_ASIO_NOEXCEPT
  36. : executor_(other.executor_),
  37. has_native_impl_(other.has_native_impl_)
  38. {
  39. }
  40. template <typename Executor1>
  41. io_object_executor(
  42. const io_object_executor<Executor1>& other) BOOST_ASIO_NOEXCEPT
  43. : executor_(other.inner_executor()),
  44. has_native_impl_(other.has_native_implementation())
  45. {
  46. }
  47. #if defined(BOOST_ASIO_HAS_MOVE)
  48. io_object_executor(io_object_executor&& other) BOOST_ASIO_NOEXCEPT
  49. : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)),
  50. has_native_impl_(other.has_native_impl_)
  51. {
  52. }
  53. #endif // defined(BOOST_ASIO_HAS_MOVE)
  54. const Executor& inner_executor() const BOOST_ASIO_NOEXCEPT
  55. {
  56. return executor_;
  57. }
  58. bool has_native_implementation() const BOOST_ASIO_NOEXCEPT
  59. {
  60. return has_native_impl_;
  61. }
  62. execution_context& context() const BOOST_ASIO_NOEXCEPT
  63. {
  64. return executor_.context();
  65. }
  66. void on_work_started() const BOOST_ASIO_NOEXCEPT
  67. {
  68. if (is_same<Executor, io_context::executor_type>::value
  69. || has_native_impl_)
  70. {
  71. // When using a native implementation, work is already counted by the
  72. // execution context.
  73. }
  74. else
  75. {
  76. executor_.on_work_started();
  77. }
  78. }
  79. void on_work_finished() const BOOST_ASIO_NOEXCEPT
  80. {
  81. if (is_same<Executor, io_context::executor_type>::value
  82. || has_native_impl_)
  83. {
  84. // When using a native implementation, work is already counted by the
  85. // execution context.
  86. }
  87. else
  88. {
  89. executor_.on_work_finished();
  90. }
  91. }
  92. template <typename F, typename A>
  93. void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  94. {
  95. if (is_same<Executor, io_context::executor_type>::value
  96. || has_native_impl_)
  97. {
  98. // When using a native implementation, I/O completion handlers are
  99. // already dispatched according to the execution context's executor's
  100. // rules. We can call the function directly.
  101. #if defined(BOOST_ASIO_HAS_MOVE)
  102. if (is_same<F, typename decay<F>::type>::value)
  103. {
  104. boost_asio_handler_invoke_helpers::invoke(f, f);
  105. return;
  106. }
  107. #endif // defined(BOOST_ASIO_HAS_MOVE)
  108. typename decay<F>::type function(BOOST_ASIO_MOVE_CAST(F)(f));
  109. boost_asio_handler_invoke_helpers::invoke(function, function);
  110. }
  111. else
  112. {
  113. executor_.dispatch(BOOST_ASIO_MOVE_CAST(F)(f), a);
  114. }
  115. }
  116. template <typename F, typename A>
  117. void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  118. {
  119. executor_.post(BOOST_ASIO_MOVE_CAST(F)(f), a);
  120. }
  121. template <typename F, typename A>
  122. void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  123. {
  124. executor_.defer(BOOST_ASIO_MOVE_CAST(F)(f), a);
  125. }
  126. friend bool operator==(const io_object_executor& a,
  127. const io_object_executor& b) BOOST_ASIO_NOEXCEPT
  128. {
  129. return a.executor_ == b.executor_
  130. && a.has_native_impl_ == b.has_native_impl_;
  131. }
  132. friend bool operator!=(const io_object_executor& a,
  133. const io_object_executor& b) BOOST_ASIO_NOEXCEPT
  134. {
  135. return a.executor_ != b.executor_
  136. || a.has_native_impl_ != b.has_native_impl_;
  137. }
  138. private:
  139. Executor executor_;
  140. const bool has_native_impl_;
  141. };
  142. } // namespace detail
  143. } // namespace asio
  144. } // namespace boost
  145. #include <boost/asio/detail/pop_options.hpp>
  146. #endif // BOOST_ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP