co_spawn.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. //
  2. // experimental/impl/co_spawn.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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_EXPERIMENTAL_IMPL_CO_SPAWN_HPP
  11. #define BOOST_ASIO_EXPERIMENTAL_IMPL_CO_SPAWN_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 <exception>
  17. #include <functional>
  18. #include <memory>
  19. #include <new>
  20. #include <tuple>
  21. #include <utility>
  22. #include <boost/asio/async_result.hpp>
  23. #include <boost/asio/detail/thread_context.hpp>
  24. #include <boost/asio/detail/thread_info_base.hpp>
  25. #include <boost/asio/detail/type_traits.hpp>
  26. #include <boost/asio/dispatch.hpp>
  27. #include <boost/asio/post.hpp>
  28. #include <boost/asio/detail/push_options.hpp>
  29. namespace boost {
  30. namespace asio {
  31. namespace experimental {
  32. namespace detail {
  33. // Promise object for coroutine at top of thread-of-execution "stack".
  34. template <typename Executor>
  35. class awaiter
  36. {
  37. public:
  38. struct deleter
  39. {
  40. void operator()(awaiter* a)
  41. {
  42. if (a)
  43. a->release();
  44. }
  45. };
  46. typedef std::unique_ptr<awaiter, deleter> ptr;
  47. typedef Executor executor_type;
  48. ~awaiter()
  49. {
  50. if (has_executor_)
  51. static_cast<Executor*>(static_cast<void*>(executor_))->~Executor();
  52. }
  53. void set_executor(const Executor& ex)
  54. {
  55. new (&executor_) Executor(ex);
  56. has_executor_ = true;
  57. }
  58. executor_type get_executor() const noexcept
  59. {
  60. return *static_cast<const Executor*>(static_cast<const void*>(executor_));
  61. }
  62. awaiter* get_return_object()
  63. {
  64. return this;
  65. }
  66. auto initial_suspend()
  67. {
  68. return std::experimental::suspend_always();
  69. }
  70. auto final_suspend()
  71. {
  72. return std::experimental::suspend_always();
  73. }
  74. void return_void()
  75. {
  76. }
  77. awaiter* add_ref()
  78. {
  79. ++ref_count_;
  80. return this;
  81. }
  82. void release()
  83. {
  84. if (--ref_count_ == 0)
  85. coroutine_handle<awaiter>::from_promise(*this).destroy();
  86. }
  87. void unhandled_exception()
  88. {
  89. pending_exception_ = std::current_exception();
  90. }
  91. void rethrow_unhandled_exception()
  92. {
  93. if (pending_exception_)
  94. {
  95. std::exception_ptr ex = std::exchange(pending_exception_, nullptr);
  96. std::rethrow_exception(ex);
  97. }
  98. }
  99. private:
  100. std::size_t ref_count_ = 0;
  101. std::exception_ptr pending_exception_ = nullptr;
  102. alignas(Executor) unsigned char executor_[sizeof(Executor)];
  103. bool has_executor_ = false;
  104. };
  105. // Base promise for coroutines further down the thread-of-execution "stack".
  106. template <typename Executor>
  107. class awaitee_base
  108. {
  109. public:
  110. #if !defined(BOOST_ASIO_DISABLE_AWAITEE_RECYCLING)
  111. void* operator new(std::size_t size)
  112. {
  113. return boost::asio::detail::thread_info_base::allocate(
  114. boost::asio::detail::thread_info_base::awaitee_tag(),
  115. boost::asio::detail::thread_context::thread_call_stack::top(),
  116. size);
  117. }
  118. void operator delete(void* pointer, std::size_t size)
  119. {
  120. boost::asio::detail::thread_info_base::deallocate(
  121. boost::asio::detail::thread_info_base::awaitee_tag(),
  122. boost::asio::detail::thread_context::thread_call_stack::top(),
  123. pointer, size);
  124. }
  125. #endif // !defined(BOOST_ASIO_DISABLE_AWAITEE_RECYCLING)
  126. auto initial_suspend()
  127. {
  128. return std::experimental::suspend_never();
  129. }
  130. struct final_suspender
  131. {
  132. awaitee_base* this_;
  133. bool await_ready() const noexcept
  134. {
  135. return false;
  136. }
  137. void await_suspend(coroutine_handle<void>)
  138. {
  139. this_->wake_caller();
  140. }
  141. void await_resume() const noexcept
  142. {
  143. }
  144. };
  145. auto final_suspend()
  146. {
  147. return final_suspender{this};
  148. }
  149. void set_except(std::exception_ptr e)
  150. {
  151. pending_exception_ = e;
  152. }
  153. void unhandled_exception()
  154. {
  155. set_except(std::current_exception());
  156. }
  157. void rethrow_exception()
  158. {
  159. if (pending_exception_)
  160. {
  161. std::exception_ptr ex = std::exchange(pending_exception_, nullptr);
  162. std::rethrow_exception(ex);
  163. }
  164. }
  165. awaiter<Executor>* top()
  166. {
  167. return awaiter_;
  168. }
  169. coroutine_handle<void> caller()
  170. {
  171. return caller_;
  172. }
  173. bool ready() const
  174. {
  175. return ready_;
  176. }
  177. void wake_caller()
  178. {
  179. if (caller_)
  180. caller_.resume();
  181. else
  182. ready_ = true;
  183. }
  184. class awaitable_executor
  185. {
  186. public:
  187. explicit awaitable_executor(awaitee_base* a)
  188. : this_(a)
  189. {
  190. }
  191. bool await_ready() const noexcept
  192. {
  193. return this_->awaiter_ != nullptr;
  194. }
  195. template <typename U, typename Ex>
  196. void await_suspend(coroutine_handle<detail::awaitee<U, Ex>> h) noexcept
  197. {
  198. this_->resume_on_attach_ = h;
  199. }
  200. Executor await_resume()
  201. {
  202. return this_->awaiter_->get_executor();
  203. }
  204. private:
  205. awaitee_base* this_;
  206. };
  207. awaitable_executor await_transform(this_coro::executor_t) noexcept
  208. {
  209. return awaitable_executor(this);
  210. }
  211. class awaitable_token
  212. {
  213. public:
  214. explicit awaitable_token(awaitee_base* a)
  215. : this_(a)
  216. {
  217. }
  218. bool await_ready() const noexcept
  219. {
  220. return this_->awaiter_ != nullptr;
  221. }
  222. template <typename U, typename Ex>
  223. void await_suspend(coroutine_handle<detail::awaitee<U, Ex>> h) noexcept
  224. {
  225. this_->resume_on_attach_ = h;
  226. }
  227. await_token<Executor> await_resume()
  228. {
  229. return await_token<Executor>(this_->awaiter_);
  230. }
  231. private:
  232. awaitee_base* this_;
  233. };
  234. awaitable_token await_transform(this_coro::token_t) noexcept
  235. {
  236. return awaitable_token(this);
  237. }
  238. template <typename T>
  239. awaitable<T, Executor> await_transform(awaitable<T, Executor>& t) const
  240. {
  241. return std::move(t);
  242. }
  243. template <typename T>
  244. awaitable<T, Executor> await_transform(awaitable<T, Executor>&& t) const
  245. {
  246. return std::move(t);
  247. }
  248. std::experimental::suspend_always await_transform(
  249. std::experimental::suspend_always) const
  250. {
  251. return std::experimental::suspend_always();
  252. }
  253. void attach_caller(coroutine_handle<awaiter<Executor>> h)
  254. {
  255. this->caller_ = h;
  256. this->attach_callees(&h.promise());
  257. }
  258. template <typename U>
  259. void attach_caller(coroutine_handle<awaitee<U, Executor>> h)
  260. {
  261. this->caller_ = h;
  262. if (h.promise().awaiter_)
  263. this->attach_callees(h.promise().awaiter_);
  264. else
  265. h.promise().unattached_callee_ = this;
  266. }
  267. void attach_callees(awaiter<Executor>* a)
  268. {
  269. for (awaitee_base* curr = this; curr != nullptr;
  270. curr = std::exchange(curr->unattached_callee_, nullptr))
  271. {
  272. curr->awaiter_ = a;
  273. if (curr->resume_on_attach_)
  274. return std::exchange(curr->resume_on_attach_, nullptr).resume();
  275. }
  276. }
  277. protected:
  278. awaiter<Executor>* awaiter_ = nullptr;
  279. coroutine_handle<void> caller_ = nullptr;
  280. awaitee_base<Executor>* unattached_callee_ = nullptr;
  281. std::exception_ptr pending_exception_ = nullptr;
  282. coroutine_handle<void> resume_on_attach_ = nullptr;
  283. bool ready_ = false;
  284. };
  285. // Promise object for coroutines further down the thread-of-execution "stack".
  286. template <typename T, typename Executor>
  287. class awaitee
  288. : public awaitee_base<Executor>
  289. {
  290. public:
  291. awaitee()
  292. {
  293. }
  294. awaitee(awaitee&& other) noexcept
  295. : awaitee_base<Executor>(std::move(other))
  296. {
  297. }
  298. ~awaitee()
  299. {
  300. if (has_result_)
  301. static_cast<T*>(static_cast<void*>(result_))->~T();
  302. }
  303. awaitable<T, Executor> get_return_object()
  304. {
  305. return awaitable<T, Executor>(this);
  306. };
  307. template <typename U>
  308. void return_value(U&& u)
  309. {
  310. new (&result_) T(std::forward<U>(u));
  311. has_result_ = true;
  312. }
  313. T get()
  314. {
  315. this->caller_ = nullptr;
  316. this->rethrow_exception();
  317. return std::move(*static_cast<T*>(static_cast<void*>(result_)));
  318. }
  319. private:
  320. alignas(T) unsigned char result_[sizeof(T)];
  321. bool has_result_ = false;
  322. };
  323. // Promise object for coroutines further down the thread-of-execution "stack".
  324. template <typename Executor>
  325. class awaitee<void, Executor>
  326. : public awaitee_base<Executor>
  327. {
  328. public:
  329. awaitable<void, Executor> get_return_object()
  330. {
  331. return awaitable<void, Executor>(this);
  332. };
  333. void return_void()
  334. {
  335. }
  336. void get()
  337. {
  338. this->caller_ = nullptr;
  339. this->rethrow_exception();
  340. }
  341. };
  342. template <typename Executor>
  343. class awaiter_task
  344. {
  345. public:
  346. typedef Executor executor_type;
  347. awaiter_task(awaiter<Executor>* a)
  348. : awaiter_(a->add_ref())
  349. {
  350. }
  351. awaiter_task(awaiter_task&& other) noexcept
  352. : awaiter_(std::exchange(other.awaiter_, nullptr))
  353. {
  354. }
  355. ~awaiter_task()
  356. {
  357. if (awaiter_)
  358. {
  359. // Coroutine "stack unwinding" must be performed through the executor.
  360. executor_type ex(awaiter_->get_executor());
  361. (post)(ex,
  362. [a = std::move(awaiter_)]() mutable
  363. {
  364. typename awaiter<Executor>::ptr(std::move(a));
  365. });
  366. }
  367. }
  368. executor_type get_executor() const noexcept
  369. {
  370. return awaiter_->get_executor();
  371. }
  372. protected:
  373. typename awaiter<Executor>::ptr awaiter_;
  374. };
  375. template <typename Executor>
  376. class co_spawn_handler : public awaiter_task<Executor>
  377. {
  378. public:
  379. using awaiter_task<Executor>::awaiter_task;
  380. void operator()()
  381. {
  382. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  383. coroutine_handle<awaiter<Executor>>::from_promise(*ptr.get()).resume();
  384. }
  385. };
  386. template <typename Executor, typename T>
  387. class await_handler_base : public awaiter_task<Executor>
  388. {
  389. public:
  390. typedef awaitable<T, Executor> awaitable_type;
  391. await_handler_base(await_token<Executor> token)
  392. : awaiter_task<Executor>(token.awaiter_),
  393. awaitee_(nullptr)
  394. {
  395. }
  396. await_handler_base(await_handler_base&& other) noexcept
  397. : awaiter_task<Executor>(std::move(other)),
  398. awaitee_(std::exchange(other.awaitee_, nullptr))
  399. {
  400. }
  401. void attach_awaitee(const awaitable<T, Executor>& a)
  402. {
  403. awaitee_ = a.awaitee_;
  404. }
  405. protected:
  406. awaitee<T, Executor>* awaitee_;
  407. };
  408. template <typename, typename...> class await_handler;
  409. template <typename Executor>
  410. class await_handler<Executor, void>
  411. : public await_handler_base<Executor, void>
  412. {
  413. public:
  414. using await_handler_base<Executor, void>::await_handler_base;
  415. void operator()()
  416. {
  417. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  418. this->awaitee_->return_void();
  419. this->awaitee_->wake_caller();
  420. ptr->rethrow_unhandled_exception();
  421. }
  422. };
  423. template <typename Executor>
  424. class await_handler<Executor, boost::system::error_code>
  425. : public await_handler_base<Executor, void>
  426. {
  427. public:
  428. typedef void return_type;
  429. using await_handler_base<Executor, void>::await_handler_base;
  430. void operator()(const boost::system::error_code& ec)
  431. {
  432. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  433. if (ec)
  434. {
  435. this->awaitee_->set_except(
  436. std::make_exception_ptr(boost::system::system_error(ec)));
  437. }
  438. else
  439. this->awaitee_->return_void();
  440. this->awaitee_->wake_caller();
  441. ptr->rethrow_unhandled_exception();
  442. }
  443. };
  444. template <typename Executor>
  445. class await_handler<Executor, std::exception_ptr>
  446. : public await_handler_base<Executor, void>
  447. {
  448. public:
  449. using await_handler_base<Executor, void>::await_handler_base;
  450. void operator()(std::exception_ptr ex)
  451. {
  452. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  453. if (ex)
  454. this->awaitee_->set_except(ex);
  455. else
  456. this->awaitee_->return_void();
  457. this->awaitee_->wake_caller();
  458. ptr->rethrow_unhandled_exception();
  459. }
  460. };
  461. template <typename Executor, typename T>
  462. class await_handler<Executor, T>
  463. : public await_handler_base<Executor, T>
  464. {
  465. public:
  466. using await_handler_base<Executor, T>::await_handler_base;
  467. template <typename Arg>
  468. void operator()(Arg&& arg)
  469. {
  470. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  471. this->awaitee_->return_value(std::forward<Arg>(arg));
  472. this->awaitee_->wake_caller();
  473. ptr->rethrow_unhandled_exception();
  474. }
  475. };
  476. template <typename Executor, typename T>
  477. class await_handler<Executor, boost::system::error_code, T>
  478. : public await_handler_base<Executor, T>
  479. {
  480. public:
  481. using await_handler_base<Executor, T>::await_handler_base;
  482. template <typename Arg>
  483. void operator()(const boost::system::error_code& ec, Arg&& arg)
  484. {
  485. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  486. if (ec)
  487. {
  488. this->awaitee_->set_except(
  489. std::make_exception_ptr(boost::system::system_error(ec)));
  490. }
  491. else
  492. this->awaitee_->return_value(std::forward<Arg>(arg));
  493. this->awaitee_->wake_caller();
  494. ptr->rethrow_unhandled_exception();
  495. }
  496. };
  497. template <typename Executor, typename T>
  498. class await_handler<Executor, std::exception_ptr, T>
  499. : public await_handler_base<Executor, T>
  500. {
  501. public:
  502. using await_handler_base<Executor, T>::await_handler_base;
  503. template <typename Arg>
  504. void operator()(std::exception_ptr ex, Arg&& arg)
  505. {
  506. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  507. if (ex)
  508. this->awaitee_->set_except(ex);
  509. else
  510. this->awaitee_->return_value(std::forward<Arg>(arg));
  511. this->awaitee_->wake_caller();
  512. ptr->rethrow_unhandled_exception();
  513. }
  514. };
  515. template <typename Executor, typename... Ts>
  516. class await_handler
  517. : public await_handler_base<Executor, std::tuple<Ts...>>
  518. {
  519. public:
  520. using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base;
  521. template <typename... Args>
  522. void operator()(Args&&... args)
  523. {
  524. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  525. this->awaitee_->return_value(
  526. std::forward_as_tuple(std::forward<Args>(args)...));
  527. this->awaitee_->wake_caller();
  528. ptr->rethrow_unhandled_exception();
  529. }
  530. };
  531. template <typename Executor, typename... Ts>
  532. class await_handler<Executor, boost::system::error_code, Ts...>
  533. : public await_handler_base<Executor, std::tuple<Ts...>>
  534. {
  535. public:
  536. using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base;
  537. template <typename... Args>
  538. void operator()(const boost::system::error_code& ec, Args&&... args)
  539. {
  540. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  541. if (ec)
  542. {
  543. this->awaitee_->set_except(
  544. std::make_exception_ptr(boost::system::system_error(ec)));
  545. }
  546. else
  547. {
  548. this->awaitee_->return_value(
  549. std::forward_as_tuple(std::forward<Args>(args)...));
  550. }
  551. this->awaitee_->wake_caller();
  552. ptr->rethrow_unhandled_exception();
  553. }
  554. };
  555. template <typename Executor, typename... Ts>
  556. class await_handler<Executor, std::exception_ptr, Ts...>
  557. : public await_handler_base<Executor, std::tuple<Ts...>>
  558. {
  559. public:
  560. using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base;
  561. template <typename... Args>
  562. void operator()(std::exception_ptr ex, Args&&... args)
  563. {
  564. typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
  565. if (ex)
  566. this->awaitee_->set_except(ex);
  567. else
  568. {
  569. this->awaitee_->return_value(
  570. std::forward_as_tuple(std::forward<Args>(args)...));
  571. }
  572. this->awaitee_->wake_caller();
  573. ptr->rethrow_unhandled_exception();
  574. }
  575. };
  576. template <typename T>
  577. struct awaitable_signature;
  578. template <typename T, typename Executor>
  579. struct awaitable_signature<awaitable<T, Executor>>
  580. {
  581. typedef void type(std::exception_ptr, T);
  582. };
  583. template <typename Executor>
  584. struct awaitable_signature<awaitable<void, Executor>>
  585. {
  586. typedef void type(std::exception_ptr);
  587. };
  588. template <typename T, typename Executor, typename F, typename Handler>
  589. awaiter<Executor>* co_spawn_entry_point(awaitable<T, Executor>*,
  590. executor_work_guard<Executor> work_guard, F f, Handler handler)
  591. {
  592. bool done = false;
  593. try
  594. {
  595. T t = co_await f();
  596. done = true;
  597. (dispatch)(work_guard.get_executor(),
  598. [handler = std::move(handler), t = std::move(t)]() mutable
  599. {
  600. handler(std::exception_ptr(), std::move(t));
  601. });
  602. }
  603. catch (...)
  604. {
  605. if (done)
  606. throw;
  607. (dispatch)(work_guard.get_executor(),
  608. [handler = std::move(handler), e = std::current_exception()]() mutable
  609. {
  610. handler(e, T());
  611. });
  612. }
  613. }
  614. template <typename Executor, typename F, typename Handler>
  615. awaiter<Executor>* co_spawn_entry_point(awaitable<void, Executor>*,
  616. executor_work_guard<Executor> work_guard, F f, Handler handler)
  617. {
  618. std::exception_ptr e = nullptr;
  619. try
  620. {
  621. co_await f();
  622. }
  623. catch (...)
  624. {
  625. e = std::current_exception();
  626. }
  627. (dispatch)(work_guard.get_executor(),
  628. [handler = std::move(handler), e]() mutable
  629. {
  630. handler(e);
  631. });
  632. }
  633. template <typename Executor, typename F, typename CompletionToken>
  634. auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token)
  635. {
  636. typedef typename result_of<F()>::type awaitable_type;
  637. typedef typename awaitable_type::executor_type executor_type;
  638. typedef typename awaitable_signature<awaitable_type>::type signature_type;
  639. async_completion<CompletionToken, signature_type> completion(token);
  640. executor_type ex2(ex);
  641. auto work_guard = make_work_guard(completion.completion_handler, ex2);
  642. auto* a = (co_spawn_entry_point)(
  643. static_cast<awaitable_type*>(nullptr), std::move(work_guard),
  644. std::forward<F>(f), std::move(completion.completion_handler));
  645. a->set_executor(ex2);
  646. (post)(co_spawn_handler<executor_type>(a));
  647. return completion.result.get();
  648. }
  649. #if defined(_MSC_VER)
  650. # pragma warning(push)
  651. # pragma warning(disable:4033)
  652. #endif // defined(_MSC_VER)
  653. #if defined(_MSC_VER)
  654. template <typename T> T dummy_return()
  655. {
  656. return std::move(*static_cast<T*>(nullptr));
  657. }
  658. template <>
  659. inline void dummy_return()
  660. {
  661. }
  662. #endif // defined(_MSC_VER)
  663. template <typename Awaitable>
  664. inline Awaitable make_dummy_awaitable()
  665. {
  666. for (;;) co_await std::experimental::suspend_always();
  667. #if defined(_MSC_VER)
  668. co_return dummy_return<typename Awaitable::value_type>();
  669. #endif // defined(_MSC_VER)
  670. }
  671. #if defined(_MSC_VER)
  672. # pragma warning(pop)
  673. #endif // defined(_MSC_VER)
  674. } // namespace detail
  675. } // namespace experimental
  676. template <typename Executor, typename R, typename... Args>
  677. class async_result<experimental::await_token<Executor>, R(Args...)>
  678. {
  679. public:
  680. typedef experimental::detail::await_handler<
  681. Executor, typename decay<Args>::type...> completion_handler_type;
  682. typedef typename experimental::detail::await_handler<
  683. Executor, Args...>::awaitable_type return_type;
  684. async_result(completion_handler_type& h)
  685. : awaitable_(experimental::detail::make_dummy_awaitable<return_type>())
  686. {
  687. h.attach_awaitee(awaitable_);
  688. }
  689. return_type get()
  690. {
  691. return std::move(awaitable_);
  692. }
  693. private:
  694. return_type awaitable_;
  695. };
  696. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  697. template <typename Executor, typename R, typename... Args>
  698. struct handler_type<experimental::await_token<Executor>, R(Args...)>
  699. {
  700. typedef experimental::detail::await_handler<
  701. Executor, typename decay<Args>::type...> type;
  702. };
  703. template <typename Executor, typename... Args>
  704. class async_result<experimental::detail::await_handler<Executor, Args...>>
  705. {
  706. public:
  707. typedef typename experimental::detail::await_handler<
  708. Executor, Args...>::awaitable_type type;
  709. async_result(experimental::detail::await_handler<Executor, Args...>& h)
  710. : awaitable_(experimental::detail::make_dummy_awaitable<type>())
  711. {
  712. h.attach_awaitee(awaitable_);
  713. }
  714. type get()
  715. {
  716. return std::move(awaitable_);
  717. }
  718. private:
  719. type awaitable_;
  720. };
  721. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  722. } // namespace asio
  723. } // namespace boost
  724. namespace std { namespace experimental {
  725. template <typename Executor, typename... Args>
  726. struct coroutine_traits<
  727. boost::asio::experimental::detail::awaiter<Executor>*, Args...>
  728. {
  729. typedef boost::asio::experimental::detail::awaiter<Executor> promise_type;
  730. };
  731. template <typename T, typename Executor, typename... Args>
  732. struct coroutine_traits<
  733. boost::asio::experimental::awaitable<T, Executor>, Args...>
  734. {
  735. typedef boost::asio::experimental::detail::awaitee<T, Executor> promise_type;
  736. };
  737. }} // namespace std::experimental
  738. #include <boost/asio/detail/pop_options.hpp>
  739. #endif // BOOST_ASIO_EXPERIMENTAL_IMPL_CO_SPAWN_HPP