util.hpp 3.8 KB

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