yuzu/externals/vcpkg/packages/boost-asio_x64-windows/include/boost/asio/experimental/impl/use_coro.hpp

271 lines
6.8 KiB
C++
Raw Normal View History

2022-11-05 18:35:56 +04:00
//
// experimental/impl/use_coro.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2021-2022 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 BOOST_ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP
#define BOOST_ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace experimental {
template <typename Yield, typename Return, typename Executor>
struct coro;
namespace detail {
template <typename Yield, typename Return, typename Executor>
struct coro_promise;
template <typename Executor, typename... Ts>
struct coro_init_handler
{
struct handler_t
{
};
constexpr static handler_t handler{};
struct init_helper;
struct promise_type
{
auto initial_suspend() noexcept { return suspend_always{}; }
auto final_suspend() noexcept { return suspend_always(); }
void return_void() {}
void unhandled_exception() { assert(false); }
auto await_transform(handler_t)
{
assert(executor);
assert(h);
return init_helper{this};
}
std::optional<Executor> executor;
std::optional<std::tuple<Ts...>> result;
coroutine_handle<> h;
coro_init_handler get_return_object() { return coro_init_handler{this}; }
cancellation_slot cancel_slot;
};
struct init_helper
{
promise_type *self_;
constexpr static bool await_ready() noexcept { return true; }
constexpr static void await_suspend(coroutine_handle<>) noexcept {}
auto await_resume() const noexcept
{
assert(self_);
return bind_cancellation_slot(self_->cancel_slot,
bind_executor(*self_->executor, [self = self_](Ts... ts)
{
self->cancel_slot.clear();
self->result.emplace(std::move(ts)...);
self->h.resume();
}));
}
};
promise_type* promise;
void unhandled_exception() noexcept
{
throw;
}
struct noexcept_version
{
promise_type *promise;
constexpr static bool await_ready() noexcept { return false; }
template <typename Yield, typename Return,
convertible_to<Executor> Executor1>
auto await_suspend(
coroutine_handle<coro_promise<Yield, Return, Executor1> > h) noexcept
{
promise->executor = h.promise().get_executor();
promise->h = h;
return coroutine_handle<promise_type>::from_promise(*promise);
}
template <typename... Args>
static auto resume_impl(std::tuple<Args...>&& tup)
{
return std::move(tup);
}
template <typename Arg>
static auto resume_impl(std::tuple<Arg>&& tup)
{
return get<0>(std::move(tup));
}
static void resume_impl(std::tuple<>&&) {}
auto await_resume() const noexcept
{
auto res = std::move(promise->result.value());
coroutine_handle<promise_type>::from_promise(*promise).destroy();
return resume_impl(std::move(res));
}
};
struct throwing_version
{
promise_type *promise;
constexpr static bool await_ready() noexcept { return false; }
template <typename Yield, typename Return,
convertible_to<Executor> Executor1>
auto await_suspend(
coroutine_handle<coro_promise<Yield, Return, Executor1> > h) noexcept
{
promise->executor = h.promise().get_executor();
promise->h = h;
return coroutine_handle<promise_type>::from_promise(*promise);
}
template <typename... Args>
static auto resume_impl(std::tuple<Args...>&& tup)
{
return std::move(tup);
}
static void resume_impl(std::tuple<>&&) {}
template <typename Arg>
static auto resume_impl(std::tuple<Arg>&& tup)
{
return get<0>(std::move(tup));
}
template <typename... Args>
static auto resume_impl(std::tuple<std::exception_ptr, Args...>&& tup)
{
auto ex = get<0>(std::move(tup));
if (ex)
std::rethrow_exception(ex);
if constexpr (sizeof...(Args) == 0u)
return;
else if constexpr (sizeof...(Args) == 1u)
return get<1>(std::move(tup));
else
{
return
[&]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
return std::make_tuple(std::get<Idx + 1>(std::move(tup))...);
}(std::make_index_sequence<sizeof...(Args) - 1>{});
}
}
template <typename... Args>
static auto resume_impl(
std::tuple<boost::system::error_code, Args...>&& tup)
{
auto ec = get<0>(std::move(tup));
if (ec)
boost::asio::detail::throw_exception(
boost::system::system_error(ec, "error_code in use_coro"));
if constexpr (sizeof...(Args) == 0u)
return;
else if constexpr (sizeof...(Args) == 1u)
return get<1>(std::move(tup));
else
return
[&]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
return std::make_tuple(std::get<Idx + 1>(std::move(tup))...);
}(std::make_index_sequence<sizeof...(Args) - 1>{});
}
static auto resume_impl(std::tuple<std::exception_ptr>&& tup)
{
auto ex = get<0>(std::move(tup));
if (ex)
std::rethrow_exception(ex);
}
static auto resume_impl(
std::tuple<boost::system::error_code>&& tup)
{
auto ec = get<0>(std::move(tup));
if (ec)
boost::asio::detail::throw_error(ec, "error_code in use_coro");
}
auto await_resume() const
{
auto res = std::move(promise->result.value());
coroutine_handle<promise_type>::from_promise(*promise).destroy();
return resume_impl(std::move(res));
}
};
auto as_noexcept(cancellation_slot&& sl) && noexcept
{
promise->cancel_slot = std::move(sl);
return noexcept_version{promise};
}
auto as_throwing(cancellation_slot&& sl) && noexcept
{
promise->cancel_slot = std::move(sl);
return throwing_version{promise};
}
};
} // namespace detail
} // namespace experimental
#if !defined(GENERATING_DOCUMENTATION)
template <typename Executor, typename R, typename... Args>
struct async_result<experimental::use_coro_t<Executor>, R(Args...)>
{
using return_type = experimental::detail::coro_init_handler<
Executor, typename decay<Args>::type...>;
template <typename Initiation, typename... InitArgs>
static return_type initiate(Initiation initiation,
experimental::use_coro_t<Executor>, InitArgs... args)
{
std::move(initiation)(co_await return_type::handler, std::move(args)...);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP