util.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_COBALT_UTIL_HPP
  6. #define BOOST_COBALT_UTIL_HPP
  7. #include <boost/cobalt/config.hpp>
  8. #include <boost/cobalt/this_thread.hpp>
  9. #include <boost/core/no_exceptions_support.hpp>
  10. #include <boost/system/result.hpp>
  11. #include <boost/variant2/variant.hpp>
  12. #include <limits>
  13. #include <type_traits>
  14. #include <coroutine>
  15. namespace boost::variant2
  16. {
  17. struct monostate;
  18. }
  19. namespace boost::cobalt::detail
  20. {
  21. template<typename T>
  22. constexpr std::size_t variadic_first(std::size_t = 0u)
  23. {
  24. return std::numeric_limits<std::size_t>::max();
  25. }
  26. template<typename T, typename First, typename ... Args>
  27. constexpr std::size_t variadic_first(std::size_t pos = 0u)
  28. {
  29. if constexpr (std::is_same_v<std::decay_t<First>, T>)
  30. return pos;
  31. else
  32. return variadic_first<T, Args...>(pos+1);
  33. }
  34. template<typename T, typename ... Args>
  35. constexpr bool variadic_has = variadic_first<T, Args...>() < sizeof...(Args);
  36. template<std::size_t Idx, typename First, typename ... Args>
  37. requires (Idx <= sizeof...(Args))
  38. constexpr decltype(auto) get_variadic(First && first, Args && ... args)
  39. {
  40. if constexpr (Idx == 0u)
  41. return static_cast<First>(first);
  42. else
  43. return get_variadic<Idx-1u>(static_cast<Args>(args)...);
  44. }
  45. template<std::size_t Idx, typename ... Args>
  46. struct variadic_element;
  47. template<std::size_t Idx, typename First, typename ...Tail>
  48. struct variadic_element<Idx, First, Tail...>
  49. {
  50. using type = typename variadic_element<Idx-1, Tail...>::type;
  51. };
  52. template<typename First, typename ...Tail>
  53. struct variadic_element<0u, First, Tail...>
  54. {
  55. using type = First;
  56. };
  57. template<std::size_t Idx, typename ... Args>
  58. using variadic_element_t = typename variadic_element<Idx, Args...>::type;
  59. template<typename ... Args>
  60. struct variadic_last
  61. {
  62. using type = variadic_element_t<sizeof...(Args) - 1, Args...>;
  63. };
  64. template<>
  65. struct variadic_last<>
  66. {
  67. using type = void;
  68. };
  69. template<typename ... Args>
  70. using variadic_last_t = typename variadic_last<Args...>::type;
  71. template<typename First>
  72. constexpr decltype(auto) get_last_variadic(First && first)
  73. {
  74. return first;
  75. }
  76. template<typename First, typename ... Args>
  77. constexpr decltype(auto) get_last_variadic(First &&, Args && ... args)
  78. {
  79. return get_last_variadic(static_cast<Args>(args)...);
  80. }
  81. template<typename Awaitable>
  82. auto get_resume_result(Awaitable & aw) -> system::result<decltype(aw.await_resume()), std::exception_ptr>
  83. {
  84. using type = decltype(aw.await_resume());
  85. BOOST_TRY
  86. {
  87. if constexpr (std::is_void_v<type>)
  88. {
  89. aw.await_resume();
  90. return {};
  91. }
  92. else
  93. return aw.await_resume();
  94. }
  95. BOOST_CATCH(...)
  96. {
  97. return std::current_exception();
  98. }
  99. BOOST_CATCH_END
  100. }
  101. #if BOOST_COBALT_NO_SELF_DELETE
  102. BOOST_COBALT_DECL
  103. void self_destroy(std::coroutine_handle<void> h, const cobalt::executor & exec) noexcept;
  104. template<typename T>
  105. inline void self_destroy(std::coroutine_handle<T> h) noexcept
  106. {
  107. if constexpr (requires {h.promise().get_executor();})
  108. self_destroy(h, h.promise().get_executor());
  109. else
  110. self_destroy(h, this_thread::get_executor());
  111. }
  112. #else
  113. template<typename T>
  114. inline void self_destroy(std::coroutine_handle<T> h) noexcept
  115. {
  116. h.destroy();
  117. }
  118. template<typename T, typename Executor>
  119. inline void self_destroy(std::coroutine_handle<T> h, const Executor &) noexcept
  120. {
  121. h.destroy();
  122. }
  123. #endif
  124. template<typename T>
  125. using void_as_monostate = std::conditional_t<std::is_void_v<T>, variant2::monostate, T>;
  126. template<typename T>
  127. using monostate_as_void = std::conditional_t<std::is_same_v<T, variant2::monostate>, void, T>;
  128. }
  129. #endif //BOOST_COBALT_UTIL_HPP