async_result.hpp 12 KB

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