8#include "scoped_task.hpp"
10#include "concepts.hpp"
12#include "awaitable_timer.hpp"
21namespace hi::inline v1 {
24template<awaitable_direct T>
26 using type = std::conditional_t<std::is_same_v<await_resume_result_t<T>,
void>, std::monostate,
await_resume_result_t<T>>;
29template<awaitable_direct T>
30using when_any_result_element_t = when_any_result_element<T>::type;
36template<
bool HasTimeout,
typename... Ts>
39 using result_type = std::variant<std::monostate, detail::when_any_result_element_t<Ts>...>;
40 using awaiter_type = std::variant<std::monostate, Ts...>;
48 template<
std::size_t I,
typename Awaiter,
typename... Result>
49 when_any_result(std::in_place_index_t<I>, Awaiter
const& awaiter, Result&&...result) noexcept :
50 _result{std::in_place_index<I + 1>, std::forward<Result>(result)...}, _awaiters{std::in_place_index<I + 1>, awaiter}
52 hi_axiom(_result.index() == _awaiters.index());
55 [[nodiscard]]
bool timeout()
const noexcept requires(HasTimeout)
66 return _result.index() - 1;
73 return compare_equal<1>(awaitable_cast(rhs));
81 return std::get<T>(rhs._result);
86 template<std::
size_t I>
89 return std::get<I + 1>(rhs._result);
94 awaiter_type _awaiters;
97 [[nodiscard]]
bool compare_equal(
awaitable_direct auto const& rhs)
const noexcept
99 if (I != _awaiters.index()) {
100 if constexpr (I + 1 < std::variant_size_v<awaiter_type>) {
101 return compare_equal<I + 1>(rhs);
106 using get_type = std::decay_t<decltype(get<I>(_awaiters))>;
107 using cmp_type = std::decay_t<
decltype(rhs)>;
109 if constexpr (std::is_same_v<get_type, cmp_type>) {
110 return std::get<I>(_awaiters) == rhs;
121template<
bool HasTimeout,
typename... Ts>
148 template<
typename Rep,
typename Period>
155 when_any(when_any&&) =
delete;
156 when_any(when_any
const&) =
delete;
157 when_any& operator=(when_any&&) =
delete;
158 when_any& operator=(when_any
const&) =
delete;
160 [[nodiscard]]
constexpr bool await_ready() noexcept
162 static_assert(
sizeof...(Ts) > 0);
163 return _await_ready<0>();
166 void await_suspend(std::coroutine_handle<>
const& handle)
noexcept
168 static_assert(
sizeof...(Ts) > 0);
169 return _await_suspend<0>(handle);
172 value_type await_resume() noexcept
181 std::tuple<
typename notifier<void(await_resume_result_t<Ts>)>::token_type...> _task_cbts;
184 template<awaitable_direct Awaiter>
185 static scoped_task<await_resume_result_t<Awaiter>> _await_suspend_task(Awaiter& awaiter)
187 co_return co_await awaiter;
190 template<std::
size_t I>
191 bool _await_ready() noexcept
193 auto& task = std::get<I>(_tasks) = _await_suspend_task(std::get<I>(_awaiters));
195 if (task.completed()) {
196 using arg_type = await_resume_result_t<decltype(std::get<I>(_awaiters))>;
198 if constexpr (std::is_same_v<arg_type, void>) {
199 _value = {std::in_place_index<I>, std::get<I>(_awaiters)};
201 _value = {std::in_place_index<I>, std::get<I>(_awaiters), task.value()};
205 }
else if constexpr (I + 1 <
sizeof...(Ts)) {
206 return _await_ready<I + 1>();
213 template<std::
size_t I>
214 void _await_suspend(std::coroutine_handle<>
const& handle)
noexcept
216 using arg_type = await_resume_result_t<decltype(std::get<I>(_awaiters))>;
218 if constexpr (std::is_same_v<arg_type, void>) {
219 std::get<I>(_task_cbts) = std::get<I>(_tasks).subscribe([
this, handle]() {
220 this->_value = {std::in_place_index<I>, std::get<I>(_awaiters)};
225 std::get<I>(_task_cbts) = std::get<I>(_tasks).subscribe([
this, handle](arg_type
const& arg) {
226 this->_value = {std::in_place_index<I>, std::get<I>(_awaiters), arg};
231 if constexpr (I + 1 <
sizeof...(Ts)) {
232 _await_suspend<I + 1>(handle);
236 template<
bool HasTimeout,
typename... Args>
237 friend class when_any;
240template<awaitable... Others>
241when_any(Others&&...) -> when_any<false, awaitable_cast_type_t<Others>...>;
243template<
typename Rep,
typename Period, awaitable... Others>
await_resume_result< T >::type await_resume_result_t
Get the result type of an awaitable.
Definition type_traits.hpp:411
This file includes required definitions.
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition required.hpp:29
Definition awaitable_timer.hpp:11
Definition when_any.hpp:25
Result of the when_any awaitable.
Definition when_any.hpp:37
std::size_t index() const noexcept
The index of the awaitable that was triggered.
Definition when_any.hpp:64
friend auto & get(when_any_result const &rhs) noexcept
Get the value returned by the awaitable that triggered when_any.
Definition when_any.hpp:79
bool operator==(awaitable auto const &rhs) const noexcept
Comparison to check if the awaitable was the one that triggered when_any.
Definition when_any.hpp:71
An awaitable that waits for any of the given awaitables to complete.
Definition when_any.hpp:122
when_any(awaitable auto &&...others) noexcept
Construct a when_any object from the given awaitables.
Definition when_any.hpp:136
when_any(std::chrono::duration< Rep, Period > timeout, awaitable auto &&...others) noexcept
Construct a when_any object from the given awaitables.
Definition when_any.hpp:149
Check if type can be directly co_await on.
Definition concepts.hpp:134
Check if type can be directly or indirectly co_await on.
Definition concepts.hpp:170