File indexing completed on 2025-01-18 09:28:51
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(const 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, const 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 }
0120
0121 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
0122
0123 namespace std {
0124
0125 template <typename Executor, typename Completion, typename... Args>
0126 struct coroutine_traits<
0127 boost::asio::experimental::detail::partial_coro,
0128 Executor, Completion, Args...>
0129 {
0130 using promise_type =
0131 boost::asio::experimental::detail::partial_promise<
0132 boost::asio::associated_allocator_t<Completion>>;
0133 };
0134
0135 }
0136
0137 #else
0138
0139 namespace std { namespace experimental {
0140
0141 template <typename Executor, typename Completion, typename... Args>
0142 struct coroutine_traits<
0143 boost::asio::experimental::detail::partial_coro,
0144 Executor, Completion, Args...>
0145 {
0146 using promise_type =
0147 boost::asio::experimental::detail::partial_promise<
0148 boost::asio::associated_allocator_t<Completion>>;
0149 };
0150
0151 }}
0152
0153 #endif
0154
0155 namespace boost {
0156 namespace asio {
0157 namespace experimental {
0158 namespace detail {
0159
0160 template <execution::executor Executor,
0161 typename CompletionToken, typename... Args>
0162 partial_coro post_coroutine(Executor exec,
0163 CompletionToken token, Args&&... args) noexcept
0164 {
0165 post(exec, boost::asio::append(std::move(token), std::move(args)...));
0166 co_return;
0167 }
0168
0169 template <detail::execution_context Context,
0170 typename CompletionToken, typename... Args>
0171 partial_coro post_coroutine(Context& ctx,
0172 CompletionToken token, Args&&... args) noexcept
0173 {
0174 post(ctx, boost::asio::append(std::move(token), std::move(args)...));
0175 co_return;
0176 }
0177
0178 template <execution::executor Executor,
0179 typename CompletionToken, typename... Args>
0180 partial_coro dispatch_coroutine(Executor exec,
0181 CompletionToken token, Args&&... args) noexcept
0182 {
0183 dispatch(exec, boost::asio::append(std::move(token), std::move(args)...));
0184 co_return;
0185 }
0186
0187 template <detail::execution_context Context,
0188 typename CompletionToken, typename... Args>
0189 partial_coro dispatch_coroutine(Context& ctx,
0190 CompletionToken token, Args &&... args) noexcept
0191 {
0192 dispatch(ctx, boost::asio::append(std::move(token), std::move(args)...));
0193 co_return;
0194 }
0195
0196 }
0197 }
0198 }
0199 }
0200
0201 #endif