Skip to content

Commit 8e8040b

Browse files
AnyOf: make it a functor
Being a functor is more fashionable than being a function.
1 parent 069a7a7 commit 8e8040b

1 file changed

Lines changed: 43 additions & 37 deletions

File tree

src/include/crhandle/taskutils.hpp

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -58,48 +58,54 @@ struct NonVoid<C<Ts...>>
5858
template <typename T>
5959
using NonVoid = typename internal::NonVoid<T>::Type;
6060

61-
template <Executor E, TaskResult... Rs>
62-
TaskHandle<NonVoid<std::variant<Rs...>>, E> AnyOf(TaskHandle<Rs, E>... ts)
61+
struct AnyOfFn
6362
{
64-
using ThisTaskHandle = TaskHandle<NonVoid<std::variant<Rs...>>, E>;
65-
66-
std::optional<NonVoid<std::variant<Rs...>>> ret;
67-
stdcr::coroutine_handle<> continuation = nullptr;
68-
69-
auto TaskWrapper = [&]<size_t I, typename R>(std::in_place_index_t<I> i,
70-
TaskHandle<R, E> task) -> TaskHandle<void, E> {
71-
if (ret.has_value())
72-
co_return;
73-
74-
if constexpr (std::is_same_v<R, void>) {
75-
co_await std::move(task);
76-
ret.emplace(i, internal::TypeConverter<void>::Type{});
77-
} else {
78-
R tmp = co_await std::move(task);
79-
ret.emplace(i, std::move(tmp));
80-
}
81-
if (continuation)
82-
continuation.resume();
83-
};
84-
85-
auto handles = internal::CreateArray(std::make_index_sequence<sizeof...(Rs)>{},
86-
std::forward_as_tuple(std::move(ts)...),
87-
TaskWrapper);
63+
template <Executor E, TaskResult... Rs>
64+
using HandleType = TaskHandle<NonVoid<std::variant<Rs...>>, E>;
8865

89-
auto thisHandle =
90-
co_await internal::CurrentHandleRetriever<typename ThisTaskHandle::promise_type>{};
91-
const auto & thisPromise = thisHandle.promise();
92-
93-
for (auto & h : handles)
94-
h.Run(thisPromise.Executor(), &thisPromise.CancelationFlag());
66+
template <Executor E, TaskResult... Rs>
67+
HandleType<E, Rs...> operator()(TaskHandle<Rs, E>... ts) const
68+
{
69+
std::optional<NonVoid<std::variant<Rs...>>> ret;
70+
stdcr::coroutine_handle<> continuation = nullptr;
71+
72+
auto TaskWrapper = [&]<size_t I, typename R>(std::in_place_index_t<I> i,
73+
TaskHandle<R, E> task) -> TaskHandle<void, E> {
74+
if (ret.has_value())
75+
co_return;
76+
77+
if constexpr (std::is_same_v<R, void>) {
78+
co_await std::move(task);
79+
ret.emplace(i, internal::TypeConverter<void>::Type{});
80+
} else {
81+
R tmp = co_await std::move(task);
82+
ret.emplace(i, std::move(tmp));
83+
}
84+
if (continuation)
85+
continuation.resume();
86+
};
87+
88+
auto tasks = internal::CreateArray(std::make_index_sequence<sizeof...(Rs)>{},
89+
std::forward_as_tuple(std::move(ts)...),
90+
TaskWrapper);
91+
92+
auto thisHandle =
93+
co_await internal::CurrentHandleRetriever<typename HandleType<E, Rs...>::promise_type>{};
94+
const auto & thisPromise = thisHandle.promise();
95+
96+
for (auto & h : tasks)
97+
h.Run(thisPromise.Executor(), &thisPromise.CancelationFlag());
98+
99+
if (!ret.has_value()) {
100+
continuation = thisHandle;
101+
co_await stdcr::suspend_always{};
102+
}
95103

96-
if (!ret.has_value()) {
97-
continuation = thisHandle;
98-
co_await stdcr::suspend_always{};
104+
co_return *ret;
99105
}
106+
};
100107

101-
co_return *ret;
102-
}
108+
inline constexpr AnyOfFn AnyOf;
103109

104110
} // namespace cr
105111

0 commit comments

Comments
 (0)