File indexing completed on 2025-07-12 08:08:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
0013 #define BOOST_ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
0014
0015 #include <boost/asio/detail/config.hpp>
0016 #include <boost/asio/append.hpp>
0017 #include <boost/asio/awaitable.hpp>
0018 #include <boost/asio/experimental/coro_traits.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
0021 # include <coroutine>
0022 #else
0023 # include <experimental/coroutine>
0024 #endif
0025
0026 namespace boost {
0027 namespace asio {
0028 namespace experimental {
0029 namespace detail {
0030
0031 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
0032
0033 using std::coroutine_handle;
0034 using std::coroutine_traits;
0035 using std::suspend_never;
0036 using std::suspend_always;
0037 using std::noop_coroutine;
0038
0039 #else
0040
0041 using std::experimental::coroutine_handle;
0042 using std::experimental::coroutine_traits;
0043 using std::experimental::suspend_never;
0044 using std::experimental::suspend_always;
0045 using std::experimental::noop_coroutine;
0046
0047 #endif
0048
0049 struct partial_coro
0050 {
0051 coroutine_handle<void> handle{nullptr};
0052 };
0053
0054 template <typename Allocator>
0055 struct partial_promise_base
0056 {
0057 template <typename Executor, typename Token, typename... Args>
0058 void* operator new(std::size_t size, Executor&, Token& tk, Args&...)
0059 {
0060 return allocate_coroutine<Allocator>(size, get_associated_allocator(tk));
0061 }
0062
0063 void operator delete(void* raw, std::size_t size)
0064 {
0065 deallocate_coroutine<Allocator>(raw, size);
0066 }
0067 };
0068
0069 template <>
0070 struct partial_promise_base<std::allocator<void>>
0071 {
0072 };
0073
0074 template <typename Allocator>
0075 struct partial_promise : partial_promise_base<Allocator>
0076 {
0077 auto initial_suspend() noexcept
0078 {
0079 return boost::asio::detail::suspend_always{};
0080 }
0081
0082 auto final_suspend() noexcept
0083 {
0084 struct awaitable_t
0085 {
0086 partial_promise *p;
0087
0088 constexpr bool await_ready() noexcept { return true; }
0089
0090 auto await_suspend(boost::asio::detail::coroutine_handle<>) noexcept
0091 {
0092 p->get_return_object().handle.destroy();
0093 }
0094
0095 constexpr void await_resume() noexcept {}
0096 };
0097
0098 return awaitable_t{this};
0099 }
0100
0101 void return_void() {}
0102
0103 partial_coro get_return_object()
0104 {
0105 return partial_coro{coroutine_handle<partial_promise>::from_promise(*this)};
0106 }
0107
0108 void unhandled_exception()
0109 {
0110 assert(false);
0111 }
0112 };
0113
0114 }
0115 }
0116 }
0117 }
0118
0119 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
0120
0121 namespace std {
0122
0123 template <typename Executor, typename Completion, typename... Args>
0124 struct coroutine_traits<
0125 boost::asio::experimental::detail::partial_coro,
0126 Executor, Completion, Args...>
0127 {
0128 using promise_type =
0129 boost::asio::experimental::detail::partial_promise<
0130 boost::asio::associated_allocator_t<Completion>>;
0131 };
0132
0133 }
0134
0135 #else
0136
0137 namespace std { namespace experimental {
0138
0139 template <typename Executor, typename Completion, typename... Args>
0140 struct coroutine_traits<
0141 boost::asio::experimental::detail::partial_coro,
0142 Executor, Completion, Args...>
0143 {
0144 using promise_type =
0145 boost::asio::experimental::detail::partial_promise<
0146 boost::asio::associated_allocator_t<Completion>>;
0147 };
0148
0149 }}
0150
0151 #endif
0152
0153 namespace boost {
0154 namespace asio {
0155 namespace experimental {
0156 namespace detail {
0157
0158 template <execution::executor Executor,
0159 typename CompletionToken, typename... Args>
0160 partial_coro post_coroutine(Executor exec,
0161 CompletionToken token, Args&&... args) noexcept
0162 {
0163 post(exec, boost::asio::append(std::move(token), std::move(args)...));
0164 co_return;
0165 }
0166
0167 template <detail::execution_context Context,
0168 typename CompletionToken, typename... Args>
0169 partial_coro post_coroutine(Context& ctx,
0170 CompletionToken token, Args&&... args) noexcept
0171 {
0172 post(ctx, boost::asio::append(std::move(token), std::move(args)...));
0173 co_return;
0174 }
0175
0176 template <execution::executor Executor,
0177 typename CompletionToken, typename... Args>
0178 partial_coro dispatch_coroutine(Executor exec,
0179 CompletionToken token, Args&&... args) noexcept
0180 {
0181 dispatch(exec, boost::asio::append(std::move(token), std::move(args)...));
0182 co_return;
0183 }
0184
0185 template <detail::execution_context Context,
0186 typename CompletionToken, typename... Args>
0187 partial_coro dispatch_coroutine(Context& ctx,
0188 CompletionToken token, Args &&... args) noexcept
0189 {
0190 dispatch(ctx, boost::asio::append(std::move(token), std::move(args)...));
0191 co_return;
0192 }
0193
0194 }
0195 }
0196 }
0197 }
0198
0199 #endif