use_future.hpp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. //
  2. // impl/use_future.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef 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. execution_context& query(execution::context_t) const BOOST_ASIO_NOEXCEPT
  194. {
  195. return boost::asio::query(system_executor(), execution::context);
  196. }
  197. static BOOST_ASIO_CONSTEXPR Blocking query(execution::blocking_t)
  198. {
  199. return Blocking();
  200. }
  201. promise_executor<T, execution::blocking_t::possibly_t>
  202. require(execution::blocking_t::possibly_t) const
  203. {
  204. return promise_executor<T, execution::blocking_t::possibly_t>(p_);
  205. }
  206. promise_executor<T, execution::blocking_t::never_t>
  207. require(execution::blocking_t::never_t) const
  208. {
  209. return promise_executor<T, execution::blocking_t::never_t>(p_);
  210. }
  211. template <typename F>
  212. void execute(BOOST_ASIO_MOVE_ARG(F) f) const
  213. {
  214. #if defined(BOOST_ASIO_NO_DEPRECATED)
  215. boost::asio::require(system_executor(), Blocking()).execute(
  216. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
  217. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  218. execution::execute(
  219. boost::asio::require(system_executor(), Blocking()),
  220. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
  221. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  222. }
  223. #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  224. execution_context& context() const BOOST_ASIO_NOEXCEPT
  225. {
  226. return system_executor().context();
  227. }
  228. void on_work_started() const BOOST_ASIO_NOEXCEPT {}
  229. void on_work_finished() const BOOST_ASIO_NOEXCEPT {}
  230. template <typename F, typename A>
  231. void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A&) const
  232. {
  233. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f))();
  234. }
  235. template <typename F, typename A>
  236. void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  237. {
  238. system_executor().post(
  239. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
  240. }
  241. template <typename F, typename A>
  242. void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
  243. {
  244. system_executor().defer(
  245. promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
  246. }
  247. #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  248. friend bool operator==(const promise_executor& a,
  249. const promise_executor& b) BOOST_ASIO_NOEXCEPT
  250. {
  251. return a.p_ == b.p_;
  252. }
  253. friend bool operator!=(const promise_executor& a,
  254. const promise_executor& b) BOOST_ASIO_NOEXCEPT
  255. {
  256. return a.p_ != b.p_;
  257. }
  258. private:
  259. shared_ptr<std::promise<T> > p_;
  260. };
  261. // The base class for all completion handlers that create promises.
  262. template <typename T>
  263. class promise_creator
  264. {
  265. public:
  266. typedef promise_executor<T> executor_type;
  267. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  268. {
  269. return executor_type(p_);
  270. }
  271. typedef std::future<T> future_type;
  272. future_type get_future()
  273. {
  274. return p_->get_future();
  275. }
  276. protected:
  277. template <typename Allocator>
  278. void create_promise(const Allocator& a)
  279. {
  280. BOOST_ASIO_REBIND_ALLOC(Allocator, char) b(a);
  281. p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
  282. }
  283. shared_ptr<std::promise<T> > p_;
  284. };
  285. // For completion signature void().
  286. class promise_handler_0
  287. : public promise_creator<void>
  288. {
  289. public:
  290. void operator()()
  291. {
  292. this->p_->set_value();
  293. }
  294. };
  295. // For completion signature void(error_code).
  296. class promise_handler_ec_0
  297. : public promise_creator<void>
  298. {
  299. public:
  300. void operator()(const boost::system::error_code& ec)
  301. {
  302. if (ec)
  303. {
  304. this->p_->set_exception(
  305. std::make_exception_ptr(
  306. boost::system::system_error(ec)));
  307. }
  308. else
  309. {
  310. this->p_->set_value();
  311. }
  312. }
  313. };
  314. // For completion signature void(exception_ptr).
  315. class promise_handler_ex_0
  316. : public promise_creator<void>
  317. {
  318. public:
  319. void operator()(const std::exception_ptr& ex)
  320. {
  321. if (ex)
  322. {
  323. this->p_->set_exception(ex);
  324. }
  325. else
  326. {
  327. this->p_->set_value();
  328. }
  329. }
  330. };
  331. // For completion signature void(T).
  332. template <typename T>
  333. class promise_handler_1
  334. : public promise_creator<T>
  335. {
  336. public:
  337. template <typename Arg>
  338. void operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
  339. {
  340. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  341. }
  342. };
  343. // For completion signature void(error_code, T).
  344. template <typename T>
  345. class promise_handler_ec_1
  346. : public promise_creator<T>
  347. {
  348. public:
  349. template <typename Arg>
  350. void operator()(const boost::system::error_code& ec,
  351. BOOST_ASIO_MOVE_ARG(Arg) arg)
  352. {
  353. if (ec)
  354. {
  355. this->p_->set_exception(
  356. std::make_exception_ptr(
  357. boost::system::system_error(ec)));
  358. }
  359. else
  360. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  361. }
  362. };
  363. // For completion signature void(exception_ptr, T).
  364. template <typename T>
  365. class promise_handler_ex_1
  366. : public promise_creator<T>
  367. {
  368. public:
  369. template <typename Arg>
  370. void operator()(const std::exception_ptr& ex,
  371. BOOST_ASIO_MOVE_ARG(Arg) arg)
  372. {
  373. if (ex)
  374. this->p_->set_exception(ex);
  375. else
  376. this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
  377. }
  378. };
  379. // For completion signature void(T1, ..., Tn);
  380. template <typename T>
  381. class promise_handler_n
  382. : public promise_creator<T>
  383. {
  384. public:
  385. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  386. template <typename... Args>
  387. void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
  388. {
  389. this->p_->set_value(
  390. std::forward_as_tuple(
  391. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  392. }
  393. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  394. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  395. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  396. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  397. {\
  398. this->p_->set_value( \
  399. std::forward_as_tuple( \
  400. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  401. } \
  402. /**/
  403. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  404. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  405. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  406. };
  407. // For completion signature void(error_code, T1, ..., Tn);
  408. template <typename T>
  409. class promise_handler_ec_n
  410. : public promise_creator<T>
  411. {
  412. public:
  413. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  414. template <typename... Args>
  415. void operator()(const boost::system::error_code& ec,
  416. BOOST_ASIO_MOVE_ARG(Args)... args)
  417. {
  418. if (ec)
  419. {
  420. this->p_->set_exception(
  421. std::make_exception_ptr(
  422. boost::system::system_error(ec)));
  423. }
  424. else
  425. {
  426. this->p_->set_value(
  427. std::forward_as_tuple(
  428. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  429. }
  430. }
  431. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  432. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  433. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  434. void operator()(const boost::system::error_code& ec, \
  435. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  436. {\
  437. if (ec) \
  438. { \
  439. this->p_->set_exception( \
  440. std::make_exception_ptr( \
  441. boost::system::system_error(ec))); \
  442. } \
  443. else \
  444. { \
  445. this->p_->set_value( \
  446. std::forward_as_tuple( \
  447. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  448. } \
  449. } \
  450. /**/
  451. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  452. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  453. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  454. };
  455. // For completion signature void(exception_ptr, T1, ..., Tn);
  456. template <typename T>
  457. class promise_handler_ex_n
  458. : public promise_creator<T>
  459. {
  460. public:
  461. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  462. template <typename... Args>
  463. void operator()(const std::exception_ptr& ex,
  464. BOOST_ASIO_MOVE_ARG(Args)... args)
  465. {
  466. if (ex)
  467. this->p_->set_exception(ex);
  468. else
  469. {
  470. this->p_->set_value(
  471. std::forward_as_tuple(
  472. BOOST_ASIO_MOVE_CAST(Args)(args)...));
  473. }
  474. }
  475. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  476. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  477. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  478. void operator()(const std::exception_ptr& ex, \
  479. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  480. {\
  481. if (ex) \
  482. this->p_->set_exception(ex); \
  483. else \
  484. { \
  485. this->p_->set_value( \
  486. std::forward_as_tuple( \
  487. BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
  488. } \
  489. } \
  490. /**/
  491. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  492. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  493. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  494. };
  495. // Helper template to choose the appropriate concrete promise handler
  496. // implementation based on the supplied completion signature.
  497. template <typename> class promise_handler_selector;
  498. template <>
  499. class promise_handler_selector<void()>
  500. : public promise_handler_0 {};
  501. template <>
  502. class promise_handler_selector<void(boost::system::error_code)>
  503. : public promise_handler_ec_0 {};
  504. template <>
  505. class promise_handler_selector<void(std::exception_ptr)>
  506. : public promise_handler_ex_0 {};
  507. template <typename Arg>
  508. class promise_handler_selector<void(Arg)>
  509. : public promise_handler_1<Arg> {};
  510. template <typename Arg>
  511. class promise_handler_selector<void(boost::system::error_code, Arg)>
  512. : public promise_handler_ec_1<Arg> {};
  513. template <typename Arg>
  514. class promise_handler_selector<void(std::exception_ptr, Arg)>
  515. : public promise_handler_ex_1<Arg> {};
  516. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  517. template <typename... Arg>
  518. class promise_handler_selector<void(Arg...)>
  519. : public promise_handler_n<std::tuple<Arg...> > {};
  520. template <typename... Arg>
  521. class promise_handler_selector<void(boost::system::error_code, Arg...)>
  522. : public promise_handler_ec_n<std::tuple<Arg...> > {};
  523. template <typename... Arg>
  524. class promise_handler_selector<void(std::exception_ptr, Arg...)>
  525. : public promise_handler_ex_n<std::tuple<Arg...> > {};
  526. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  527. #define BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
  528. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  529. class promise_handler_selector< \
  530. void(Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  531. : public promise_handler_n< \
  532. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  533. \
  534. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  535. class promise_handler_selector< \
  536. void(boost::system::error_code, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  537. : public promise_handler_ec_n< \
  538. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  539. \
  540. template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  541. class promise_handler_selector< \
  542. void(std::exception_ptr, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
  543. : public promise_handler_ex_n< \
  544. std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
  545. /**/
  546. BOOST_ASIO_VARIADIC_GENERATE_5(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
  547. #undef BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF
  548. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  549. // Completion handlers produced from the use_future completion token, when not
  550. // using use_future::operator().
  551. template <typename Signature, typename Allocator>
  552. class promise_handler
  553. : public promise_handler_selector<Signature>
  554. {
  555. public:
  556. typedef Allocator allocator_type;
  557. typedef void result_type;
  558. promise_handler(use_future_t<Allocator> u)
  559. : allocator_(u.get_allocator())
  560. {
  561. this->create_promise(allocator_);
  562. }
  563. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  564. {
  565. return allocator_;
  566. }
  567. private:
  568. Allocator allocator_;
  569. };
  570. template <typename Function>
  571. struct promise_function_wrapper
  572. {
  573. explicit promise_function_wrapper(Function& f)
  574. : function_(BOOST_ASIO_MOVE_CAST(Function)(f))
  575. {
  576. }
  577. explicit promise_function_wrapper(const Function& f)
  578. : function_(f)
  579. {
  580. }
  581. void operator()()
  582. {
  583. function_();
  584. }
  585. Function function_;
  586. };
  587. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  588. template <typename Function, typename Signature, typename Allocator>
  589. inline void asio_handler_invoke(Function& f,
  590. promise_handler<Signature, Allocator>* h)
  591. {
  592. typename promise_handler<Signature, Allocator>::executor_type
  593. ex(h->get_executor());
  594. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  595. }
  596. template <typename Function, typename Signature, typename Allocator>
  597. inline void asio_handler_invoke(const Function& f,
  598. promise_handler<Signature, Allocator>* h)
  599. {
  600. typename promise_handler<Signature, Allocator>::executor_type
  601. ex(h->get_executor());
  602. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  603. }
  604. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  605. // Helper base class for async_result specialisation.
  606. template <typename Signature, typename Allocator>
  607. class promise_async_result
  608. {
  609. public:
  610. typedef promise_handler<Signature, Allocator> completion_handler_type;
  611. typedef typename completion_handler_type::future_type return_type;
  612. explicit promise_async_result(completion_handler_type& h)
  613. : future_(h.get_future())
  614. {
  615. }
  616. return_type get()
  617. {
  618. return BOOST_ASIO_MOVE_CAST(return_type)(future_);
  619. }
  620. private:
  621. return_type future_;
  622. };
  623. // Return value from use_future::operator().
  624. template <typename Function, typename Allocator>
  625. class packaged_token
  626. {
  627. public:
  628. packaged_token(Function f, const Allocator& a)
  629. : function_(BOOST_ASIO_MOVE_CAST(Function)(f)),
  630. allocator_(a)
  631. {
  632. }
  633. //private:
  634. Function function_;
  635. Allocator allocator_;
  636. };
  637. // Completion handlers produced from the use_future completion token, when
  638. // using use_future::operator().
  639. template <typename Function, typename Allocator, typename Result>
  640. class packaged_handler
  641. : public promise_creator<Result>
  642. {
  643. public:
  644. typedef Allocator allocator_type;
  645. typedef void result_type;
  646. packaged_handler(packaged_token<Function, Allocator> t)
  647. : function_(BOOST_ASIO_MOVE_CAST(Function)(t.function_)),
  648. allocator_(t.allocator_)
  649. {
  650. this->create_promise(allocator_);
  651. }
  652. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  653. {
  654. return allocator_;
  655. }
  656. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  657. template <typename... Args>
  658. void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
  659. {
  660. (promise_invoke_and_set)(*this->p_,
  661. function_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
  662. }
  663. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  664. void operator()()
  665. {
  666. (promise_invoke_and_set)(*this->p_, function_);
  667. }
  668. #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
  669. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  670. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  671. {\
  672. (promise_invoke_and_set)(*this->p_, \
  673. function_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  674. } \
  675. /**/
  676. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
  677. #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
  678. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  679. private:
  680. Function function_;
  681. Allocator allocator_;
  682. };
  683. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  684. template <typename Function,
  685. typename Function1, typename Allocator, typename Result>
  686. inline void asio_handler_invoke(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. template <typename Function,
  694. typename Function1, typename Allocator, typename Result>
  695. inline void asio_handler_invoke(const Function& f,
  696. packaged_handler<Function1, Allocator, Result>* h)
  697. {
  698. typename packaged_handler<Function1, Allocator, Result>::executor_type
  699. ex(h->get_executor());
  700. boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
  701. }
  702. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  703. // Helper base class for async_result specialisation.
  704. template <typename Function, typename Allocator, typename Result>
  705. class packaged_async_result
  706. {
  707. public:
  708. typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
  709. typedef typename completion_handler_type::future_type return_type;
  710. explicit packaged_async_result(completion_handler_type& h)
  711. : future_(h.get_future())
  712. {
  713. }
  714. return_type get()
  715. {
  716. return BOOST_ASIO_MOVE_CAST(return_type)(future_);
  717. }
  718. private:
  719. return_type future_;
  720. };
  721. } // namespace detail
  722. template <typename Allocator> template <typename Function>
  723. inline detail::packaged_token<typename decay<Function>::type, Allocator>
  724. use_future_t<Allocator>::operator()(BOOST_ASIO_MOVE_ARG(Function) f) const
  725. {
  726. return detail::packaged_token<typename decay<Function>::type, Allocator>(
  727. BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
  728. }
  729. #if !defined(GENERATING_DOCUMENTATION)
  730. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  731. template <typename Allocator, typename Result, typename... Args>
  732. class async_result<use_future_t<Allocator>, Result(Args...)>
  733. : public detail::promise_async_result<
  734. void(typename decay<Args>::type...), Allocator>
  735. {
  736. public:
  737. explicit async_result(
  738. typename detail::promise_async_result<void(typename decay<Args>::type...),
  739. Allocator>::completion_handler_type& h)
  740. : detail::promise_async_result<
  741. void(typename decay<Args>::type...), Allocator>(h)
  742. {
  743. }
  744. };
  745. template <typename Function, typename Allocator,
  746. typename Result, typename... Args>
  747. class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
  748. : public detail::packaged_async_result<Function, Allocator,
  749. typename result_of<Function(Args...)>::type>
  750. {
  751. public:
  752. explicit async_result(
  753. typename detail::packaged_async_result<Function, Allocator,
  754. typename result_of<Function(Args...)>::type>::completion_handler_type& h)
  755. : detail::packaged_async_result<Function, Allocator,
  756. typename result_of<Function(Args...)>::type>(h)
  757. {
  758. }
  759. };
  760. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  761. template <typename Allocator, typename Result>
  762. class async_result<use_future_t<Allocator>, Result()>
  763. : public detail::promise_async_result<void(), Allocator>
  764. {
  765. public:
  766. explicit async_result(
  767. typename detail::promise_async_result<
  768. void(), Allocator>::completion_handler_type& h)
  769. : detail::promise_async_result<void(), Allocator>(h)
  770. {
  771. }
  772. };
  773. template <typename Function, typename Allocator, typename Result>
  774. class async_result<detail::packaged_token<Function, Allocator>, Result()>
  775. : public detail::packaged_async_result<Function, Allocator,
  776. typename result_of<Function()>::type>
  777. {
  778. public:
  779. explicit async_result(
  780. typename detail::packaged_async_result<Function, Allocator,
  781. typename result_of<Function()>::type>::completion_handler_type& h)
  782. : detail::packaged_async_result<Function, Allocator,
  783. typename result_of<Function()>::type>(h)
  784. {
  785. }
  786. };
  787. #define BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
  788. template <typename Allocator, \
  789. typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  790. class async_result<use_future_t<Allocator>, \
  791. Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
  792. : public detail::promise_async_result< \
  793. void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator> \
  794. { \
  795. public: \
  796. explicit async_result( \
  797. typename detail::promise_async_result< \
  798. void(BOOST_ASIO_VARIADIC_DECAY(n)), \
  799. Allocator>::completion_handler_type& h) \
  800. : detail::promise_async_result< \
  801. void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator>(h) \
  802. { \
  803. } \
  804. }; \
  805. \
  806. template <typename Function, typename Allocator, \
  807. typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  808. class async_result<detail::packaged_token<Function, Allocator>, \
  809. Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
  810. : public detail::packaged_async_result<Function, Allocator, \
  811. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type> \
  812. { \
  813. public: \
  814. explicit async_result( \
  815. typename detail::packaged_async_result<Function, Allocator, \
  816. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type \
  817. >::completion_handler_type& h) \
  818. : detail::packaged_async_result<Function, Allocator, \
  819. typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type>(h) \
  820. { \
  821. } \
  822. }; \
  823. /**/
  824. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF)
  825. #undef BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF
  826. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  827. namespace traits {
  828. #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  829. template <typename T, typename Blocking>
  830. struct equality_comparable<
  831. boost::asio::detail::promise_executor<T, Blocking> >
  832. {
  833. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  834. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  835. };
  836. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  837. #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  838. template <typename T, typename Blocking, typename Function>
  839. struct execute_member<
  840. boost::asio::detail::promise_executor<T, Blocking>, Function>
  841. {
  842. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  843. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  844. typedef void result_type;
  845. };
  846. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  847. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  848. template <typename T, typename Blocking, typename Property>
  849. struct query_static_constexpr_member<
  850. boost::asio::detail::promise_executor<T, Blocking>,
  851. Property,
  852. typename boost::asio::enable_if<
  853. boost::asio::is_convertible<
  854. Property,
  855. boost::asio::execution::blocking_t
  856. >::value
  857. >::type
  858. >
  859. {
  860. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  861. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  862. typedef Blocking result_type;
  863. static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
  864. {
  865. return Blocking();
  866. }
  867. };
  868. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  869. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  870. template <typename T, typename Blocking>
  871. struct query_member<
  872. boost::asio::detail::promise_executor<T, Blocking>,
  873. execution::context_t
  874. >
  875. {
  876. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  877. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  878. typedef boost::asio::system_context& result_type;
  879. };
  880. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  881. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  882. template <typename T, typename Blocking>
  883. struct require_member<
  884. boost::asio::detail::promise_executor<T, Blocking>,
  885. execution::blocking_t::possibly_t
  886. >
  887. {
  888. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  889. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  890. typedef boost::asio::detail::promise_executor<T,
  891. execution::blocking_t::possibly_t> result_type;
  892. };
  893. template <typename T, typename Blocking>
  894. struct require_member<
  895. boost::asio::detail::promise_executor<T, Blocking>,
  896. execution::blocking_t::never_t
  897. >
  898. {
  899. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  900. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  901. typedef boost::asio::detail::promise_executor<T,
  902. execution::blocking_t::never_t> result_type;
  903. };
  904. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  905. } // namespace traits
  906. #endif // !defined(GENERATING_DOCUMENTATION)
  907. } // namespace asio
  908. } // namespace boost
  909. #include <boost/asio/detail/pop_options.hpp>
  910. #endif // BOOST_ASIO_IMPL_USE_FUTURE_HPP