work_dispatcher.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // detail/work_dispatcher.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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 ASIO_DETAIL_WORK_DISPATCHER_HPP
  11. #define ASIO_DETAIL_WORK_DISPATCHER_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/detail/bind_handler.hpp"
  17. #include "asio/detail/type_traits.hpp"
  18. #include "asio/associated_executor.hpp"
  19. #include "asio/associated_allocator.hpp"
  20. #include "asio/executor_work_guard.hpp"
  21. #include "asio/execution/executor.hpp"
  22. #include "asio/execution/allocator.hpp"
  23. #include "asio/execution/blocking.hpp"
  24. #include "asio/execution/outstanding_work.hpp"
  25. #include "asio/prefer.hpp"
  26. #include "asio/detail/push_options.hpp"
  27. namespace asio {
  28. namespace detail {
  29. template <typename Handler, typename Executor, typename = void>
  30. struct is_work_dispatcher_required : true_type
  31. {
  32. };
  33. template <typename Handler, typename Executor>
  34. struct is_work_dispatcher_required<Handler, Executor,
  35. enable_if_t<
  36. is_same<
  37. typename associated_executor<Handler,
  38. Executor>::asio_associated_executor_is_unspecialised,
  39. void
  40. >::value
  41. >> : false_type
  42. {
  43. };
  44. template <typename Handler, typename Executor, typename = void>
  45. class work_dispatcher
  46. {
  47. public:
  48. template <typename CompletionHandler>
  49. work_dispatcher(CompletionHandler&& handler,
  50. const Executor& handler_ex)
  51. : handler_(static_cast<CompletionHandler&&>(handler)),
  52. executor_(asio::prefer(handler_ex,
  53. execution::outstanding_work.tracked))
  54. {
  55. }
  56. work_dispatcher(const work_dispatcher& other)
  57. : handler_(other.handler_),
  58. executor_(other.executor_)
  59. {
  60. }
  61. work_dispatcher(work_dispatcher&& other)
  62. : handler_(static_cast<Handler&&>(other.handler_)),
  63. executor_(static_cast<work_executor_type&&>(other.executor_))
  64. {
  65. }
  66. void operator()()
  67. {
  68. associated_allocator_t<Handler> alloc((get_associated_allocator)(handler_));
  69. asio::prefer(executor_, execution::allocator(alloc)).execute(
  70. asio::detail::bind_handler(
  71. static_cast<Handler&&>(handler_)));
  72. }
  73. private:
  74. typedef decay_t<
  75. prefer_result_t<const Executor&,
  76. execution::outstanding_work_t::tracked_t
  77. >
  78. > work_executor_type;
  79. Handler handler_;
  80. work_executor_type executor_;
  81. };
  82. #if !defined(ASIO_NO_TS_EXECUTORS)
  83. template <typename Handler, typename Executor>
  84. class work_dispatcher<Handler, Executor,
  85. enable_if_t<!execution::is_executor<Executor>::value>>
  86. {
  87. public:
  88. template <typename CompletionHandler>
  89. work_dispatcher(CompletionHandler&& handler, const Executor& handler_ex)
  90. : work_(handler_ex),
  91. handler_(static_cast<CompletionHandler&&>(handler))
  92. {
  93. }
  94. work_dispatcher(const work_dispatcher& other)
  95. : work_(other.work_),
  96. handler_(other.handler_)
  97. {
  98. }
  99. work_dispatcher(work_dispatcher&& other)
  100. : work_(static_cast<executor_work_guard<Executor>&&>(other.work_)),
  101. handler_(static_cast<Handler&&>(other.handler_))
  102. {
  103. }
  104. void operator()()
  105. {
  106. associated_allocator_t<Handler> alloc((get_associated_allocator)(handler_));
  107. work_.get_executor().dispatch(
  108. asio::detail::bind_handler(
  109. static_cast<Handler&&>(handler_)), alloc);
  110. work_.reset();
  111. }
  112. private:
  113. executor_work_guard<Executor> work_;
  114. Handler handler_;
  115. };
  116. #endif // !defined(ASIO_NO_TS_EXECUTORS)
  117. } // namespace detail
  118. } // namespace asio
  119. #include "asio/detail/pop_options.hpp"
  120. #endif // ASIO_DETAIL_WORK_DISPATCHER_HPP