async_result.hpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. //
  2. // async_result.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 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 trait is a customisation point that is used within the
  274. * initiating function for an @ref asynchronous_operation. The trait combines:
  275. *
  276. * @li the completion signature (or signatures) that describe the arguments that
  277. * an asynchronous operation will pass to a completion handler;
  278. *
  279. * @li the @ref completion_token type supplied by the caller; and
  280. *
  281. * @li the operation's internal implementation.
  282. *
  283. * Specialisations of the trait must satisfy the @ref async_result_requirements,
  284. * and are reponsible for determining:
  285. *
  286. * @li the concrete completion handler type to be called at the end of the
  287. * asynchronous operation;
  288. *
  289. * @li the initiating function return type;
  290. *
  291. * @li how the return value of the initiating function is obtained; and
  292. *
  293. * @li how and when to launch the operation by invoking the supplied initiation
  294. * function object.
  295. *
  296. * This template may be specialised for user-defined completion token types.
  297. * The primary template assumes that the CompletionToken is the already a
  298. * concrete completion handler.
  299. *
  300. * @note For backwards compatibility, the primary template implements member
  301. * types and functions that are associated with legacy forms of the async_result
  302. * trait. These are annotated as "Legacy" in the documentation below. User
  303. * specialisations of this trait do not need to implement these in order to
  304. * satisfy the @ref async_result_requirements.
  305. *
  306. * In general, implementers of asynchronous operations should use the
  307. * async_initiate function rather than using the async_result trait directly.
  308. *
  309. * For a more detailed discussion of the role of async_result and
  310. * async_initiate, see the overview documentation for @ref completion_token.
  311. */
  312. template <typename CompletionToken,
  313. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  314. class async_result
  315. {
  316. public:
  317. /// (Legacy.) The concrete completion handler type for the specific signature.
  318. typedef CompletionToken completion_handler_type;
  319. /// (Legacy.) The return type of the initiating function.
  320. typedef void return_type;
  321. /// (Legacy.) Construct an async result from a given handler.
  322. /**
  323. * When using a specalised async_result, the constructor has an opportunity
  324. * to initialise some state associated with the completion handler, which is
  325. * then returned from the initiating function.
  326. */
  327. explicit async_result(completion_handler_type& h);
  328. /// (Legacy.) Obtain the value to be returned from the initiating function.
  329. return_type get();
  330. /// Initiate the asynchronous operation that will produce the result, and
  331. /// obtain the value to be returned from the initiating function.
  332. template <typename Initiation, typename RawCompletionToken, typename... Args>
  333. static return_type initiate(
  334. Initiation&& initiation,
  335. RawCompletionToken&& token,
  336. Args&&... args);
  337. private:
  338. async_result(const async_result&) = delete;
  339. async_result& operator=(const async_result&) = delete;
  340. };
  341. #else // defined(GENERATING_DOCUMENTATION)
  342. template <typename CompletionToken,
  343. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  344. class async_result :
  345. public conditional_t<
  346. detail::are_any_lvalue_completion_signatures<Signatures...>::value
  347. || !detail::are_any_rvalue_completion_signatures<Signatures...>::value,
  348. detail::completion_handler_async_result<CompletionToken, Signatures...>,
  349. async_result<CompletionToken,
  350. typename detail::simple_completion_signature<Signatures>::type...>
  351. >
  352. {
  353. public:
  354. typedef conditional_t<
  355. detail::are_any_lvalue_completion_signatures<Signatures...>::value
  356. || !detail::are_any_rvalue_completion_signatures<Signatures...>::value,
  357. detail::completion_handler_async_result<CompletionToken, Signatures...>,
  358. async_result<CompletionToken,
  359. typename detail::simple_completion_signature<Signatures>::type...>
  360. > base_type;
  361. using base_type::base_type;
  362. private:
  363. async_result(const async_result&) = delete;
  364. async_result& operator=(const async_result&) = delete;
  365. };
  366. template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  367. class async_result<void, Signatures...>
  368. {
  369. // Empty.
  370. };
  371. #endif // defined(GENERATING_DOCUMENTATION)
  372. /// (Legacy.) Helper template to deduce the handler type from a CompletionToken,
  373. /// capture a local copy of the handler, and then create an async_result for the
  374. /// handler.
  375. template <typename CompletionToken,
  376. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  377. struct async_completion
  378. {
  379. /// The real handler type to be used for the asynchronous operation.
  380. typedef typename boost::asio::async_result<
  381. decay_t<CompletionToken>, Signatures...>::completion_handler_type
  382. completion_handler_type;
  383. /// Constructor.
  384. /**
  385. * The constructor creates the concrete completion handler and makes the link
  386. * between the handler and the asynchronous result.
  387. */
  388. explicit async_completion(CompletionToken& token)
  389. : completion_handler(static_cast<conditional_t<
  390. is_same<CompletionToken, completion_handler_type>::value,
  391. completion_handler_type&, CompletionToken&&>>(token)),
  392. result(completion_handler)
  393. {
  394. }
  395. /// A copy of, or reference to, a real handler object.
  396. conditional_t<
  397. is_same<CompletionToken, completion_handler_type>::value,
  398. completion_handler_type&, completion_handler_type> completion_handler;
  399. /// The result of the asynchronous operation's initiating function.
  400. async_result<decay_t<CompletionToken>, Signatures...> result;
  401. };
  402. namespace detail {
  403. struct async_result_memfns_base
  404. {
  405. void initiate();
  406. };
  407. template <typename T>
  408. struct async_result_memfns_derived
  409. : T, async_result_memfns_base
  410. {
  411. };
  412. template <typename T, T>
  413. struct async_result_memfns_check
  414. {
  415. };
  416. template <typename>
  417. char (&async_result_initiate_memfn_helper(...))[2];
  418. template <typename T>
  419. char async_result_initiate_memfn_helper(
  420. async_result_memfns_check<
  421. void (async_result_memfns_base::*)(),
  422. &async_result_memfns_derived<T>::initiate>*);
  423. template <typename CompletionToken,
  424. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures>
  425. struct async_result_has_initiate_memfn
  426. : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
  427. async_result<decay_t<CompletionToken>, Signatures...>
  428. >(0)) != 1>
  429. {
  430. };
  431. } // namespace detail
  432. #if defined(GENERATING_DOCUMENTATION)
  433. # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
  434. void_or_deduced
  435. # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \
  436. void_or_deduced
  437. # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  438. void_or_deduced
  439. #else
  440. # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
  441. typename ::boost::asio::async_result< \
  442. typename ::boost::asio::decay<ct>::type, sig>::return_type
  443. # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \
  444. typename ::boost::asio::async_result< \
  445. typename ::boost::asio::decay<ct>::type, sig0, sig1>::return_type
  446. # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  447. typename ::boost::asio::async_result< \
  448. typename ::boost::asio::decay<ct>::type, sig0, sig1, sig2>::return_type
  449. #define BOOST_ASIO_HANDLER_TYPE(ct, sig) \
  450. typename ::boost::asio::async_result< \
  451. typename ::boost::asio::decay<ct>::type, sig>::completion_handler_type
  452. #define BOOST_ASIO_HANDLER_TYPE2(ct, sig0, sig1) \
  453. typename ::boost::asio::async_result< \
  454. typename ::boost::asio::decay<ct>::type, \
  455. sig0, sig1>::completion_handler_type
  456. #define BOOST_ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \
  457. typename ::boost::asio::async_result< \
  458. typename ::boost::asio::decay<ct>::type, \
  459. sig0, sig1, sig2>::completion_handler_type
  460. #endif
  461. #if defined(GENERATING_DOCUMENTATION)
  462. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  463. auto
  464. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  465. auto
  466. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  467. auto
  468. #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
  469. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  470. auto
  471. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  472. auto
  473. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  474. auto
  475. #else
  476. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \
  477. BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig)
  478. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \
  479. BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)
  480. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \
  481. BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)
  482. #endif
  483. #if defined(GENERATING_DOCUMENTATION)
  484. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  485. auto
  486. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  487. auto
  488. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  489. auto
  490. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)
  491. #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
  492. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  493. auto
  494. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  495. auto
  496. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  497. auto
  498. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)
  499. #else
  500. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \
  501. auto
  502. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \
  503. auto
  504. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \
  505. auto
  506. # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr
  507. #endif
  508. #if defined(GENERATING_DOCUMENTATION)
  509. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \
  510. void_or_deduced
  511. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \
  512. void_or_deduced
  513. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \
  514. void_or_deduced
  515. #else
  516. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \
  517. decltype expr
  518. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \
  519. decltype expr
  520. # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \
  521. decltype expr
  522. #endif
  523. #if defined(GENERATING_DOCUMENTATION)
  524. /// Helper function for implementing an asynchronous operation's initiating
  525. /// function.
  526. /**
  527. * The async_initiate function wraps the async_result trait. It automatically
  528. * performs the necessary decay and forward of the completion token, and also
  529. * enables backwards compatibility with legacy completion token implementations.
  530. *
  531. * @param initiation A function object that will be called to launch the
  532. * asynchronous operation. It receives the concrete completion handler as its
  533. * first argument, followed by any additional arguments passed to
  534. * async_initiate.
  535. *
  536. * @param token The @ref completion_token provided by the user. This will be
  537. * transformed into a concrete completion handler by the async_result trait.
  538. *
  539. * @param args Additional arguments to be forwarded to the initiation function
  540. * object.
  541. *
  542. * @returns The return value is determined by the async_result specialisation
  543. * for the completion token type. For callback-based tokens, returns @c void.
  544. * For other tokens such as use_future or use_awaitable, returns the
  545. * corresponding future or awaitable type.
  546. *
  547. * @note Asynchronous operation implementations should use this function rather
  548. * than directly using the async_result trait, or the legacy async_completion
  549. * helper template.
  550. *
  551. * For a more detailed discussion of the role of async_result and
  552. * async_initiate, see the overview documentation for @ref completion_token.
  553. */
  554. template <typename CompletionToken,
  555. completion_signature... Signatures,
  556. typename Initiation, typename... Args>
  557. void_or_deduced async_initiate(
  558. Initiation&& initiation,
  559. type_identity_t<CompletionToken>& token,
  560. Args&&... args);
  561. #else // defined(GENERATING_DOCUMENTATION)
  562. template <typename CompletionToken,
  563. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  564. typename Initiation, typename... Args>
  565. inline auto async_initiate(Initiation&& initiation,
  566. type_identity_t<CompletionToken>& token, Args&&... args)
  567. -> decltype(enable_if_t<
  568. enable_if_t<
  569. detail::are_completion_signatures<Signatures...>::value,
  570. detail::async_result_has_initiate_memfn<
  571. CompletionToken, Signatures...>>::value,
  572. async_result<decay_t<CompletionToken>, Signatures...>>::initiate(
  573. static_cast<Initiation&&>(initiation),
  574. static_cast<CompletionToken&&>(token),
  575. static_cast<Args&&>(args)...))
  576. {
  577. return async_result<decay_t<CompletionToken>, Signatures...>::initiate(
  578. static_cast<Initiation&&>(initiation),
  579. static_cast<CompletionToken&&>(token),
  580. static_cast<Args&&>(args)...);
  581. }
  582. template <
  583. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  584. typename CompletionToken, typename Initiation, typename... Args>
  585. inline auto async_initiate(Initiation&& initiation,
  586. CompletionToken&& token, Args&&... args)
  587. -> decltype(enable_if_t<
  588. enable_if_t<
  589. detail::are_completion_signatures<Signatures...>::value,
  590. detail::async_result_has_initiate_memfn<
  591. CompletionToken, Signatures...>>::value,
  592. async_result<decay_t<CompletionToken>, Signatures...>>::initiate(
  593. static_cast<Initiation&&>(initiation),
  594. static_cast<CompletionToken&&>(token),
  595. static_cast<Args&&>(args)...))
  596. {
  597. return async_result<decay_t<CompletionToken>, Signatures...>::initiate(
  598. static_cast<Initiation&&>(initiation),
  599. static_cast<CompletionToken&&>(token),
  600. static_cast<Args&&>(args)...);
  601. }
  602. template <typename CompletionToken,
  603. BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  604. typename Initiation, typename... Args>
  605. inline typename enable_if_t<
  606. !enable_if_t<
  607. detail::are_completion_signatures<Signatures...>::value,
  608. detail::async_result_has_initiate_memfn<
  609. CompletionToken, Signatures...>>::value,
  610. async_result<decay_t<CompletionToken>, Signatures...>
  611. >::return_type
  612. async_initiate(Initiation&& initiation,
  613. type_identity_t<CompletionToken>& token, Args&&... args)
  614. {
  615. async_completion<CompletionToken, Signatures...> completion(token);
  616. static_cast<Initiation&&>(initiation)(
  617. static_cast<
  618. typename async_result<decay_t<CompletionToken>,
  619. Signatures...>::completion_handler_type&&>(
  620. completion.completion_handler),
  621. static_cast<Args&&>(args)...);
  622. return completion.result.get();
  623. }
  624. template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
  625. typename CompletionToken, typename Initiation, typename... Args>
  626. inline typename enable_if_t<
  627. !enable_if_t<
  628. detail::are_completion_signatures<Signatures...>::value,
  629. detail::async_result_has_initiate_memfn<
  630. CompletionToken, Signatures...>>::value,
  631. async_result<decay_t<CompletionToken>, Signatures...>
  632. >::return_type
  633. async_initiate(Initiation&& initiation, CompletionToken&& token, Args&&... args)
  634. {
  635. async_completion<CompletionToken, Signatures...> completion(token);
  636. static_cast<Initiation&&>(initiation)(
  637. static_cast<
  638. typename async_result<decay_t<CompletionToken>,
  639. Signatures...>::completion_handler_type&&>(
  640. completion.completion_handler),
  641. static_cast<Args&&>(args)...);
  642. return completion.result.get();
  643. }
  644. #endif // defined(GENERATING_DOCUMENTATION)
  645. #if defined(BOOST_ASIO_HAS_CONCEPTS)
  646. namespace detail {
  647. template <typename... Signatures>
  648. struct initiation_archetype
  649. {
  650. template <completion_handler_for<Signatures...> CompletionHandler>
  651. void operator()(CompletionHandler&&) const
  652. {
  653. }
  654. };
  655. } // namespace detail
  656. template <typename T, typename... Signatures>
  657. BOOST_ASIO_CONCEPT completion_token_for =
  658. detail::are_completion_signatures<Signatures...>::value
  659. &&
  660. requires(T&& t)
  661. {
  662. async_initiate<T, Signatures...>(
  663. detail::initiation_archetype<Signatures...>{}, t);
  664. };
  665. #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) \
  666. ::boost::asio::completion_token_for<sig>
  667. #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \
  668. ::boost::asio::completion_token_for<sig0, sig1>
  669. #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \
  670. ::boost::asio::completion_token_for<sig0, sig1, sig2>
  671. #else // defined(BOOST_ASIO_HAS_CONCEPTS)
  672. #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) typename
  673. #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename
  674. #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename
  675. #endif // defined(BOOST_ASIO_HAS_CONCEPTS)
  676. namespace detail {
  677. struct async_operation_probe {};
  678. struct async_operation_probe_result {};
  679. template <typename Call, typename = void>
  680. struct is_async_operation_call : false_type
  681. {
  682. };
  683. template <typename Call>
  684. struct is_async_operation_call<Call,
  685. void_t<
  686. enable_if_t<
  687. is_same<
  688. result_of_t<Call>,
  689. async_operation_probe_result
  690. >::value
  691. >
  692. >
  693. > : true_type
  694. {
  695. };
  696. } // namespace detail
  697. #if !defined(GENERATING_DOCUMENTATION)
  698. template <typename... Signatures>
  699. class async_result<detail::async_operation_probe, Signatures...>
  700. {
  701. public:
  702. typedef detail::async_operation_probe_result return_type;
  703. template <typename Initiation, typename... InitArgs>
  704. static return_type initiate(Initiation&&,
  705. detail::async_operation_probe, InitArgs&&...)
  706. {
  707. return return_type();
  708. }
  709. };
  710. #endif // !defined(GENERATING_DOCUMENTATION)
  711. #if defined(GENERATING_DOCUMENTATION)
  712. /// The is_async_operation trait detects whether a type @c T and arguments
  713. /// @c Args... may be used to initiate an asynchronous operation.
  714. /**
  715. * Class template @c is_async_operation is a trait is derived from @c true_type
  716. * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous
  717. * operation, where @c token is an unspecified completion token type. Otherwise,
  718. * @c is_async_operation is derived from @c false_type.
  719. */
  720. template <typename T, typename... Args>
  721. struct is_async_operation : integral_constant<bool, automatically_determined>
  722. {
  723. };
  724. #else // defined(GENERATING_DOCUMENTATION)
  725. template <typename T, typename... Args>
  726. struct is_async_operation :
  727. detail::is_async_operation_call<
  728. T(Args..., detail::async_operation_probe)>
  729. {
  730. };
  731. #endif // defined(GENERATING_DOCUMENTATION)
  732. #if defined(BOOST_ASIO_HAS_CONCEPTS)
  733. template <typename T, typename... Args>
  734. BOOST_ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value;
  735. #define BOOST_ASIO_ASYNC_OPERATION \
  736. ::boost::asio::async_operation
  737. #define BOOST_ASIO_ASYNC_OPERATION1(a0) \
  738. ::boost::asio::async_operation<a0>
  739. #define BOOST_ASIO_ASYNC_OPERATION2(a0, a1) \
  740. ::boost::asio::async_operation<a0, a1>
  741. #define BOOST_ASIO_ASYNC_OPERATION3(a0, a1, a2) \
  742. ::boost::asio::async_operation<a0, a1, a2>
  743. #else // defined(BOOST_ASIO_HAS_CONCEPTS)
  744. #define BOOST_ASIO_ASYNC_OPERATION typename
  745. #define BOOST_ASIO_ASYNC_OPERATION1(a0) typename
  746. #define BOOST_ASIO_ASYNC_OPERATION2(a0, a1) typename
  747. #define BOOST_ASIO_ASYNC_OPERATION3(a0, a1, a2) typename
  748. #endif // defined(BOOST_ASIO_HAS_CONCEPTS)
  749. namespace detail {
  750. struct completion_signature_probe {};
  751. template <typename... T>
  752. struct completion_signature_probe_result
  753. {
  754. template <template <typename...> class Op>
  755. struct apply
  756. {
  757. typedef Op<T...> type;
  758. };
  759. };
  760. template <typename T>
  761. struct completion_signature_probe_result<T>
  762. {
  763. typedef T type;
  764. template <template <typename...> class Op>
  765. struct apply
  766. {
  767. typedef Op<T> type;
  768. };
  769. };
  770. template <>
  771. struct completion_signature_probe_result<void>
  772. {
  773. template <template <typename...> class Op>
  774. struct apply
  775. {
  776. typedef Op<> type;
  777. };
  778. };
  779. } // namespace detail
  780. #if !defined(GENERATING_DOCUMENTATION)
  781. template <typename... Signatures>
  782. class async_result<detail::completion_signature_probe, Signatures...>
  783. {
  784. public:
  785. typedef detail::completion_signature_probe_result<Signatures...> return_type;
  786. template <typename Initiation, typename... InitArgs>
  787. static return_type initiate(Initiation&&,
  788. detail::completion_signature_probe, InitArgs&&...)
  789. {
  790. return return_type();
  791. }
  792. };
  793. template <typename Signature>
  794. class async_result<detail::completion_signature_probe, Signature>
  795. {
  796. public:
  797. typedef detail::completion_signature_probe_result<Signature> return_type;
  798. template <typename Initiation, typename... InitArgs>
  799. static return_type initiate(Initiation&&,
  800. detail::completion_signature_probe, InitArgs&&...)
  801. {
  802. return return_type();
  803. }
  804. };
  805. #endif // !defined(GENERATING_DOCUMENTATION)
  806. #if defined(GENERATING_DOCUMENTATION)
  807. /// The completion_signature_of trait determines the completion signature
  808. /// of an asynchronous operation.
  809. /**
  810. * Class template @c completion_signature_of is a trait with a member type
  811. * alias @c type that denotes the completion signature of the asynchronous
  812. * operation initiated by the expression <tt>T(Args..., token)</tt> operation,
  813. * where @c token is an unspecified completion token type. If the asynchronous
  814. * operation does not have exactly one completion signature, the instantion of
  815. * the trait is well-formed but the member type alias @c type is omitted. If
  816. * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation
  817. * then use of the trait is ill-formed.
  818. */
  819. template <typename T, typename... Args>
  820. struct completion_signature_of
  821. {
  822. typedef automatically_determined type;
  823. };
  824. #else // defined(GENERATING_DOCUMENTATION)
  825. template <typename T, typename... Args>
  826. struct completion_signature_of :
  827. result_of_t<T(Args..., detail::completion_signature_probe)>
  828. {
  829. };
  830. #endif // defined(GENERATING_DOCUMENTATION)
  831. template <typename T, typename... Args>
  832. using completion_signature_of_t =
  833. typename completion_signature_of<T, Args...>::type;
  834. } // namespace asio
  835. } // namespace boost
  836. #include <boost/asio/detail/pop_options.hpp>
  837. #include <boost/asio/default_completion_token.hpp>
  838. #endif // BOOST_ASIO_ASYNC_RESULT_HPP