Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

use_future.hpp 22KB

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