Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:40:33

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef BOOST_COBALT_WRAPPER_HPP
0006 #define BOOST_COBALT_WRAPPER_HPP
0007 
0008 #include <boost/cobalt/this_coro.hpp>
0009 #include <boost/cobalt/concepts.hpp>
0010 #include <boost/cobalt/detail/util.hpp>
0011 
0012 #include <boost/asio/bind_executor.hpp>
0013 #include <boost/asio/executor.hpp>
0014 #include <boost/asio/post.hpp>
0015 #include <boost/config.hpp>
0016 
0017 #include <coroutine>
0018 #include <utility>
0019 #if BOOST_COBALT_NO_SELF_DELETE
0020 #include <boost/asio/consign.hpp>
0021 #endif
0022 namespace boost::cobalt::detail
0023 {
0024 
0025 template<typename Allocator>
0026 struct partial_promise_base
0027 {
0028     template<typename CompletionToken>
0029     void * operator new(const std::size_t size, CompletionToken & token)
0030     {
0031       // gcc: 168 40
0032       // clang: 144 40
0033       return allocate_coroutine(size, asio::get_associated_allocator(token));
0034     }
0035 
0036     template<typename Executor, typename CompletionToken>
0037     void * operator new(const std::size_t size, Executor &, CompletionToken & token)
0038     {
0039       // gcc: 120 8 16
0040       // clang: 96 8 16
0041       return allocate_coroutine(size, asio::get_associated_allocator(token));
0042     }
0043 #if defined(__cpp_sized_deallocation)
0044     void operator delete(void * raw, const std::size_t size)
0045     {
0046       deallocate_coroutine<Allocator>(raw, size);
0047     }
0048 #else
0049   void operator delete(void * raw)
0050   {
0051     deallocate_coroutine<Allocator>(raw);
0052   }
0053 
0054 #endif
0055 
0056 };
0057 
0058 template<>
0059 struct partial_promise_base<std::allocator<void>> {};
0060 
0061 
0062 template<>           struct partial_promise_base<void> {};
0063 template<typename T> struct partial_promise_base<std::allocator<T>> {};
0064 
0065 // alloc options are two: allocator or aligned storage
0066 template<typename Allocator = void>
0067 struct partial_promise : partial_promise_base<Allocator>
0068 {
0069     auto initial_suspend() noexcept
0070     {
0071         return std::suspend_always();
0072     }
0073 
0074     auto final_suspend() noexcept
0075     {
0076         return std::suspend_never();
0077     }
0078 
0079     void return_void() {}
0080 };
0081 
0082 template<typename Allocator = void>
0083 struct post_coroutine_promise : partial_promise<Allocator>
0084 {
0085     template<typename CompletionToken>
0086     auto yield_value(CompletionToken cpl)
0087     {
0088         struct awaitable_t
0089         {
0090             CompletionToken cpl;
0091             constexpr bool await_ready() noexcept { return false; }
0092             BOOST_NOINLINE
0093             auto await_suspend(std::coroutine_handle<void> h) noexcept
0094             {
0095                 auto c = std::move(cpl);
0096                 if (this_thread::has_executor())
0097                   detail::self_destroy(h, asio::get_associated_executor(c, this_thread::get_executor()));
0098                 else
0099                   detail::self_destroy(h, asio::get_associated_executor(c));
0100 
0101                 asio::post(std::move(c));
0102             }
0103 
0104             constexpr void await_resume() noexcept {}
0105         };
0106         return awaitable_t{std::move(cpl)};
0107     }
0108 
0109     std::coroutine_handle<post_coroutine_promise<Allocator>> get_return_object()
0110     {
0111         return std::coroutine_handle<post_coroutine_promise<Allocator>>::from_promise(*this);
0112     }
0113 
0114     void unhandled_exception()
0115     {
0116         detail::self_destroy(std::coroutine_handle<post_coroutine_promise<Allocator>>::from_promise(*this));
0117         throw;
0118     }
0119 };
0120 
0121 
0122 }
0123 
0124 namespace std
0125 {
0126 
0127 template <typename T, typename ... Args>
0128 struct coroutine_traits<coroutine_handle<boost::cobalt::detail::post_coroutine_promise<T>>, Args...>
0129 {
0130     using promise_type = boost::cobalt::detail::post_coroutine_promise<T>;
0131 };
0132 
0133 } // namespace std
0134 
0135 
0136 namespace boost::cobalt::detail
0137 {
0138 
0139 
0140 template <typename CompletionToken>
0141 auto post_coroutine(CompletionToken token)
0142     -> std::coroutine_handle<post_coroutine_promise<asio::associated_allocator_t<CompletionToken>>>
0143 {
0144     co_yield std::move(token);
0145 }
0146 
0147 template <asio::execution::executor Executor, typename CompletionToken>
0148 auto post_coroutine(Executor exec, CompletionToken token)
0149     -> std::coroutine_handle<post_coroutine_promise<asio::associated_allocator_t<CompletionToken>>>
0150 {
0151     co_yield asio::bind_executor(exec, std::move(token));
0152 }
0153 
0154 template <with_get_executor Context, typename CompletionToken>
0155 auto post_coroutine(Context &ctx, CompletionToken token)
0156     -> std::coroutine_handle<post_coroutine_promise<asio::associated_allocator_t<CompletionToken>>>
0157 {
0158     co_yield asio::bind_executor(ctx.get_executor(), std::move(token));
0159 }
0160 
0161 }
0162 
0163 #endif //BOOST_COBALT_WRAPPER_HPP