use_future.hpp 26 KB

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