File indexing completed on 2025-12-17 09:40:33
0001
0002
0003
0004
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
0032
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
0040
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
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 }
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