Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright (c) 2024 Klemens Morgenstern (klemens.morgenstern@gmx.net)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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       // destroy the lifetime.
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 //BOOST_COBALT_EXPERIMENTAL_YIELD_CONTEXT_HPP