async_result.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950
  1. //
  2. // async_result.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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/push_options.hpp>
  18. namespace boost {
  19. namespace asio {
  20. namespace detail {
  21. template <typename T>
  22. struct is_completion_signature : false_type
  23. {
  24. };
  25. template <typename R, typename... Args>
  26. struct is_completion_signature<R(Args...)> : true_type
  27. {
  28. };
  29. template <typename R, typename... Args>
  30. struct is_completion_signature<R(Args...) &> : true_type
  31. {
  32. };
  33. template <typename R, typename... Args>
  34. struct is_completion_signature<R(Args...) &&> : true_type
  35. {
  36. };
  37. # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  38. template <typename R, typename... Args>
  39. struct is_completion_signature<R(Args...) noexcept> : true_type
  40. {
  41. };
  42. template <typename R, typename... Args>
  43. struct is_completion_signature<R(Args...) & noexcept> : true_type
  44. {
  45. };
  46. template <typename R, typename... Args>
  47. struct is_completion_signature<R(Args...) && noexcept> : true_type
  48. {
  49. };
  50. # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  51. template <typename... T>
  52. struct are_completion_signatures : false_type
  53. {
  54. };
  55. template <>
  56. struct are_completion_signatures<>
  57. : true_type
  58. {
  59. };
  60. template <typename T0>
  61. struct are_completion_signatures<T0>
  62. : is_completion_signature<T0>
  63. {
  64. };
  65. template <typename T0, typename... TN>
  66. struct are_completion_signatures<T0, TN...>
  67. : integral_constant<bool, (
  68. is_completion_signature<T0>::value
  69. && are_completion_signatures<TN...>::value)>
  70. {
  71. };
  72. } // namespace detail
  73. #if defined(BOOST_ASIO_HAS_CONCEPTS)
  74. namespace detail {
  75. template <typename T, typename... Args>
  76. BOOST_ASIO_CONCEPT callable_with = requires(T&& t, Args&&... args)
  77. {
  78. static_cast<T&&>(t)(static_cast<Args&&>(args)...);
  79. };
  80. template <typename T, typename... Signatures>
  81. struct is_completion_handler_for : false_type
  82. {
  83. };
  84. template <typename T, typename R, typename... Args>
  85. struct is_completion_handler_for<T, R(Args...)>
  86. : integral_constant<bool, (callable_with<decay_t<T>, Args...>)>
  87. {
  88. };
  89. template <typename T, typename R, typename... Args>
  90. struct is_completion_handler_for<T, R(Args...) &>
  91. : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)>
  92. {
  93. };
  94. template <typename T, typename R, typename... Args>
  95. struct is_completion_handler_for<T, R(Args...) &&>
  96. : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)>
  97. {
  98. };
  99. # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  100. template <typename T, typename R, typename... Args>
  101. struct is_completion_handler_for<T, R(Args...) noexcept>
  102. : integral_constant<bool, (callable_with<decay_t<T>, Args...>)>
  103. {
  104. };
  105. template <typename T, typename R, typename... Args>
  106. struct is_completion_handler_for<T, R(Args...) & noexcept>
  107. : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)>
  108. {
  109. };
  110. template <typename T, typename R, typename... Args>
  111. struct is_completion_handler_for<T, R(Args...) && noexcept>
  112. : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)>
  113. {
  114. };
  115. # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  116. template <typename T, typename Signature0, typename... SignatureN>
  117. struct is_completion_handler_for<T, Signature0, SignatureN...>
  118. : integral_constant<bool, (
  119. is_completion_handler_for<T, Signature0>::value
  120. && is_completion_handler_for<T, SignatureN...>::value)>
  121. {
  122. };
  123. } // namespace detail
  124. template <typename T>
  125. BOOST_ASIO_CONCEPT completion_signature =
  126. detail::is_completion_signature<T>::value;
  127. #define BOOST_ASIO_COMPLETION_SIGNATURE \
  128. ::boost::asio::completion_signature
  129. template <typename T, typename... Signatures>
  130. BOOST_ASIO_CONCEPT completion_handler_for =
  131. detail::are_completion_signatures<Signatures...>::value
  132. && detail::is_completion_handler_for<T, Signatures...>::value;
  133. #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) \
  134. ::boost::asio::completion_handler_for<sig>
  135. #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) \
  136. ::boost::asio::completion_handler_for<sig0, sig1>
  137. #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) \
  138. ::boost::asio::completion_handler_for<sig0, sig1, sig2>
  139. #else // defined(BOOST_ASIO_HAS_CONCEPTS)
  140. #define BOOST_ASIO_COMPLETION_SIGNATURE typename
  141. #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) typename
  142. #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) typename
  143. #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename
  144. #endif // defined(BOOST_ASIO_HAS_CONCEPTS)
  145. namespace detail {
  146. template <typename T>
  147. struct is_lvalue_completion_signature : false_type
  148. {
  149. };
  150. template <typename R, typename... Args>
  151. struct is_lvalue_completion_signature<R(Args...) &> : true_type
  152. {
  153. };
  154. # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  155. template <typename R, typename... Args>
  156. struct is_lvalue_completion_signature<R(Args...) & noexcept> : true_type
  157. {
  158. };
  159. # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  160. template <typename... Signatures>
  161. struct are_any_lvalue_completion_signatures : false_type
  162. {
  163. };
  164. template <typename Sig0>
  165. struct are_any_lvalue_completion_signatures<Sig0>
  166. : is_lvalue_completion_signature<Sig0>
  167. {
  168. };
  169. template <typename Sig0, typename... SigN>
  170. struct are_any_lvalue_completion_signatures<Sig0, SigN...>
  171. : integral_constant<bool, (
  172. is_lvalue_completion_signature<Sig0>::value
  173. || are_any_lvalue_completion_signatures<SigN...>::value)>
  174. {
  175. };
  176. template <typename T>
  177. struct is_rvalue_completion_signature : false_type
  178. {
  179. };
  180. template <typename R, typename... Args>
  181. struct is_rvalue_completion_signature<R(Args...) &&> : true_type
  182. {
  183. };
  184. # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  185. template <typename R, typename... Args>
  186. struct is_rvalue_completion_signature<R(Args...) && noexcept> : true_type
  187. {
  188. };
  189. # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  190. template <typename... Signatures>
  191. struct are_any_rvalue_completion_signatures : false_type
  192. {
  193. };
  194. template <typename Sig0>
  195. struct are_any_rvalue_completion_signatures<Sig0>
  196. : is_rvalue_completion_signature<Sig0>
  197. {
  198. };
  199. template <typename Sig0, typename... SigN>
  200. struct are_any_rvalue_completion_signatures<Sig0, SigN...>
  201. : integral_constant<bool, (
  202. is_rvalue_completion_signature<Sig0>::value
  203. || are_any_rvalue_completion_signatures<SigN...>::value)>
  204. {
  205. };
  206. template <typename T>
  207. struct simple_completion_signature;
  208. template <typename R, typename... Args>
  209. struct simple_completion_signature<R(Args...)>
  210. {
  211. typedef R type(Args...);
  212. };
  213. template <typename R, typename... Args>
  214. struct simple_completion_signature<R(Args...) &>
  215. {
  216. typedef R type(Args...);
  217. };
  218. template <typename R, typename... Args>
  219. struct simple_completion_signature<R(Args...) &&>
  220. {
  221. typedef R type(Args...);
  222. };
  223. # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  224. template <typename R, typename... Args>
  225. struct simple_completion_signature<R(Args...) noexcept>
  226. {
  227. typedef R type(Args...);
  228. };
  229. template <typename R, typename... Args>
  230. struct simple_completion_signature<R(Args...) & noexcept>
  231. {
  232. typedef R type(Args...);
  233. };
  234. template <typename R, typename... Args>
  235. struct simple_completion_signature<R(Args...) && noexcept>
  236. {
  237. typedef R type(Args...);
  238. };
  239. # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)
  240. template <typename CompletionToken,
  241. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  242. class completion_handler_async_result
  243. {
  244. public:
  245. typedef CompletionToken completion_handler_type;
  246. typedef void return_type;
  247. explicit completion_handler_async_result(completion_handler_type&)
  248. {
  249. }
  250. return_type get()
  251. {
  252. }
  253. template <typename Initiation,
  254. BOOST_ASIO_COMPLETION_HANDLER_FOR(Signatures...) RawCompletionToken,
  255. typename... Args>
  256. static return_type initiate(Initiation&& initiation,
  257. RawCompletionToken&& token, Args&&... args)
  258. {
  259. static_cast<Initiation&&>(initiation)(
  260. static_cast<RawCompletionToken&&>(token),
  261. static_cast<Args&&>(args)...);
  262. }
  263. private:
  264. completion_handler_async_result(
  265. const completion_handler_async_result&) = delete;
  266. completion_handler_async_result& operator=(
  267. const completion_handler_async_result&) = delete;
  268. };
  269. } // namespace detail
  270. #if defined(GENERATING_DOCUMENTATION)
  271. /// An interface for customising the behaviour of an initiating function.
  272. /**
  273. * The async_result traits class is used for determining:
  274. *
  275. * @li the concrete completion handler type to be called at the end of the
  276. * asynchronous operation;
  277. *
  278. * @li the initiating function return type; and
  279. *
  280. * @li how the return value of the initiating function is obtained.
  281. *
  282. * The trait allows the handler and return types to be determined at the point
  283. * where the specific completion handler signature is known.
  284. *
  285. * This template may be specialised for user-defined completion token types.
  286. * The primary template assumes that the CompletionToken is the completion
  287. * handler.
  288. */
  289. template <typename CompletionToken,
  290. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  291. class async_result
  292. {
  293. public:
  294. /// The concrete completion handler type for the specific signature.
  295. typedef CompletionToken completion_handler_type;
  296. /// The return type of the initiating function.
  297. typedef void return_type;
  298. /// Construct an async result from a given handler.
  299. /**
  300. * When using a specalised async_result, the constructor has an opportunity
  301. * to initialise some state associated with the completion handler, which is
  302. * then returned from the initiating function.
  303. */
  304. explicit async_result(completion_handler_type& h);
  305. /// Obtain the value to be returned from the initiating function.
  306. return_type get();
  307. /// Initiate the asynchronous operation that will produce the result, and
  308. /// obtain the value to be returned from the initiating function.
  309. template <typename Initiation, typename RawCompletionToken, typename... Args>
  310. static return_type initiate(
  311. Initiation&& initiation,
  312. RawCompletionToken&& token,
  313. Args&&... args);
  314. private:
  315. async_result(const async_result&) = delete;
  316. async_result& operator=(const async_result&) = delete;
  317. };
  318. #else // defined(GENERATING_DOCUMENTATION)
  319. template <typename CompletionToken,
  320. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  321. class async_result :
  322. public conditional_t<
  323. detail::are_any_lvalue_completion_signatures<Signatures...>::value
  324. || !detail::are_any_rvalue_completion_signatures<Signatures...>::value,
  325. detail::completion_handler_async_result<CompletionToken, Signatures...>,
  326. async_result<CompletionToken,
  327. typename detail::simple_completion_signature<Signatures>::type...>
  328. >
  329. {
  330. public:
  331. typedef conditional_t<
  332. detail::are_any_lvalue_completion_signatures<Signatures...>::value
  333. || !detail::are_any_rvalue_completion_signatures<Signatures...>::value,
  334. detail::completion_handler_async_result<CompletionToken, Signatures...>,
  335. async_result<CompletionToken,
  336. typename detail::simple_completion_signature<Signatures>::type...>
  337. > base_type;
  338. using base_type::base_type;
  339. private:
  340. async_result(const async_result&) = delete;
  341. async_result& operator=(const async_result&) = delete;
  342. };
  343. template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  344. class async_result<void, Signatures...>
  345. {
  346. // Empty.
  347. };
  348. #endif // defined(GENERATING_DOCUMENTATION)
  349. /// Helper template to deduce the handler type from a CompletionToken, capture
  350. /// a local copy of the handler, and then create an async_result for the
  351. /// handler.
  352. template <typename CompletionToken,
  353. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  354. struct async_completion
  355. {
  356. /// The real handler type to be used for the asynchronous operation.
  357. typedef typename boost::asio::async_result<
  358. decay_t<CompletionToken>, Signatures...>::completion_handler_type
  359. completion_handler_type;
  360. /// Constructor.
  361. /**
  362. * The constructor creates the concrete completion handler and makes the link
  363. * between the handler and the asynchronous result.
  364. */
  365. explicit async_completion(CompletionToken& token)
  366. : completion_handler(static_cast<conditional_t<
  367. is_same<CompletionToken, completion_handler_type>::value,
  368. completion_handler_type&, CompletionToken&&>>(token)),
  369. result(completion_handler)
  370. {
  371. }
  372. /// A copy of, or reference to, a real handler object.
  373. conditional_t<
  374. is_same<CompletionToken, completion_handler_type>::value,
  375. completion_handler_type&, completion_handler_type> completion_handler;
  376. /// The result of the asynchronous operation's initiating function.
  377. async_result<decay_t<CompletionToken>, Signatures...> result;
  378. };
  379. namespace detail {
  380. struct async_result_memfns_base
  381. {
  382. void initiate();
  383. };
  384. template <typename T>
  385. struct async_result_memfns_derived
  386. : T, async_result_memfns_base
  387. {
  388. };
  389. template <typename T, T>
  390. struct async_result_memfns_check
  391. {
  392. };
  393. template <typename>
  394. char (&async_result_initiate_memfn_helper(...))[2];
  395. template <typename T>
  396. char async_result_initiate_memfn_helper(
  397. async_result_memfns_check<
  398. void (async_result_memfns_base::*)(),
  399. &async_result_memfns_derived<T>::initiate>*);
  400. template <typename CompletionToken,
  401. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  402. struct async_result_has_initiate_memfn
  403. : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
  404. async_result<decay_t<CompletionToken>, Signatures...>
  405. >(0)) != 1>
  406. {
  407. };
  408. } // namespace detail
  409. #if defined(GENERATING_DOCUMENTATION)
  410. # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
  411. void_or_deduced
  412. # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \
  413. void_or_deduced
  414. # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  415. void_or_deduced
  416. #else
  417. # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
  418. typename ::boost::asio::async_result< \
  419. typename ::boost::asio::decay<ct>::type, sig>::return_type
  420. # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \
  421. typename ::boost::asio::async_result< \
  422. typename ::boost::asio::decay<ct>::type, sig0, sig1>::return_type
  423. # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  424. typename ::boost::asio::async_result< \
  425. typename ::boost::asio::decay<ct>::type, sig0, sig1, sig2>::return_type
  426. #define BOOST_ASIO_HANDLER_TYPE(ct, sig) \
  427. typename ::boost::asio::async_result< \
  428. typename ::boost::asio::decay<ct>::type, sig>::completion_handler_type
  429. #define BOOST_ASIO_HANDLER_TYPE2(ct, sig0, sig1) \
  430. typename ::boost::asio::async_result< \
  431. typename ::boost::asio::decay<ct>::type, \
  432. sig0, sig1>::completion_handler_type
  433. #define BOOST_ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \
  434. typename ::boost::asio::async_result< \
  435. typename ::boost::asio::decay<ct>::type, \
  436. sig0, sig1, sig2>::completion_handler_type
  437. #endif
  438. #if defined(GENERATING_DOCUMENTATION)
  439. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  440. auto
  441. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  442. auto
  443. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  444. auto
  445. #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
  446. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  447. auto
  448. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  449. auto
  450. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  451. auto
  452. #else
  453. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  454. BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig)
  455. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  456. BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)
  457. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  458. BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)
  459. #endif
  460. #if defined(GENERATING_DOCUMENTATION)
  461. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  462. auto
  463. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  464. auto
  465. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  466. auto
  467. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)
  468. #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
  469. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  470. auto
  471. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  472. auto
  473. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  474. auto
  475. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)
  476. #else
  477. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  478. auto
  479. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  480. auto
  481. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  482. auto
  483. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr
  484. #endif
  485. #if defined(GENERATING_DOCUMENTATION)
  486. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \
  487. void_or_deduced
  488. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \
  489. void_or_deduced
  490. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \
  491. void_or_deduced
  492. #else
  493. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \
  494. decltype expr
  495. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \
  496. decltype expr
  497. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \
  498. decltype expr
  499. #endif
  500. #if defined(GENERATING_DOCUMENTATION)
  501. template <typename CompletionToken,
  502. completion_signature... Signatures,
  503. typename Initiation, typename... Args>
  504. void_or_deduced async_initiate(
  505. Initiation&& initiation,
  506. type_identity_t<CompletionToken>& token,
  507. Args&&... args);
  508. #else // defined(GENERATING_DOCUMENTATION)
  509. template <typename CompletionToken,
  510. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  511. typename Initiation, typename... Args>
  512. inline auto async_initiate(Initiation&& initiation,
  513. type_identity_t<CompletionToken>& token, Args&&... args)
  514. -> decltype(enable_if_t<
  515. enable_if_t<
  516. detail::are_completion_signatures<Signatures...>::value,
  517. detail::async_result_has_initiate_memfn<
  518. CompletionToken, Signatures...>>::value,
  519. async_result<decay_t<CompletionToken>, Signatures...>>::initiate(
  520. static_cast<Initiation&&>(initiation),
  521. static_cast<CompletionToken&&>(token),
  522. static_cast<Args&&>(args)...))
  523. {
  524. return async_result<decay_t<CompletionToken>, Signatures...>::initiate(
  525. static_cast<Initiation&&>(initiation),
  526. static_cast<CompletionToken&&>(token),
  527. static_cast<Args&&>(args)...);
  528. }
  529. template <
  530. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  531. typename CompletionToken, typename Initiation, typename... Args>
  532. inline auto async_initiate(Initiation&& initiation,
  533. CompletionToken&& token, Args&&... args)
  534. -> decltype(enable_if_t<
  535. enable_if_t<
  536. detail::are_completion_signatures<Signatures...>::value,
  537. detail::async_result_has_initiate_memfn<
  538. CompletionToken, Signatures...>>::value,
  539. async_result<decay_t<CompletionToken>, Signatures...>>::initiate(
  540. static_cast<Initiation&&>(initiation),
  541. static_cast<CompletionToken&&>(token),
  542. static_cast<Args&&>(args)...))
  543. {
  544. return async_result<decay_t<CompletionToken>, Signatures...>::initiate(
  545. static_cast<Initiation&&>(initiation),
  546. static_cast<CompletionToken&&>(token),
  547. static_cast<Args&&>(args)...);
  548. }
  549. template <typename CompletionToken,
  550. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  551. typename Initiation, typename... Args>
  552. inline typename enable_if_t<
  553. !enable_if_t<
  554. detail::are_completion_signatures<Signatures...>::value,
  555. detail::async_result_has_initiate_memfn<
  556. CompletionToken, Signatures...>>::value,
  557. async_result<decay_t<CompletionToken>, Signatures...>
  558. >::return_type
  559. async_initiate(Initiation&& initiation,
  560. type_identity_t<CompletionToken>& token, Args&&... args)
  561. {
  562. async_completion<CompletionToken, Signatures...> completion(token);
  563. static_cast<Initiation&&>(initiation)(
  564. static_cast<
  565. typename async_result<decay_t<CompletionToken>,
  566. Signatures...>::completion_handler_type&&>(
  567. completion.completion_handler),
  568. static_cast<Args&&>(args)...);
  569. return completion.result.get();
  570. }
  571. template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  572. typename CompletionToken, typename Initiation, typename... Args>
  573. inline typename enable_if_t<
  574. !enable_if_t<
  575. detail::are_completion_signatures<Signatures...>::value,
  576. detail::async_result_has_initiate_memfn<
  577. CompletionToken, Signatures...>>::value,
  578. async_result<decay_t<CompletionToken>, Signatures...>
  579. >::return_type
  580. async_initiate(Initiation&& initiation, CompletionToken&& token, Args&&... args)
  581. {
  582. async_completion<CompletionToken, Signatures...> completion(token);
  583. static_cast<Initiation&&>(initiation)(
  584. static_cast<
  585. typename async_result<decay_t<CompletionToken>,
  586. Signatures...>::completion_handler_type&&>(
  587. completion.completion_handler),
  588. static_cast<Args&&>(args)...);
  589. return completion.result.get();
  590. }
  591. #endif // defined(GENERATING_DOCUMENTATION)
  592. #if defined(BOOST_ASIO_HAS_CONCEPTS)
  593. namespace detail {
  594. template <typename... Signatures>
  595. struct initiation_archetype
  596. {
  597. template <completion_handler_for<Signatures...> CompletionHandler>
  598. void operator()(CompletionHandler&&) const
  599. {
  600. }
  601. };
  602. } // namespace detail
  603. template <typename T, typename... Signatures>
  604. BOOST_ASIO_CONCEPT completion_token_for =
  605. detail::are_completion_signatures<Signatures...>::value
  606. &&
  607. requires(T&& t)
  608. {
  609. async_initiate<T, Signatures...>(
  610. detail::initiation_archetype<Signatures...>{}, t);
  611. };
  612. #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) \
  613. ::boost::asio::completion_token_for<sig>
  614. #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \
  615. ::boost::asio::completion_token_for<sig0, sig1>
  616. #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \
  617. ::boost::asio::completion_token_for<sig0, sig1, sig2>
  618. #else // defined(BOOST_ASIO_HAS_CONCEPTS)
  619. #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) typename
  620. #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename
  621. #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename
  622. #endif // defined(BOOST_ASIO_HAS_CONCEPTS)
  623. namespace detail {
  624. struct async_operation_probe {};
  625. struct async_operation_probe_result {};
  626. template <typename Call, typename = void>
  627. struct is_async_operation_call : false_type
  628. {
  629. };
  630. template <typename Call>
  631. struct is_async_operation_call<Call,
  632. void_t<
  633. enable_if_t<
  634. is_same<
  635. result_of_t<Call>,
  636. async_operation_probe_result
  637. >::value
  638. >
  639. >
  640. > : true_type
  641. {
  642. };
  643. } // namespace detail
  644. #if !defined(GENERATING_DOCUMENTATION)
  645. template <typename... Signatures>
  646. class async_result<detail::async_operation_probe, Signatures...>
  647. {
  648. public:
  649. typedef detail::async_operation_probe_result return_type;
  650. template <typename Initiation, typename... InitArgs>
  651. static return_type initiate(Initiation&&,
  652. detail::async_operation_probe, InitArgs&&...)
  653. {
  654. return return_type();
  655. }
  656. };
  657. #endif // !defined(GENERATING_DOCUMENTATION)
  658. #if defined(GENERATING_DOCUMENTATION)
  659. /// The is_async_operation trait detects whether a type @c T and arguments
  660. /// @c Args... may be used to initiate an asynchronous operation.
  661. /**
  662. * Class template @c is_async_operation is a trait is derived from @c true_type
  663. * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous
  664. * operation, where @c token is an unspecified completion token type. Otherwise,
  665. * @c is_async_operation is derived from @c false_type.
  666. */
  667. template <typename T, typename... Args>
  668. struct is_async_operation : integral_constant<bool, automatically_determined>
  669. {
  670. };
  671. #else // defined(GENERATING_DOCUMENTATION)
  672. template <typename T, typename... Args>
  673. struct is_async_operation :
  674. detail::is_async_operation_call<
  675. T(Args..., detail::async_operation_probe)>
  676. {
  677. };
  678. #endif // defined(GENERATING_DOCUMENTATION)
  679. #if defined(BOOST_ASIO_HAS_CONCEPTS)
  680. template <typename T, typename... Args>
  681. BOOST_ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value;
  682. #define BOOST_ASIO_ASYNC_OPERATION(t) \
  683. ::boost::asio::async_operation<t>
  684. #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) \
  685. ::boost::asio::async_operation<t, a0>
  686. #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) \
  687. ::boost::asio::async_operation<t, a0, a1>
  688. #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \
  689. ::boost::asio::async_operation<t, a0, a1, a2>
  690. #else // defined(BOOST_ASIO_HAS_CONCEPTS)
  691. #define BOOST_ASIO_ASYNC_OPERATION(t) typename
  692. #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) typename
  693. #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) typename
  694. #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename
  695. #endif // defined(BOOST_ASIO_HAS_CONCEPTS)
  696. namespace detail {
  697. struct completion_signature_probe {};
  698. template <typename... T>
  699. struct completion_signature_probe_result
  700. {
  701. template <template <typename...> class Op>
  702. struct apply
  703. {
  704. typedef Op<T...> type;
  705. };
  706. };
  707. template <typename T>
  708. struct completion_signature_probe_result<T>
  709. {
  710. typedef T type;
  711. template <template <typename...> class Op>
  712. struct apply
  713. {
  714. typedef Op<T> type;
  715. };
  716. };
  717. template <>
  718. struct completion_signature_probe_result<void>
  719. {
  720. template <template <typename...> class Op>
  721. struct apply
  722. {
  723. typedef Op<> type;
  724. };
  725. };
  726. } // namespace detail
  727. #if !defined(GENERATING_DOCUMENTATION)
  728. template <typename... Signatures>
  729. class async_result<detail::completion_signature_probe, Signatures...>
  730. {
  731. public:
  732. typedef detail::completion_signature_probe_result<Signatures...> return_type;
  733. template <typename Initiation, typename... InitArgs>
  734. static return_type initiate(Initiation&&,
  735. detail::completion_signature_probe, InitArgs&&...)
  736. {
  737. return return_type();
  738. }
  739. };
  740. template <typename Signature>
  741. class async_result<detail::completion_signature_probe, Signature>
  742. {
  743. public:
  744. typedef detail::completion_signature_probe_result<Signature> return_type;
  745. template <typename Initiation, typename... InitArgs>
  746. static return_type initiate(Initiation&&,
  747. detail::completion_signature_probe, InitArgs&&...)
  748. {
  749. return return_type();
  750. }
  751. };
  752. #endif // !defined(GENERATING_DOCUMENTATION)
  753. #if defined(GENERATING_DOCUMENTATION)
  754. /// The completion_signature_of trait determines the completion signature
  755. /// of an asynchronous operation.
  756. /**
  757. * Class template @c completion_signature_of is a trait with a member type
  758. * alias @c type that denotes the completion signature of the asynchronous
  759. * operation initiated by the expression <tt>T(Args..., token)</tt> operation,
  760. * where @c token is an unspecified completion token type. If the asynchronous
  761. * operation does not have exactly one completion signature, the instantion of
  762. * the trait is well-formed but the member type alias @c type is omitted. If
  763. * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation
  764. * then use of the trait is ill-formed.
  765. */
  766. template <typename T, typename... Args>
  767. struct completion_signature_of
  768. {
  769. typedef automatically_determined type;
  770. };
  771. #else // defined(GENERATING_DOCUMENTATION)
  772. template <typename T, typename... Args>
  773. struct completion_signature_of :
  774. result_of_t<T(Args..., detail::completion_signature_probe)>
  775. {
  776. };
  777. #endif // defined(GENERATING_DOCUMENTATION)
  778. template <typename T, typename... Args>
  779. using completion_signature_of_t =
  780. typename completion_signature_of<T, Args...>::type;
  781. } // namespace asio
  782. } // namespace boost
  783. #include <boost/asio/detail/pop_options.hpp>
  784. #include <boost/asio/default_completion_token.hpp>
  785. #endif // BOOST_ASIO_ASYNC_RESULT_HPP