use_future.hpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. //
  2. // impl/use_future.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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_IMPL_USE_FUTURE_HPP
  11. #define BOOST_ASIO_IMPL_USE_FUTURE_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 <tuple>
  17. #include <boost/asio/async_result.hpp>
  18. #include <boost/asio/detail/memory.hpp>
  19. #include <boost/asio/dispatch.hpp>
  20. #include <boost/system/error_code.hpp>
  21. #include <boost/asio/execution.hpp>
  22. #include <boost/asio/packaged_task.hpp>
  23. #include <boost/system/system_error.hpp>
  24. #include <boost/asio/system_executor.hpp>
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. namespace detail {
  29. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  30. template <typename T, typename F, typename... Args>
  31. inline void promise_invoke_and_set(std::promise<T>& p,
  32. F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
  33. {
  34. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  35. try
  36. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  37. {
  38. p.set_value(f(BOOST_ASIO_MOVE_CAST(Args)(args)...));
  39. }
  40. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  41. catch (...)
  42. {
  43. p.set_exception(std::current_exception());
  44. }
  45. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  46. }
  47. template <typename F, typename... Args>
  48. inline void promise_invoke_and_set(std::promise<void>& p,
  49. F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
  50. {
  51. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  52. try
  53. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  54. {
  55. f(BOOST_ASIO_MOVE_CAST(Args)(args)...);
  56. p.set_value();
  57. }
  58. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  59. catch (...)
  60. {
  61. p.set_exception(std::current_exception());
  62. }
  63. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  64. }
  65. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  66. template <typename T, typename F>
  67. inline void promise_invoke_and_set(std::promise<T>& p, F& f)
  68. {
  69. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  70. try
  71. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  72. {
  73. p.set_value(f());
  74. }
  75. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  76. catch (...)
  77. {
  78. p.set_exception(std::current_exception());
  79. }
  80. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  81. }
  82. template <typename F, typename Args>
  83. inline void promise_invoke_and_set(std::promise<void>& p, F& f)
  84. {
  85. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  86. try
  87. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  88. {
  89. f();
  90. p.set_value();
  91. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  92. }
  93. catch (...)
  94. {
  95. p.set_exception(std::current_exception());
  96. }
  97. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  98. }
  99. #if defined(BOOST_ASIO_NO_EXCEPTIONS)
  100. #define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
  101. template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  102. inline void promise_invoke_and_set(std::promise<T>& p, \
  103. F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  104. { \
  105. p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  106. } \
  107. \
  108. template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  109. inline void promise_invoke_and_set(std::promise<void>& p, \
  110. F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  111. { \
  112. f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  113. p.set_value(); \
  114. } \
  115. /**/
  116. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
  117. #undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
  118. #else // defined(BOOST_ASIO_NO_EXCEPTIONS)
  119. #define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
  120. template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  121. inline void promise_invoke_and_set(std::promise<T>& p, \
  122. F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  123. { \
  124. try \
  125. { \
  126. p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  127. } \
  128. catch (...) \
  129. { \
  130. p.set_exception(std::current_exception()); \
  131. } \
  132. } \
  133. \
  134. template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  135. inline void promise_invoke_and_set(std::promise<void>& p, \
  136. F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  137. { \
  138. try \
  139. { \
  140. f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  141. p.set_value(); \
  142. } \
  143. catch (...) \
  144. { \
  145. p.set_exception(std::current_exception()); \
  146. } \
  147. } \
  148. /**/
  149. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
  150. #undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
  151. #endif // defined(BOOST_ASIO_NO_EXCEPTIONS)
  152. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  153. // A function object adapter to invoke a nullary function object and capture
  154. // any exception thrown into a promise.
  155. template <typename T, typename F>
  156. class promise_invoker
  157. {
  158. public:
  159. promise_invoker(const shared_ptr<std::promise<T> >& p,
  160. BOOST_ASIO_MOVE_ARG(F) f)
  161. : p_(p), f_(BOOST_ASIO_MOVE_CAST(F)(f))
  162. {
  163. }
  164. void operator()()
  165. {
  166. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  167. try
  168. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  169. {
  170. f_();
  171. }
  172. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  173. catch (...)
  174. {
  175. p_->set_exception(std::current_exception());
  176. }
  177. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  178. }
  179. private:
  180. shared_ptr<std::promise<T> > p_;
  181. typename decay<F>::type f_;
  182. };
  183. // An executor that adapts the system_executor to capture any exeption thrown
  184. // by a submitted function object and save it into a promise.
  185. template <typename T, typename Blocking = execution::blocking_t::possibly_t>
  186. class promise_executor
  187. {
  188. public:
  189. explicit promise_executor(const shared_ptr<std::promise<T> >& p)
  190. : p_(p)
  191. {
  192. }
  193. static BOOST_ASIO_CONSTEXPR Blocking query(execution::blocking_t)
  194. {
  195. return Blocking();
  196. }
  197. promise_executor<T, execution::blocking_t::possibly_t>
  198. require(execution::blocking_t::possibly_t) const
  199. {
  200. return promise_executor<T, execution::blocking_t::possibly_t>(p_);
  201. }
  202. promise_executor<T, execution::blocking_t::never_t>
  203. require(execution::blocking_t::never_t) const
  204. {
  205. return promise_executor<T, execution::blocking_t::never_t>(p_);
  206. }
  207. template <typename F>
  208. void execute(BOOST_ASIO_MOVE_ARG(F) f) const
  209. {
  210. execution::execute(
  211. boost::asio::require(system_executor(), Blocking()),
  212. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
  213. }
  214. #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  215. execution_context& context() const BOOST_ASIO_NOEXCEPT
  216. {
  217. return system_executor().context();
  218. }
  219. void on_work_started() const BOOST_ASIO_NOEXCEPT {}
  220. void on_work_finished() const BOOST_ASIO_NOEXCEPT {}
  221. template <typename F, typename A>
  222. void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A&) const
  223. {
  224. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f))();
  225. }
  226. template <typename F, typename A>
  227. void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  228. {
  229. system_executor().post(
  230. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
  231. }
  232. template <typename F, typename A>
  233. void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  234. {
  235. system_executor().defer(
  236. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
  237. }
  238. #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  239. friend bool operator==(const promise_executor& a,
  240. const promise_executor& b) BOOST_ASIO_NOEXCEPT
  241. {
  242. return a.p_ == b.p_;
  243. }
  244. friend bool operator!=(const promise_executor& a,
  245. const promise_executor& b) BOOST_ASIO_NOEXCEPT
  246. {
  247. return a.p_ != b.p_;
  248. }
  249. private:
  250. shared_ptr<std::promise<T> > p_;
  251. };
  252. // The base class for all completion handlers that create promises.
  253. template <typename T>
  254. class promise_creator
  255. {
  256. public:
  257. typedef promise_executor<T> executor_type;
  258. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  259. {
  260. return executor_type(p_);
  261. }
  262. typedef std::future<T> future_type;
  263. future_type get_future()
  264. {
  265. return p_->get_future();
  266. }
  267. protected:
  268. template <typename Allocator>
  269. void create_promise(const Allocator& a)
  270. {
  271. BOOST_ASIO_REBIND_ALLOC(Allocator, char) b(a);
  272. p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
  273. }
  274. shared_ptr<std::promise<T> > p_;
  275. };
  276. // For completion signature void().
  277. class promise_handler_0
  278. : public promise_creator<void>
  279. {
  280. public:
  281. void operator()()
  282. {
  283. this->p_->set_value();
  284. }
  285. };
  286. // For completion signature void(error_code).
  287. class promise_handler_ec_0
  288. : public promise_creator<void>
  289. {
  290. public:
  291. void operator()(const boost::system::error_code& ec)
  292. {
  293. if (ec)
  294. {
  295. this->p_->set_exception(
  296. std::make_exception_ptr(
  297. boost::system::system_error(ec)));
  298. }
  299. else
  300. {
  301. this->p_->set_value();
  302. }
  303. }
  304. };
  305. // For completion signature void(exception_ptr).
  306. class promise_handler_ex_0
  307. : public promise_creator<void>
  308. {
  309. public:
  310. void operator()(const std::exception_ptr& ex)
  311. {
  312. if (ex)
  313. {
  314. this->p_->set_exception(ex);
  315. }
  316. else
  317. {
  318. this->p_->set_value();
  319. }
  320. }
  321. };
  322. // For completion signature void(T).
  323. template <typename T>
  324. class promise_handler_1
  325. : public promise_creator<T>
  326. {
  327. public:
  328. template <typename Arg>
  329. void operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
  330. {
  331. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  332. }
  333. };
  334. // For completion signature void(error_code, T).
  335. template <typename T>
  336. class promise_handler_ec_1
  337. : public promise_creator<T>
  338. {
  339. public:
  340. template <typename Arg>
  341. void operator()(const boost::system::error_code& ec,
  342. BOOST_ASIO_MOVE_ARG(Arg) arg)
  343. {
  344. if (ec)
  345. {
  346. this->p_->set_exception(
  347. std::make_exception_ptr(
  348. boost::system::system_error(ec)));
  349. }
  350. else
  351. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  352. }
  353. };
  354. // For completion signature void(exception_ptr, T).
  355. template <typename T>
  356. class promise_handler_ex_1
  357. : public promise_creator<T>
  358. {
  359. public:
  360. template <typename Arg>
  361. void operator()(const std::exception_ptr& ex,
  362. BOOST_ASIO_MOVE_ARG(Arg) arg)
  363. {
  364. if (ex)
  365. this->p_->set_exception(ex);
  366. else
  367. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  368. }
  369. };
  370. // For completion signature void(T1, ..., Tn);
  371. template <typename T>
  372. class promise_handler_n
  373. : public promise_creator<T>
  374. {
  375. public:
  376. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  377. template <typename... Args>
  378. void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
  379. {
  380. this->p_->set_value(
  381. std::forward_as_tuple(
  382. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  383. }
  384. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  385. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  386. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  387. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  388. {\
  389. this->p_->set_value( \
  390. std::forward_as_tuple( \
  391. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  392. } \
  393. /**/
  394. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  395. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  396. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  397. };
  398. // For completion signature void(error_code, T1, ..., Tn);
  399. template <typename T>
  400. class promise_handler_ec_n
  401. : public promise_creator<T>
  402. {
  403. public:
  404. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  405. template <typename... Args>
  406. void operator()(const boost::system::error_code& ec,
  407. BOOST_ASIO_MOVE_ARG(Args)... args)
  408. {
  409. if (ec)
  410. {
  411. this->p_->set_exception(
  412. std::make_exception_ptr(
  413. boost::system::system_error(ec)));
  414. }
  415. else
  416. {
  417. this->p_->set_value(
  418. std::forward_as_tuple(
  419. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  420. }
  421. }
  422. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  423. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  424. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  425. void operator()(const boost::system::error_code& ec, \
  426. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  427. {\
  428. if (ec) \
  429. { \
  430. this->p_->set_exception( \
  431. std::make_exception_ptr( \
  432. boost::system::system_error(ec))); \
  433. } \
  434. else \
  435. { \
  436. this->p_->set_value( \
  437. std::forward_as_tuple( \
  438. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  439. } \
  440. } \
  441. /**/
  442. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  443. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  444. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  445. };
  446. // For completion signature void(exception_ptr, T1, ..., Tn);
  447. template <typename T>
  448. class promise_handler_ex_n
  449. : public promise_creator<T>
  450. {
  451. public:
  452. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  453. template <typename... Args>
  454. void operator()(const std::exception_ptr& ex,
  455. BOOST_ASIO_MOVE_ARG(Args)... args)
  456. {
  457. if (ex)
  458. this->p_->set_exception(ex);
  459. else
  460. {
  461. this->p_->set_value(
  462. std::forward_as_tuple(
  463. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  464. }
  465. }
  466. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  467. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  468. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  469. void operator()(const std::exception_ptr& ex, \
  470. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  471. {\
  472. if (ex) \
  473. this->p_->set_exception(ex); \
  474. else \
  475. { \
  476. this->p_->set_value( \
  477. std::forward_as_tuple( \
  478. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  479. } \
  480. } \
  481. /**/
  482. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  483. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  484. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  485. };
  486. // Helper template to choose the appropriate concrete promise handler
  487. // implementation based on the supplied completion signature.
  488. template <typename> class promise_handler_selector;
  489. template <>
  490. class promise_handler_selector<void()>
  491. : public promise_handler_0 {};
  492. template <>
  493. class promise_handler_selector<void(boost::system::error_code)>
  494. : public promise_handler_ec_0 {};
  495. template <>
  496. class promise_handler_selector<void(std::exception_ptr)>
  497. : public promise_handler_ex_0 {};
  498. template <typename Arg>
  499. class promise_handler_selector<void(Arg)>
  500. : public promise_handler_1<Arg> {};
  501. template <typename Arg>
  502. class promise_handler_selector<void(boost::system::error_code, Arg)>
  503. : public promise_handler_ec_1<Arg> {};
  504. template <typename Arg>
  505. class promise_handler_selector<void(std::exception_ptr, Arg)>
  506. : public promise_handler_ex_1<Arg> {};
  507. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  508. template <typename... Arg>
  509. class promise_handler_selector<void(Arg...)>
  510. : public promise_handler_n<std::tuple<Arg...> > {};
  511. template <typename... Arg>
  512. class promise_handler_selector<void(boost::system::error_code, Arg...)>
  513. : public promise_handler_ec_n<std::tuple<Arg...> > {};
  514. template <typename... Arg>
  515. class promise_handler_selector<void(std::exception_ptr, Arg...)>
  516. : public promise_handler_ex_n<std::tuple<Arg...> > {};
  517. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  518. #define BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
  519. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  520. class promise_handler_selector< \
  521. void(Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  522. : public promise_handler_n< \
  523. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  524. \
  525. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  526. class promise_handler_selector< \
  527. void(boost::system::error_code, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  528. : public promise_handler_ec_n< \
  529. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  530. \
  531. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  532. class promise_handler_selector< \
  533. void(std::exception_ptr, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  534. : public promise_handler_ex_n< \
  535. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  536. /**/
  537. BOOST_ASIO_VARIADIC_GENERATE_5(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
  538. #undef BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF
  539. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  540. // Completion handlers produced from the use_future completion token, when not
  541. // using use_future::operator().
  542. template <typename Signature, typename Allocator>
  543. class promise_handler
  544. : public promise_handler_selector<Signature>
  545. {
  546. public:
  547. typedef Allocator allocator_type;
  548. typedef void result_type;
  549. promise_handler(use_future_t<Allocator> u)
  550. : allocator_(u.get_allocator())
  551. {
  552. this->create_promise(allocator_);
  553. }
  554. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  555. {
  556. return allocator_;
  557. }
  558. private:
  559. Allocator allocator_;
  560. };
  561. template <typename Function>
  562. struct promise_function_wrapper
  563. {
  564. explicit promise_function_wrapper(Function& f)
  565. : function_(BOOST_ASIO_MOVE_CAST(Function)(f))
  566. {
  567. }
  568. explicit promise_function_wrapper(const Function& f)
  569. : function_(f)
  570. {
  571. }
  572. void operator()()
  573. {
  574. function_();
  575. }
  576. Function function_;
  577. };
  578. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  579. template <typename Function, typename Signature, typename Allocator>
  580. inline void asio_handler_invoke(Function& f,
  581. promise_handler<Signature, Allocator>* h)
  582. {
  583. typename promise_handler<Signature, Allocator>::executor_type
  584. ex(h->get_executor());
  585. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  586. }
  587. template <typename Function, typename Signature, typename Allocator>
  588. inline void asio_handler_invoke(const Function& f,
  589. promise_handler<Signature, Allocator>* h)
  590. {
  591. typename promise_handler<Signature, Allocator>::executor_type
  592. ex(h->get_executor());
  593. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  594. }
  595. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  596. // Helper base class for async_result specialisation.
  597. template <typename Signature, typename Allocator>
  598. class promise_async_result
  599. {
  600. public:
  601. typedef promise_handler<Signature, Allocator> completion_handler_type;
  602. typedef typename completion_handler_type::future_type return_type;
  603. explicit promise_async_result(completion_handler_type& h)
  604. : future_(h.get_future())
  605. {
  606. }
  607. return_type get()
  608. {
  609. return BOOST_ASIO_MOVE_CAST(return_type)(future_);
  610. }
  611. private:
  612. return_type future_;
  613. };
  614. // Return value from use_future::operator().
  615. template <typename Function, typename Allocator>
  616. class packaged_token
  617. {
  618. public:
  619. packaged_token(Function f, const Allocator& a)
  620. : function_(BOOST_ASIO_MOVE_CAST(Function)(f)),
  621. allocator_(a)
  622. {
  623. }
  624. //private:
  625. Function function_;
  626. Allocator allocator_;
  627. };
  628. // Completion handlers produced from the use_future completion token, when
  629. // using use_future::operator().
  630. template <typename Function, typename Allocator, typename Result>
  631. class packaged_handler
  632. : public promise_creator<Result>
  633. {
  634. public:
  635. typedef Allocator allocator_type;
  636. typedef void result_type;
  637. packaged_handler(packaged_token<Function, Allocator> t)
  638. : function_(BOOST_ASIO_MOVE_CAST(Function)(t.function_)),
  639. allocator_(t.allocator_)
  640. {
  641. this->create_promise(allocator_);
  642. }
  643. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  644. {
  645. return allocator_;
  646. }
  647. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  648. template <typename... Args>
  649. void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
  650. {
  651. (promise_invoke_and_set)(*this->p_,
  652. function_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
  653. }
  654. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  655. void operator()()
  656. {
  657. (promise_invoke_and_set)(*this->p_, function_);
  658. }
  659. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  660. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  661. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  662. {\
  663. (promise_invoke_and_set)(*this->p_, \
  664. function_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  665. } \
  666. /**/
  667. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  668. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  669. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  670. private:
  671. Function function_;
  672. Allocator allocator_;
  673. };
  674. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  675. template <typename Function,
  676. typename Function1, typename Allocator, typename Result>
  677. inline void asio_handler_invoke(Function& f,
  678. packaged_handler<Function1, Allocator, Result>* h)
  679. {
  680. typename packaged_handler<Function1, Allocator, Result>::executor_type
  681. ex(h->get_executor());
  682. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  683. }
  684. template <typename Function,
  685. typename Function1, typename Allocator, typename Result>
  686. inline void asio_handler_invoke(const Function& f,
  687. packaged_handler<Function1, Allocator, Result>* h)
  688. {
  689. typename packaged_handler<Function1, Allocator, Result>::executor_type
  690. ex(h->get_executor());
  691. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  692. }
  693. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  694. // Helper base class for async_result specialisation.
  695. template <typename Function, typename Allocator, typename Result>
  696. class packaged_async_result
  697. {
  698. public:
  699. typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
  700. typedef typename completion_handler_type::future_type return_type;
  701. explicit packaged_async_result(completion_handler_type& h)
  702. : future_(h.get_future())
  703. {
  704. }
  705. return_type get()
  706. {
  707. return BOOST_ASIO_MOVE_CAST(return_type)(future_);
  708. }
  709. private:
  710. return_type future_;
  711. };
  712. } // namespace detail
  713. template <typename Allocator> template <typename Function>
  714. inline detail::packaged_token<typename decay<Function>::type, Allocator>
  715. use_future_t<Allocator>::operator()(BOOST_ASIO_MOVE_ARG(Function) f) const
  716. {
  717. return detail::packaged_token<typename decay<Function>::type, Allocator>(
  718. BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
  719. }
  720. #if !defined(GENERATING_DOCUMENTATION)
  721. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  722. template <typename Allocator, typename Result, typename... Args>
  723. class async_result<use_future_t<Allocator>, Result(Args...)>
  724. : public detail::promise_async_result<
  725. void(typename decay<Args>::type...), Allocator>
  726. {
  727. public:
  728. explicit async_result(
  729. typename detail::promise_async_result<void(typename decay<Args>::type...),
  730. Allocator>::completion_handler_type& h)
  731. : detail::promise_async_result<
  732. void(typename decay<Args>::type...), Allocator>(h)
  733. {
  734. }
  735. };
  736. template <typename Function, typename Allocator,
  737. typename Result, typename... Args>
  738. class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
  739. : public detail::packaged_async_result<Function, Allocator,
  740. typename result_of<Function(Args...)>::type>
  741. {
  742. public:
  743. explicit async_result(
  744. typename detail::packaged_async_result<Function, Allocator,
  745. typename result_of<Function(Args...)>::type>::completion_handler_type& h)
  746. : detail::packaged_async_result<Function, Allocator,
  747. typename result_of<Function(Args...)>::type>(h)
  748. {
  749. }
  750. };
  751. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  752. template <typename Allocator, typename Result>
  753. class async_result<use_future_t<Allocator>, Result()>
  754. : public detail::promise_async_result<void(), Allocator>
  755. {
  756. public:
  757. explicit async_result(
  758. typename detail::promise_async_result<
  759. void(), Allocator>::completion_handler_type& h)
  760. : detail::promise_async_result<void(), Allocator>(h)
  761. {
  762. }
  763. };
  764. template <typename Function, typename Allocator, typename Result>
  765. class async_result<detail::packaged_token<Function, Allocator>, Result()>
  766. : public detail::packaged_async_result<Function, Allocator,
  767. typename result_of<Function()>::type>
  768. {
  769. public:
  770. explicit async_result(
  771. typename detail::packaged_async_result<Function, Allocator,
  772. typename result_of<Function()>::type>::completion_handler_type& h)
  773. : detail::packaged_async_result<Function, Allocator,
  774. typename result_of<Function()>::type>(h)
  775. {
  776. }
  777. };
  778. #define BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
  779. template <typename Allocator, \
  780. typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  781. class async_result<use_future_t<Allocator>, \
  782. Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
  783. : public detail::promise_async_result< \
  784. void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator> \
  785. { \
  786. public: \
  787. explicit async_result( \
  788. typename detail::promise_async_result< \
  789. void(BOOST_ASIO_VARIADIC_DECAY(n)), \
  790. Allocator>::completion_handler_type& h) \
  791. : detail::promise_async_result< \
  792. void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator>(h) \
  793. { \
  794. } \
  795. }; \
  796. \
  797. template <typename Function, typename Allocator, \
  798. typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  799. class async_result<detail::packaged_token<Function, Allocator>, \
  800. Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
  801. : public detail::packaged_async_result<Function, Allocator, \
  802. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type> \
  803. { \
  804. public: \
  805. explicit async_result( \
  806. typename detail::packaged_async_result<Function, Allocator, \
  807. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type \
  808. >::completion_handler_type& h) \
  809. : detail::packaged_async_result<Function, Allocator, \
  810. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type>(h) \
  811. { \
  812. } \
  813. }; \
  814. /**/
  815. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF)
  816. #undef BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF
  817. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  818. namespace traits {
  819. #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  820. template <typename T, typename Blocking>
  821. struct equality_comparable<
  822. boost::asio::detail::promise_executor<T, Blocking> >
  823. {
  824. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  825. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  826. };
  827. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  828. #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  829. template <typename T, typename Blocking, typename Function>
  830. struct execute_member<
  831. boost::asio::detail::promise_executor<T, Blocking>, Function>
  832. {
  833. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  834. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  835. typedef void result_type;
  836. };
  837. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  838. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)
  839. template <typename T, typename Blocking, typename Property>
  840. struct query_static_constexpr_member<
  841. boost::asio::detail::promise_executor<T, Blocking>,
  842. Property,
  843. typename boost::asio::enable_if<
  844. boost::asio::is_convertible<
  845. Property,
  846. boost::asio::execution::blocking_t
  847. >::value
  848. >::type
  849. >
  850. {
  851. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  852. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  853. typedef Blocking result_type;
  854. static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
  855. {
  856. return Blocking();
  857. }
  858. };
  859. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)
  860. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  861. template <typename T, typename Blocking>
  862. struct require_member<
  863. boost::asio::detail::promise_executor<T, Blocking>,
  864. execution::blocking_t::possibly_t
  865. >
  866. {
  867. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  868. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  869. typedef boost::asio::detail::promise_executor<T,
  870. execution::blocking_t::possibly_t> result_type;
  871. };
  872. template <typename T, typename Blocking>
  873. struct require_member<
  874. boost::asio::detail::promise_executor<T, Blocking>,
  875. execution::blocking_t::never_t
  876. >
  877. {
  878. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  879. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  880. typedef boost::asio::detail::promise_executor<T,
  881. execution::blocking_t::never_t> result_type;
  882. };
  883. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  884. } // namespace traits
  885. #endif // !defined(GENERATING_DOCUMENTATION)
  886. } // namespace asio
  887. } // namespace boost
  888. #include <boost/asio/detail/pop_options.hpp>
  889. #endif // BOOST_ASIO_IMPL_USE_FUTURE_HPP