198 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //
 | |
| // experimental/detail/partial_promise.hpp
 | |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| //
 | |
| // Copyright (c) 2021-2023 Klemens D. Morgenstern
 | |
| //                         (klemens dot morgenstern at gmx dot net)
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| 
 | |
| #ifndef ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
 | |
| #define ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
 | |
| 
 | |
| #include "asio/detail/config.hpp"
 | |
| #include "asio/append.hpp"
 | |
| #include "asio/awaitable.hpp"
 | |
| #include "asio/experimental/coro_traits.hpp"
 | |
| 
 | |
| #if defined(ASIO_HAS_STD_COROUTINE)
 | |
| # include <coroutine>
 | |
| #else // defined(ASIO_HAS_STD_COROUTINE)
 | |
| # include <experimental/coroutine>
 | |
| #endif // defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| namespace asio {
 | |
| namespace experimental {
 | |
| namespace detail {
 | |
| 
 | |
| #if defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| using std::coroutine_handle;
 | |
| using std::coroutine_traits;
 | |
| using std::suspend_never;
 | |
| using std::suspend_always;
 | |
| using std::noop_coroutine;
 | |
| 
 | |
| #else // defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| using std::experimental::coroutine_handle;
 | |
| using std::experimental::coroutine_traits;
 | |
| using std::experimental::suspend_never;
 | |
| using std::experimental::suspend_always;
 | |
| using std::experimental::noop_coroutine;
 | |
| 
 | |
| #endif // defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| struct partial_coro
 | |
| {
 | |
|   coroutine_handle<void> handle{nullptr};
 | |
| };
 | |
| 
 | |
| template <typename Allocator>
 | |
| struct partial_promise_base
 | |
| {
 | |
|   template <typename Executor, typename Token, typename... Args>
 | |
|   void* operator new(const std::size_t size, Executor&, Token& tk, Args&...)
 | |
|   {
 | |
|     return allocate_coroutine<Allocator>(size, get_associated_allocator(tk));
 | |
|   }
 | |
| 
 | |
|   void operator delete(void* raw, const std::size_t size)
 | |
|   {
 | |
|     deallocate_coroutine<Allocator>(raw, size);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct partial_promise_base<std::allocator<void>>
 | |
| {
 | |
| };
 | |
| 
 | |
| template <typename Allocator>
 | |
| struct partial_promise : partial_promise_base<Allocator>
 | |
| {
 | |
|   auto initial_suspend() noexcept
 | |
|   {
 | |
|     return asio::detail::suspend_always{};
 | |
|   }
 | |
| 
 | |
|   auto final_suspend() noexcept
 | |
|   {
 | |
|     struct awaitable_t
 | |
|     {
 | |
|       partial_promise *p;
 | |
| 
 | |
|       constexpr bool await_ready() noexcept { return true; }
 | |
| 
 | |
|       auto await_suspend(asio::detail::coroutine_handle<>) noexcept
 | |
|       {
 | |
|         p->get_return_object().handle.destroy();
 | |
|       }
 | |
| 
 | |
|       constexpr void await_resume() noexcept {}
 | |
|     };
 | |
| 
 | |
|     return awaitable_t{this};
 | |
|   }
 | |
| 
 | |
|   void return_void() {}
 | |
| 
 | |
|   partial_coro get_return_object()
 | |
|   {
 | |
|     return partial_coro{coroutine_handle<partial_promise>::from_promise(*this)};
 | |
|   }
 | |
| 
 | |
|   void unhandled_exception()
 | |
|   {
 | |
|     assert(false);
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| }; // namespace detail
 | |
| } // namespace experimental
 | |
| } // namespace asio
 | |
| 
 | |
| #if defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| namespace std {
 | |
| 
 | |
| template <typename Executor, typename Completion, typename... Args>
 | |
| struct coroutine_traits<
 | |
|     asio::experimental::detail::partial_coro,
 | |
|     Executor, Completion, Args...>
 | |
| {
 | |
|   using promise_type =
 | |
|     asio::experimental::detail::partial_promise<
 | |
|       asio::associated_allocator_t<Completion>>;
 | |
| };
 | |
| 
 | |
| } // namespace std
 | |
| 
 | |
| #else // defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| namespace std { namespace experimental {
 | |
| 
 | |
| template <typename Executor, typename Completion, typename... Args>
 | |
| struct coroutine_traits<
 | |
|     asio::experimental::detail::partial_coro,
 | |
|     Executor, Completion, Args...>
 | |
| {
 | |
|   using promise_type =
 | |
|     asio::experimental::detail::partial_promise<
 | |
|       asio::associated_allocator_t<Completion>>;
 | |
| };
 | |
| 
 | |
| }} // namespace std::experimental
 | |
| 
 | |
| #endif // defined(ASIO_HAS_STD_COROUTINE)
 | |
| 
 | |
| namespace asio {
 | |
| namespace experimental {
 | |
| namespace detail {
 | |
| 
 | |
| template <execution::executor Executor,
 | |
|     typename CompletionToken, typename... Args>
 | |
| partial_coro post_coroutine(Executor exec,
 | |
|     CompletionToken token, Args&&... args) noexcept
 | |
| {
 | |
|   post(exec, asio::append(std::move(token), std::move(args)...));
 | |
|   co_return;
 | |
| }
 | |
| 
 | |
| template <detail::execution_context Context,
 | |
|     typename CompletionToken, typename... Args>
 | |
| partial_coro post_coroutine(Context& ctx,
 | |
|     CompletionToken token, Args&&... args) noexcept
 | |
| {
 | |
|   post(ctx, asio::append(std::move(token), std::move(args)...));
 | |
|   co_return;
 | |
| }
 | |
| 
 | |
| template <execution::executor Executor,
 | |
|     typename CompletionToken, typename... Args>
 | |
| partial_coro dispatch_coroutine(Executor exec,
 | |
|     CompletionToken token, Args&&... args) noexcept
 | |
| {
 | |
|   dispatch(exec, asio::append(std::move(token), std::move(args)...));
 | |
|   co_return;
 | |
| }
 | |
| 
 | |
| template <detail::execution_context Context,
 | |
|     typename CompletionToken, typename... Args>
 | |
| partial_coro dispatch_coroutine(Context& ctx,
 | |
|     CompletionToken token, Args &&... args) noexcept
 | |
| {
 | |
|   dispatch(ctx, asio::append(std::move(token), std::move(args)...));
 | |
|   co_return;
 | |
| }
 | |
| 
 | |
| } // namespace detail
 | |
| } // namespace experimental
 | |
| } // namespace asio
 | |
| 
 | |
| #endif // ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
 |