Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
6.9KB

  1. //
  2. // impl/use_awaitable.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 ASIO_IMPL_USE_AWAITABLE_HPP
  11. #define ASIO_IMPL_USE_AWAITABLE_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/async_result.hpp"
  17. #include "asio/detail/push_options.hpp"
  18. namespace asio {
  19. namespace detail {
  20. template <typename Executor, typename T>
  21. class awaitable_handler_base
  22. : public awaitable_thread<Executor>
  23. {
  24. public:
  25. typedef void result_type;
  26. typedef awaitable<T, Executor> awaitable_type;
  27. // Construct from the entry point of a new thread of execution.
  28. awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)
  29. : awaitable_thread<Executor>(std::move(a), ex)
  30. {
  31. }
  32. // Transfer ownership from another awaitable_thread.
  33. explicit awaitable_handler_base(awaitable_thread<Executor>* h)
  34. : awaitable_thread<Executor>(std::move(*h))
  35. {
  36. }
  37. protected:
  38. awaitable_frame<T, Executor>* frame() noexcept
  39. {
  40. return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);
  41. }
  42. };
  43. template <typename, typename...>
  44. class awaitable_handler;
  45. template <typename Executor>
  46. class awaitable_handler<Executor, void>
  47. : public awaitable_handler_base<Executor, void>
  48. {
  49. public:
  50. using awaitable_handler_base<Executor, void>::awaitable_handler_base;
  51. void operator()()
  52. {
  53. this->frame()->attach_thread(this);
  54. this->frame()->return_void();
  55. this->frame()->pop_frame();
  56. this->pump();
  57. }
  58. };
  59. template <typename Executor>
  60. class awaitable_handler<Executor, asio::error_code>
  61. : public awaitable_handler_base<Executor, void>
  62. {
  63. public:
  64. using awaitable_handler_base<Executor, void>::awaitable_handler_base;
  65. void operator()(const asio::error_code& ec)
  66. {
  67. this->frame()->attach_thread(this);
  68. if (ec)
  69. this->frame()->set_error(ec);
  70. else
  71. this->frame()->return_void();
  72. this->frame()->pop_frame();
  73. this->pump();
  74. }
  75. };
  76. template <typename Executor>
  77. class awaitable_handler<Executor, std::exception_ptr>
  78. : public awaitable_handler_base<Executor, void>
  79. {
  80. public:
  81. using awaitable_handler_base<Executor, void>::awaitable_handler_base;
  82. void operator()(std::exception_ptr ex)
  83. {
  84. this->frame()->attach_thread(this);
  85. if (ex)
  86. this->frame()->set_except(ex);
  87. else
  88. this->frame()->return_void();
  89. this->frame()->pop_frame();
  90. this->pump();
  91. }
  92. };
  93. template <typename Executor, typename T>
  94. class awaitable_handler<Executor, T>
  95. : public awaitable_handler_base<Executor, T>
  96. {
  97. public:
  98. using awaitable_handler_base<Executor, T>::awaitable_handler_base;
  99. template <typename Arg>
  100. void operator()(Arg&& arg)
  101. {
  102. this->frame()->attach_thread(this);
  103. this->frame()->return_value(std::forward<Arg>(arg));
  104. this->frame()->pop_frame();
  105. this->pump();
  106. }
  107. };
  108. template <typename Executor, typename T>
  109. class awaitable_handler<Executor, asio::error_code, T>
  110. : public awaitable_handler_base<Executor, T>
  111. {
  112. public:
  113. using awaitable_handler_base<Executor, T>::awaitable_handler_base;
  114. template <typename Arg>
  115. void operator()(const asio::error_code& ec, Arg&& arg)
  116. {
  117. this->frame()->attach_thread(this);
  118. if (ec)
  119. this->frame()->set_error(ec);
  120. else
  121. this->frame()->return_value(std::forward<Arg>(arg));
  122. this->frame()->pop_frame();
  123. this->pump();
  124. }
  125. };
  126. template <typename Executor, typename T>
  127. class awaitable_handler<Executor, std::exception_ptr, T>
  128. : public awaitable_handler_base<Executor, T>
  129. {
  130. public:
  131. using awaitable_handler_base<Executor, T>::awaitable_handler_base;
  132. template <typename Arg>
  133. void operator()(std::exception_ptr ex, Arg&& arg)
  134. {
  135. this->frame()->attach_thread(this);
  136. if (ex)
  137. this->frame()->set_except(ex);
  138. else
  139. this->frame()->return_value(std::forward<Arg>(arg));
  140. this->frame()->pop_frame();
  141. this->pump();
  142. }
  143. };
  144. template <typename Executor, typename... Ts>
  145. class awaitable_handler
  146. : public awaitable_handler_base<Executor, std::tuple<Ts...>>
  147. {
  148. public:
  149. using awaitable_handler_base<Executor,
  150. std::tuple<Ts...>>::awaitable_handler_base;
  151. template <typename... Args>
  152. void operator()(Args&&... args)
  153. {
  154. this->frame()->attach_thread(this);
  155. this->frame()->return_values(std::forward<Args>(args)...);
  156. this->frame()->pop_frame();
  157. this->pump();
  158. }
  159. };
  160. template <typename Executor, typename... Ts>
  161. class awaitable_handler<Executor, asio::error_code, Ts...>
  162. : public awaitable_handler_base<Executor, std::tuple<Ts...>>
  163. {
  164. public:
  165. using awaitable_handler_base<Executor,
  166. std::tuple<Ts...>>::awaitable_handler_base;
  167. template <typename... Args>
  168. void operator()(const asio::error_code& ec, Args&&... args)
  169. {
  170. this->frame()->attach_thread(this);
  171. if (ec)
  172. this->frame()->set_error(ec);
  173. else
  174. this->frame()->return_values(std::forward<Args>(args)...);
  175. this->frame()->pop_frame();
  176. this->pump();
  177. }
  178. };
  179. template <typename Executor, typename... Ts>
  180. class awaitable_handler<Executor, std::exception_ptr, Ts...>
  181. : public awaitable_handler_base<Executor, std::tuple<Ts...>>
  182. {
  183. public:
  184. using awaitable_handler_base<Executor,
  185. std::tuple<Ts...>>::awaitable_handler_base;
  186. template <typename... Args>
  187. void operator()(std::exception_ptr ex, Args&&... args)
  188. {
  189. this->frame()->attach_thread(this);
  190. if (ex)
  191. this->frame()->set_except(ex);
  192. else
  193. this->frame()->return_values(std::forward<Args>(args)...);
  194. this->frame()->pop_frame();
  195. this->pump();
  196. }
  197. };
  198. } // namespace detail
  199. #if !defined(GENERATING_DOCUMENTATION)
  200. template <typename Executor, typename R, typename... Args>
  201. class async_result<use_awaitable_t<Executor>, R(Args...)>
  202. {
  203. public:
  204. typedef typename detail::awaitable_handler<
  205. Executor, typename decay<Args>::type...> handler_type;
  206. typedef typename handler_type::awaitable_type return_type;
  207. #if defined(_MSC_VER)
  208. template <typename T>
  209. static T dummy_return()
  210. {
  211. return std::move(*static_cast<T*>(nullptr));
  212. }
  213. template <>
  214. static void dummy_return()
  215. {
  216. }
  217. #endif // defined(_MSC_VER)
  218. template <typename Initiation, typename... InitArgs>
  219. static return_type initiate(Initiation initiation,
  220. use_awaitable_t<Executor>, InitArgs... args)
  221. {
  222. co_await [&](auto* frame)
  223. {
  224. handler_type handler(frame->detach_thread());
  225. std::move(initiation)(std::move(handler), std::move(args)...);
  226. return static_cast<handler_type*>(nullptr);
  227. };
  228. for (;;) {} // Never reached.
  229. #if defined(_MSC_VER)
  230. co_return dummy_return<typename return_type::value_type>();
  231. #endif // defined(_MSC_VER)
  232. }
  233. };
  234. #endif // !defined(GENERATING_DOCUMENTATION)
  235. } // namespace asio
  236. #include "asio/detail/pop_options.hpp"
  237. #endif // ASIO_IMPL_USE_AWAITABLE_HPP