coro_completion_handler.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // experimental/detail/coro_completion_handler.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2021-2023 Klemens D. Morgenstern
  6. // (klemens dot morgenstern at gmx dot net)
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP
  12. #define ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include "asio/detail/config.hpp"
  17. #include "asio/deferred.hpp"
  18. #include "asio/experimental/coro.hpp"
  19. #include "asio/detail/push_options.hpp"
  20. namespace asio {
  21. namespace experimental {
  22. namespace detail {
  23. template <typename Promise, typename... Args>
  24. struct coro_completion_handler
  25. {
  26. coro_completion_handler(coroutine_handle<Promise> h,
  27. std::optional<std::tuple<Args...>>& result)
  28. : self(h),
  29. result(result)
  30. {
  31. }
  32. coro_completion_handler(coro_completion_handler&&) = default;
  33. coroutine_handle<Promise> self;
  34. std::optional<std::tuple<Args...>>& result;
  35. using promise_type = Promise;
  36. void operator()(Args... args)
  37. {
  38. result.emplace(std::move(args)...);
  39. self.resume();
  40. }
  41. using allocator_type = typename promise_type::allocator_type;
  42. allocator_type get_allocator() const noexcept
  43. {
  44. return self.promise().get_allocator();
  45. }
  46. using executor_type = typename promise_type::executor_type;
  47. executor_type get_executor() const noexcept
  48. {
  49. return self.promise().get_executor();
  50. }
  51. using cancellation_slot_type = typename promise_type::cancellation_slot_type;
  52. cancellation_slot_type get_cancellation_slot() const noexcept
  53. {
  54. return self.promise().get_cancellation_slot();
  55. }
  56. };
  57. template <typename Signature>
  58. struct coro_completion_handler_type;
  59. template <typename... Args>
  60. struct coro_completion_handler_type<void(Args...)>
  61. {
  62. using type = std::tuple<Args...>;
  63. template <typename Promise>
  64. using completion_handler = coro_completion_handler<Promise, Args...>;
  65. };
  66. template <typename Signature>
  67. using coro_completion_handler_type_t =
  68. typename coro_completion_handler_type<Signature>::type;
  69. inline void coro_interpret_result(std::tuple<>&&)
  70. {
  71. }
  72. template <typename... Args>
  73. inline auto coro_interpret_result(std::tuple<Args...>&& args)
  74. {
  75. return std::move(args);
  76. }
  77. template <typename... Args>
  78. auto coro_interpret_result(std::tuple<std::exception_ptr, Args...>&& args)
  79. {
  80. if (std::get<0>(args))
  81. std::rethrow_exception(std::get<0>(args));
  82. return std::apply(
  83. [](auto, auto&&... rest)
  84. {
  85. return std::make_tuple(std::move(rest)...);
  86. }, std::move(args));
  87. }
  88. template <typename... Args>
  89. auto coro_interpret_result(
  90. std::tuple<asio::error_code, Args...>&& args)
  91. {
  92. if (std::get<0>(args))
  93. asio::detail::throw_exception(
  94. asio::system_error(std::get<0>(args)));
  95. return std::apply(
  96. [](auto, auto&&... rest)
  97. {
  98. return std::make_tuple(std::move(rest)...);
  99. }, std::move(args));
  100. }
  101. template <typename Arg>
  102. inline auto coro_interpret_result(std::tuple<Arg>&& args)
  103. {
  104. return std::get<0>(std::move(args));
  105. }
  106. template <typename Arg>
  107. auto coro_interpret_result(std::tuple<std::exception_ptr, Arg>&& args)
  108. {
  109. if (std::get<0>(args))
  110. std::rethrow_exception(std::get<0>(args));
  111. return std::get<1>(std::move(args));
  112. }
  113. inline auto coro_interpret_result(
  114. std::tuple<asio::error_code>&& args)
  115. {
  116. if (std::get<0>(args))
  117. asio::detail::throw_exception(
  118. asio::system_error(std::get<0>(args)));
  119. }
  120. inline auto coro_interpret_result(std::tuple<std::exception_ptr>&& args)
  121. {
  122. if (std::get<0>(args))
  123. std::rethrow_exception(std::get<0>(args));
  124. }
  125. template <typename Arg>
  126. auto coro_interpret_result(std::tuple<asio::error_code, Arg>&& args)
  127. {
  128. if (std::get<0>(args))
  129. asio::detail::throw_exception(
  130. asio::system_error(std::get<0>(args)));
  131. return std::get<1>(std::move(args));
  132. }
  133. } // namespace detail
  134. } // namespace experimental
  135. } // namespace asio
  136. #include "asio/detail/pop_options.hpp"
  137. #endif // ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP