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.

357 lines
12KB

  1. //
  2. // async_result.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_ASYNC_RESULT_HPP
  11. #define ASIO_ASYNC_RESULT_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/type_traits.hpp"
  17. #include "asio/detail/variadic_templates.hpp"
  18. #include "asio/detail/push_options.hpp"
  19. namespace asio {
  20. /// An interface for customising the behaviour of an initiating function.
  21. /**
  22. * The async_result traits class is used for determining:
  23. *
  24. * @li the concrete completion handler type to be called at the end of the
  25. * asynchronous operation;
  26. *
  27. * @li the initiating function return type; and
  28. *
  29. * @li how the return value of the initiating function is obtained.
  30. *
  31. * The trait allows the handler and return types to be determined at the point
  32. * where the specific completion handler signature is known.
  33. *
  34. * This template may be specialised for user-defined completion token types.
  35. * The primary template assumes that the CompletionToken is the completion
  36. * handler.
  37. */
  38. template <typename CompletionToken, typename Signature>
  39. class async_result
  40. {
  41. public:
  42. /// The concrete completion handler type for the specific signature.
  43. typedef CompletionToken completion_handler_type;
  44. /// The return type of the initiating function.
  45. typedef void return_type;
  46. /// Construct an async result from a given handler.
  47. /**
  48. * When using a specalised async_result, the constructor has an opportunity
  49. * to initialise some state associated with the completion handler, which is
  50. * then returned from the initiating function.
  51. */
  52. explicit async_result(completion_handler_type& h)
  53. {
  54. (void)h;
  55. }
  56. /// Obtain the value to be returned from the initiating function.
  57. return_type get()
  58. {
  59. }
  60. #if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
  61. || defined(GENERATING_DOCUMENTATION)
  62. /// Initiate the asynchronous operation that will produce the result, and
  63. /// obtain the value to be returned from the initiating function.
  64. template <typename Initiation, typename RawCompletionToken, typename... Args>
  65. static return_type initiate(
  66. ASIO_MOVE_ARG(Initiation) initiation,
  67. ASIO_MOVE_ARG(RawCompletionToken) token,
  68. ASIO_MOVE_ARG(Args)... args)
  69. {
  70. ASIO_MOVE_CAST(Initiation)(initiation)(
  71. ASIO_MOVE_CAST(RawCompletionToken)(token),
  72. ASIO_MOVE_CAST(Args)(args)...);
  73. }
  74. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  75. // || defined(GENERATING_DOCUMENTATION)
  76. template <typename Initiation, typename RawCompletionToken>
  77. static return_type initiate(
  78. ASIO_MOVE_ARG(Initiation) initiation,
  79. ASIO_MOVE_ARG(RawCompletionToken) token)
  80. {
  81. ASIO_MOVE_CAST(Initiation)(initiation)(
  82. ASIO_MOVE_CAST(RawCompletionToken)(token));
  83. }
  84. #define ASIO_PRIVATE_INITIATE_DEF(n) \
  85. template <typename Initiation, typename RawCompletionToken, \
  86. ASIO_VARIADIC_TPARAMS(n)> \
  87. static return_type initiate( \
  88. ASIO_MOVE_ARG(Initiation) initiation, \
  89. ASIO_MOVE_ARG(RawCompletionToken) token, \
  90. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  91. { \
  92. ASIO_MOVE_CAST(Initiation)(initiation)( \
  93. ASIO_MOVE_CAST(RawCompletionToken)(token), \
  94. ASIO_VARIADIC_MOVE_ARGS(n)); \
  95. } \
  96. /**/
  97. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
  98. #undef ASIO_PRIVATE_INITIATE_DEF
  99. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  100. // || defined(GENERATING_DOCUMENTATION)
  101. private:
  102. async_result(const async_result&) ASIO_DELETED;
  103. async_result& operator=(const async_result&) ASIO_DELETED;
  104. };
  105. /// Helper template to deduce the handler type from a CompletionToken, capture
  106. /// a local copy of the handler, and then create an async_result for the
  107. /// handler.
  108. template <typename CompletionToken, typename Signature>
  109. struct async_completion
  110. {
  111. /// The real handler type to be used for the asynchronous operation.
  112. typedef typename asio::async_result<
  113. typename decay<CompletionToken>::type,
  114. Signature>::completion_handler_type completion_handler_type;
  115. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  116. /// Constructor.
  117. /**
  118. * The constructor creates the concrete completion handler and makes the link
  119. * between the handler and the asynchronous result.
  120. */
  121. explicit async_completion(CompletionToken& token)
  122. : completion_handler(static_cast<typename conditional<
  123. is_same<CompletionToken, completion_handler_type>::value,
  124. completion_handler_type&, CompletionToken&&>::type>(token)),
  125. result(completion_handler)
  126. {
  127. }
  128. #else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  129. explicit async_completion(typename decay<CompletionToken>::type& token)
  130. : completion_handler(token),
  131. result(completion_handler)
  132. {
  133. }
  134. explicit async_completion(const typename decay<CompletionToken>::type& token)
  135. : completion_handler(token),
  136. result(completion_handler)
  137. {
  138. }
  139. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  140. /// A copy of, or reference to, a real handler object.
  141. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  142. typename conditional<
  143. is_same<CompletionToken, completion_handler_type>::value,
  144. completion_handler_type&, completion_handler_type>::type completion_handler;
  145. #else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  146. completion_handler_type completion_handler;
  147. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  148. /// The result of the asynchronous operation's initiating function.
  149. async_result<typename decay<CompletionToken>::type, Signature> result;
  150. };
  151. namespace detail {
  152. template <typename CompletionToken, typename Signature>
  153. struct async_result_helper
  154. : async_result<typename decay<CompletionToken>::type, Signature>
  155. {
  156. };
  157. struct async_result_memfns_base
  158. {
  159. void initiate();
  160. };
  161. template <typename T>
  162. struct async_result_memfns_derived
  163. : T, async_result_memfns_base
  164. {
  165. };
  166. template <typename T, T>
  167. struct async_result_memfns_check
  168. {
  169. };
  170. template <typename>
  171. char (&async_result_initiate_memfn_helper(...))[2];
  172. template <typename T>
  173. char async_result_initiate_memfn_helper(
  174. async_result_memfns_check<
  175. void (async_result_memfns_base::*)(),
  176. &async_result_memfns_derived<T>::initiate>*);
  177. template <typename CompletionToken, typename Signature>
  178. struct async_result_has_initiate_memfn
  179. : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
  180. async_result<typename decay<CompletionToken>::type, Signature>
  181. >(0)) != 1>
  182. {
  183. };
  184. } // namespace detail
  185. #if defined(GENERATING_DOCUMENTATION)
  186. # define ASIO_INITFN_RESULT_TYPE(ct, sig) \
  187. void_or_deduced
  188. #elif defined(_MSC_VER) && (_MSC_VER < 1500)
  189. # define ASIO_INITFN_RESULT_TYPE(ct, sig) \
  190. typename ::asio::detail::async_result_helper< \
  191. ct, sig>::return_type
  192. #define ASIO_HANDLER_TYPE(ct, sig) \
  193. typename ::asio::detail::async_result_helper< \
  194. ct, sig>::completion_handler_type
  195. #else
  196. # define ASIO_INITFN_RESULT_TYPE(ct, sig) \
  197. typename ::asio::async_result< \
  198. typename ::asio::decay<ct>::type, sig>::return_type
  199. #define ASIO_HANDLER_TYPE(ct, sig) \
  200. typename ::asio::async_result< \
  201. typename ::asio::decay<ct>::type, sig>::completion_handler_type
  202. #endif
  203. #if defined(GENERATING_DOCUMENTATION)
  204. template <typename CompletionToken, typename Signature,
  205. typename Initiation, typename... Args>
  206. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
  207. async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
  208. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),
  209. ASIO_MOVE_ARG(Args)... args);
  210. #elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
  211. template <typename CompletionToken, typename Signature,
  212. typename Initiation, typename... Args>
  213. inline typename enable_if<
  214. detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
  215. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
  216. async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
  217. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  218. ASIO_MOVE_ARG(Args)... args)
  219. {
  220. return async_result<typename decay<CompletionToken>::type,
  221. Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
  222. ASIO_MOVE_CAST(CompletionToken)(token),
  223. ASIO_MOVE_CAST(Args)(args)...);
  224. }
  225. template <typename CompletionToken, typename Signature,
  226. typename Initiation, typename... Args>
  227. inline typename enable_if<
  228. !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
  229. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
  230. async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
  231. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  232. ASIO_MOVE_ARG(Args)... args)
  233. {
  234. async_completion<CompletionToken, Signature> completion(token);
  235. ASIO_MOVE_CAST(Initiation)(initiation)(
  236. ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
  237. Signature))(completion.completion_handler),
  238. ASIO_MOVE_CAST(Args)(args)...);
  239. return completion.result.get();
  240. }
  241. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  242. template <typename CompletionToken, typename Signature, typename Initiation>
  243. inline typename enable_if<
  244. detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
  245. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
  246. async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
  247. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  248. {
  249. return async_result<typename decay<CompletionToken>::type,
  250. Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
  251. ASIO_MOVE_CAST(CompletionToken)(token));
  252. }
  253. template <typename CompletionToken, typename Signature, typename Initiation>
  254. inline typename enable_if<
  255. !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
  256. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
  257. async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
  258. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  259. {
  260. async_completion<CompletionToken, Signature> completion(token);
  261. ASIO_MOVE_CAST(Initiation)(initiation)(
  262. ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
  263. Signature))(completion.completion_handler));
  264. return completion.result.get();
  265. }
  266. #define ASIO_PRIVATE_INITIATE_DEF(n) \
  267. template <typename CompletionToken, typename Signature, \
  268. typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
  269. inline typename enable_if< \
  270. detail::async_result_has_initiate_memfn< \
  271. CompletionToken, Signature>::value, \
  272. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
  273. async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
  274. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  275. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  276. { \
  277. return async_result<typename decay<CompletionToken>::type, \
  278. Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \
  279. ASIO_MOVE_CAST(CompletionToken)(token), \
  280. ASIO_VARIADIC_MOVE_ARGS(n)); \
  281. } \
  282. \
  283. template <typename CompletionToken, typename Signature, \
  284. typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
  285. inline typename enable_if< \
  286. !detail::async_result_has_initiate_memfn< \
  287. CompletionToken, Signature>::value, \
  288. ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
  289. async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
  290. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  291. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  292. { \
  293. async_completion<CompletionToken, Signature> completion(token); \
  294. \
  295. ASIO_MOVE_CAST(Initiation)(initiation)( \
  296. ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \
  297. Signature))(completion.completion_handler), \
  298. ASIO_VARIADIC_MOVE_ARGS(n)); \
  299. \
  300. return completion.result.get(); \
  301. } \
  302. /**/
  303. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
  304. #undef ASIO_PRIVATE_INITIATE_DEF
  305. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  306. } // namespace asio
  307. #include "asio/detail/pop_options.hpp"
  308. #endif // ASIO_ASYNC_RESULT_HPP