165 lines
3.7 KiB
C++
165 lines
3.7 KiB
C++
// Copyright (c) 2022 Klemens D. Morgenstern
|
|
//
|
|
// 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_COBALT_UTIL_HPP
|
|
#define BOOST_COBALT_UTIL_HPP
|
|
|
|
#include <boost/cobalt/config.hpp>
|
|
#include <boost/cobalt/this_thread.hpp>
|
|
|
|
#include <boost/core/no_exceptions_support.hpp>
|
|
#include <boost/system/result.hpp>
|
|
#include <boost/variant2/variant.hpp>
|
|
|
|
#include <limits>
|
|
#include <type_traits>
|
|
#include <coroutine>
|
|
|
|
namespace boost::variant2
|
|
{
|
|
struct monostate;
|
|
}
|
|
|
|
namespace boost::cobalt::detail
|
|
{
|
|
|
|
template<typename T>
|
|
constexpr std::size_t variadic_first(std::size_t = 0u)
|
|
{
|
|
return std::numeric_limits<std::size_t>::max();
|
|
}
|
|
|
|
|
|
template<typename T, typename First, typename ... Args>
|
|
constexpr std::size_t variadic_first(std::size_t pos = 0u)
|
|
{
|
|
if constexpr (std::is_same_v<std::decay_t<First>, T>)
|
|
return pos;
|
|
else
|
|
return variadic_first<T, Args...>(pos+1);
|
|
}
|
|
|
|
|
|
template<typename T, typename ... Args>
|
|
constexpr bool variadic_has = variadic_first<T, Args...>() < sizeof...(Args);
|
|
|
|
template<std::size_t Idx, typename First, typename ... Args>
|
|
requires (Idx <= sizeof...(Args))
|
|
constexpr decltype(auto) get_variadic(First && first, Args && ... args)
|
|
{
|
|
if constexpr (Idx == 0u)
|
|
return static_cast<First>(first);
|
|
else
|
|
return get_variadic<Idx-1u>(static_cast<Args>(args)...);
|
|
}
|
|
|
|
template<std::size_t Idx, typename ... Args>
|
|
struct variadic_element;
|
|
|
|
template<std::size_t Idx, typename First, typename ...Tail>
|
|
struct variadic_element<Idx, First, Tail...>
|
|
{
|
|
using type = typename variadic_element<Idx-1, Tail...>::type;
|
|
};
|
|
|
|
template<typename First, typename ...Tail>
|
|
struct variadic_element<0u, First, Tail...>
|
|
{
|
|
using type = First;
|
|
};
|
|
|
|
template<std::size_t Idx, typename ... Args>
|
|
using variadic_element_t = typename variadic_element<Idx, Args...>::type;
|
|
|
|
|
|
template<typename ... Args>
|
|
struct variadic_last
|
|
{
|
|
using type = variadic_element_t<sizeof...(Args) - 1, Args...>;
|
|
};
|
|
|
|
template<>
|
|
struct variadic_last<>
|
|
{
|
|
using type = void;
|
|
};
|
|
|
|
template<typename ... Args>
|
|
using variadic_last_t = typename variadic_last<Args...>::type;
|
|
|
|
|
|
template<typename First>
|
|
constexpr decltype(auto) get_last_variadic(First && first)
|
|
{
|
|
return first;
|
|
}
|
|
|
|
template<typename First, typename ... Args>
|
|
constexpr decltype(auto) get_last_variadic(First &&, Args && ... args)
|
|
{
|
|
return get_last_variadic(static_cast<Args>(args)...);
|
|
}
|
|
|
|
template<typename Awaitable>
|
|
auto get_resume_result(Awaitable & aw) -> system::result<decltype(aw.await_resume()), std::exception_ptr>
|
|
{
|
|
using type = decltype(aw.await_resume());
|
|
BOOST_TRY
|
|
{
|
|
if constexpr (std::is_void_v<type>)
|
|
{
|
|
aw.await_resume();
|
|
return {};
|
|
}
|
|
else
|
|
return aw.await_resume();
|
|
}
|
|
BOOST_CATCH(...)
|
|
{
|
|
return std::current_exception();
|
|
}
|
|
BOOST_CATCH_END
|
|
}
|
|
|
|
#if BOOST_COBALT_NO_SELF_DELETE
|
|
|
|
BOOST_COBALT_DECL
|
|
void self_destroy(std::coroutine_handle<void> h, const cobalt::executor & exec) noexcept;
|
|
|
|
template<typename T>
|
|
inline void self_destroy(std::coroutine_handle<T> h) noexcept
|
|
{
|
|
if constexpr (requires {h.promise().get_executor();})
|
|
self_destroy(h, h.promise().get_executor());
|
|
else
|
|
self_destroy(h, this_thread::get_executor());
|
|
}
|
|
|
|
#else
|
|
|
|
template<typename T>
|
|
inline void self_destroy(std::coroutine_handle<T> h) noexcept
|
|
{
|
|
h.destroy();
|
|
}
|
|
|
|
template<typename T, typename Executor>
|
|
inline void self_destroy(std::coroutine_handle<T> h, const Executor &) noexcept
|
|
{
|
|
h.destroy();
|
|
}
|
|
|
|
#endif
|
|
|
|
template<typename T>
|
|
using void_as_monostate = std::conditional_t<std::is_void_v<T>, variant2::monostate, T>;
|
|
|
|
template<typename T>
|
|
using monostate_as_void = std::conditional_t<std::is_same_v<T, variant2::monostate>, void, T>;
|
|
|
|
|
|
}
|
|
|
|
#endif //BOOST_COBALT_UTIL_HPP
|