21#include "pw_async2/dispatcher.h"
25template <
typename... Pendables>
31template <
size_t I,
typename T>
33 static constexpr size_t kIndex = I;
37 template <
typename... Pendables>
40 explicit SelectResult(T&& val) : value(std::move(val)) {}
45 static constexpr size_t kIndex = std::numeric_limits<size_t>::max();
46 std::nullopt_t value = std::nullopt;
51template <
typename Is,
typename... Pendables>
54template <
size_t... Is,
typename... Pendables>
56 using type = std::variant<SelectResult<Is, PendOutputOf<Pendables>>...,
60template <
typename ResultVariant,
61 typename AllPendablesCompletedHandler,
62 typename ReadyHandlers,
64void VisitSelectResult(ResultVariant&& variant,
65 AllPendablesCompletedHandler&& all_completed,
66 ReadyHandlers&& ready_handlers,
67 std::index_sequence<Is...>) {
70 using ArgType = std::decay_t<
decltype(arg)>;
71 if constexpr (std::is_same_v<ArgType, AllPendablesCompleted>) {
72 std::invoke(std::forward<AllPendablesCompletedHandler>(all_completed),
75 std::invoke(std::get<ArgType::kIndex>(
76 std::forward<ReadyHandlers>(ready_handlers)),
77 std::move(arg.value));
80 std::forward<ResultVariant>(variant));
123template <
typename... Pendables>
126 static_assert(
sizeof...(Pendables) > 0,
127 "Cannot select over an empty set of pendables");
130 std::make_index_sequence<
sizeof...(Pendables)>,
136 : pendables_(std::move(pendables)...) {}
146 template <
size_t kTupleIndex>
148 if constexpr (kTupleIndex <
sizeof...(Pendables)) {
149 auto& pendable = std::get<kTupleIndex>(pendables_);
151 if (pendable.completed()) {
152 return PendFrom<kTupleIndex + 1>(cx, has_active_pendable);
156 PendOutputOf<std::tuple_element_t<kTupleIndex,
decltype(pendables_)>>;
157 Poll<OutputType> result = pendable.Pend(cx);
159 if (result.IsReady()) {
160 return Ready(ResultVariant(
161 std::in_place_index<kTupleIndex>,
162 SelectResult<kTupleIndex, OutputType>(std::move(*result))));
164 return PendFrom<kTupleIndex + 1>(cx,
true);
168 if (!has_active_pendable) {
169 return Ready(AllPendablesCompleted{});
175 std::tuple<Pendables...> pendables_;
178template <
typename... Pendables>
179Selector(Pendables&&...) -> Selector<Pendables...>;
185template <
typename... Pendables>
186auto Select(Context& cx, Pendables&&... pendables) {
187 Selector selector(std::forward<Pendables>(pendables)...);
188 return selector.Pend(cx);
193template <
typename ResultVariant,
194 typename AllPendablesCompletedHandler,
195 typename... ReadyHandler>
196void VisitSelectResult(
197 ResultVariant&& variant,
198 AllPendablesCompletedHandler&& on_all_pendables_completed,
199 ReadyHandler&&... on_ready) {
200 static_assert(std::variant_size_v<std::decay_t<ResultVariant>> - 1 ==
201 sizeof...(ReadyHandler),
202 "Number of handlers must match the number of pendables.");
203 internal::VisitSelectResult(
204 std::forward<ResultVariant>(variant),
205 std::forward<AllPendablesCompletedHandler>(on_all_pendables_completed),
206 std::forward_as_tuple(std::forward<ReadyHandler>(on_ready)...),
207 std::make_index_sequence<
sizeof...(ReadyHandler)>{});
Poll< ResultVariant > Pend(Context &cx)
Definition: select.h:140
Indicates that every pendable within a Selector has completed.
Definition: select.h:44