Warning, file /include/boost/cobalt/experimental/yield_context.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_COBALT_EXPERIMENTAL_YIELD_CONTEXT_HPP
0009 #define BOOST_COBALT_EXPERIMENTAL_YIELD_CONTEXT_HPP
0010
0011 #include <boost/cobalt/experimental/frame.hpp>
0012 #include <boost/cobalt/concepts.hpp>
0013
0014 #include <boost/asio/spawn.hpp>
0015 #include <coroutine>
0016
0017 template<typename Executor>
0018 struct std::coroutine_handle<boost::asio::basic_yield_context<Executor>>
0019 {
0020 constexpr operator coroutine_handle<>() const noexcept { return coroutine_handle<>::from_address(address()); }
0021
0022 constexpr explicit operator bool() const noexcept { return true; }
0023
0024 constexpr bool done() const noexcept { return false; }
0025 void operator()() const noexcept {}
0026
0027 void resume() const noexcept {frame_->promiseresume();}
0028 void destroy() const noexcept {frame_->destroy();}
0029
0030 boost::asio::basic_yield_context<Executor> & promise() const noexcept { return frame_->promise; }
0031
0032 constexpr void* address() const noexcept { return frame_; }
0033
0034 struct yield_context_frame :
0035 boost::cobalt::experimental::frame<yield_context_frame, boost::asio::basic_yield_context<Executor>>
0036 {
0037 using boost::cobalt::experimental::frame<yield_context_frame, boost::asio::basic_yield_context<Executor>>::frame;
0038 void resume()
0039 {
0040 lifetime.resume();
0041 }
0042 void destroy()
0043 {
0044
0045 auto lf = std::move(lifetime);
0046 }
0047
0048 boost::asio::detail::spawn_handler_base<Executor> lifetime{this->promise};
0049 };
0050
0051 coroutine_handle(yield_context_frame & frame) : frame_(&frame) {}
0052 private:
0053 yield_context_frame * frame_;
0054 };
0055
0056 namespace boost::cobalt::experimental
0057 {
0058
0059 template<awaitable_type Aw, typename Executor>
0060 auto await(Aw && aw, boost::asio::basic_yield_context<Executor> ctx)
0061 {
0062 if (!std::forward<Aw>(aw).await_ready())
0063 {
0064
0065 using ch = std::coroutine_handle<boost::asio::basic_yield_context<Executor>>;
0066 typename ch::yield_context_frame fr{std::move(ctx)};
0067 ch h{fr};
0068 ctx.spawned_thread_->suspend_with(
0069 [&]
0070 {
0071 using rt = decltype(std::forward<Aw>(aw).await_suspend(h));
0072 if constexpr (std::is_void_v<rt>)
0073 std::forward<Aw>(aw).await_suspend(h);
0074 else if constexpr (std::is_same_v<rt, bool>)
0075 {
0076 if (!std::forward<Aw>(aw).await_suspend(h))
0077 ctx.spawned_thread_->resume();
0078 }
0079 else
0080 std::forward<Aw>(aw).await_suspend(h).resume();
0081 }
0082 );
0083
0084 }
0085 return std::forward<Aw>(aw).await_resume();
0086
0087 }
0088
0089 template<typename Aw, typename Executor>
0090 requires requires (Aw && aw) {{std::forward<Aw>(aw).operator co_await()} -> awaitable_type; }
0091 auto await(Aw && aw, boost::asio::basic_yield_context<Executor> ctx)
0092 {
0093 return await(std::forward<Aw>(aw).operator co_await(), std::move(ctx));
0094 }
0095
0096 template<typename Aw, typename Executor>
0097 requires requires (Aw && aw) {{operator co_await(std::forward<Aw>(aw))} -> awaitable_type; }
0098 auto await(Aw && aw, boost::asio::basic_yield_context<Executor> ctx)
0099 {
0100 return await(operator co_await(std::forward<Aw>(aw)), std::move(ctx));
0101 }
0102
0103 }
0104
0105
0106 #endif