File indexing completed on 2025-12-16 09:44:25
0001
0002
0003
0004
0005 #ifndef BOOST_COBALT_UTIL_HPP
0006 #define BOOST_COBALT_UTIL_HPP
0007
0008 #include <boost/cobalt/config.hpp>
0009 #include <boost/cobalt/this_thread.hpp>
0010
0011 #include <boost/core/no_exceptions_support.hpp>
0012 #include <boost/system/result.hpp>
0013 #include <boost/variant2/variant.hpp>
0014
0015 #include <limits>
0016 #include <type_traits>
0017 #include <coroutine>
0018
0019 namespace boost::variant2
0020 {
0021 struct monostate;
0022 }
0023
0024 namespace boost::cobalt::detail
0025 {
0026
0027 template<typename T>
0028 constexpr std::size_t variadic_first(std::size_t = 0u)
0029 {
0030 return std::numeric_limits<std::size_t>::max();
0031 }
0032
0033
0034 template<typename T, typename First, typename ... Args>
0035 constexpr std::size_t variadic_first(std::size_t pos = 0u)
0036 {
0037 if constexpr (std::is_same_v<std::decay_t<First>, T>)
0038 return pos;
0039 else
0040 return variadic_first<T, Args...>(pos+1);
0041 }
0042
0043
0044 template<typename T, typename ... Args>
0045 constexpr bool variadic_has = variadic_first<T, Args...>() < sizeof...(Args);
0046
0047 template<std::size_t Idx, typename First, typename ... Args>
0048 requires (Idx <= sizeof...(Args))
0049 constexpr decltype(auto) get_variadic(First && first, Args && ... args)
0050 {
0051 if constexpr (Idx == 0u)
0052 return static_cast<First>(first);
0053 else
0054 return get_variadic<Idx-1u>(static_cast<Args>(args)...);
0055 }
0056
0057 template<std::size_t Idx, typename ... Args>
0058 struct variadic_element;
0059
0060 template<std::size_t Idx, typename First, typename ...Tail>
0061 struct variadic_element<Idx, First, Tail...>
0062 {
0063 using type = typename variadic_element<Idx-1, Tail...>::type;
0064 };
0065
0066 template<typename First, typename ...Tail>
0067 struct variadic_element<0u, First, Tail...>
0068 {
0069 using type = First;
0070 };
0071
0072 template<std::size_t Idx, typename ... Args>
0073 using variadic_element_t = typename variadic_element<Idx, Args...>::type;
0074
0075
0076 template<typename ... Args>
0077 struct variadic_last
0078 {
0079 using type = variadic_element_t<sizeof...(Args) - 1, Args...>;
0080 };
0081
0082 template<>
0083 struct variadic_last<>
0084 {
0085 using type = void;
0086 };
0087
0088 template<typename ... Args>
0089 using variadic_last_t = typename variadic_last<Args...>::type;
0090
0091
0092 template<typename First>
0093 constexpr decltype(auto) get_last_variadic(First && first)
0094 {
0095 return first;
0096 }
0097
0098 template<typename First, typename ... Args>
0099 constexpr decltype(auto) get_last_variadic(First &&, Args && ... args)
0100 {
0101 return get_last_variadic(static_cast<Args>(args)...);
0102 }
0103
0104 template<typename Awaitable>
0105 auto get_resume_result(Awaitable & aw) -> system::result<decltype(aw.await_resume()), std::exception_ptr>
0106 {
0107 using type = decltype(aw.await_resume());
0108 BOOST_TRY
0109 {
0110 if constexpr (std::is_void_v<type>)
0111 {
0112 aw.await_resume();
0113 return {};
0114 }
0115 else
0116 return aw.await_resume();
0117 }
0118 BOOST_CATCH(...)
0119 {
0120 return std::current_exception();
0121 }
0122 BOOST_CATCH_END
0123 }
0124
0125 #if BOOST_COBALT_NO_SELF_DELETE
0126
0127 BOOST_COBALT_DECL
0128 void self_destroy(std::coroutine_handle<void> h, const cobalt::executor & exec) noexcept;
0129
0130 template<typename T>
0131 inline void self_destroy(std::coroutine_handle<T> h) noexcept
0132 {
0133 if constexpr (requires {h.promise().get_executor();})
0134 self_destroy(h, h.promise().get_executor());
0135 else
0136 self_destroy(h, this_thread::get_executor());
0137 }
0138
0139 #else
0140
0141 template<typename T>
0142 inline void self_destroy(std::coroutine_handle<T> h) noexcept
0143 {
0144 h.destroy();
0145 }
0146
0147 template<typename T, typename Executor>
0148 inline void self_destroy(std::coroutine_handle<T> h, const Executor &) noexcept
0149 {
0150 h.destroy();
0151 }
0152
0153 #endif
0154
0155 template<typename T>
0156 using void_as_monostate = std::conditional_t<std::is_void_v<T>, variant2::monostate, T>;
0157
0158 template<typename T>
0159 using monostate_as_void = std::conditional_t<std::is_same_v<T, variant2::monostate>, void, T>;
0160
0161
0162 }
0163
0164 #endif