async_result.hpp 24 KB

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