16#include "pw_async2/dispatcher.h"
17#include "pw_async2/future.h"
28template <
typename... Pendables>
29class [[deprecated(
"Use future-based Join instead")]]
Joiner {
31 static constexpr auto kTupleIndexSequence =
32 std::make_index_sequence<
sizeof...(Pendables)>();
33 using TupleOfOutputRvalues =
34 std::tuple<internal::PendOutputOf<Pendables>&&...>;
38 explicit Joiner(Pendables&&... pendables)
39 : pendables_(std::move(pendables)...),
40 outputs_(
Poll<internal::PendOutputOf<Pendables>>(
Pending())...) {}
45 if (!PendElements(cx, kTupleIndexSequence)) {
48 return TakeOutputs(kTupleIndexSequence);
55 template <
size_t... Is>
56 bool PendElements(
Context& cx, std::index_sequence<Is...>) {
57 return (... && PendElement<Is>(cx));
61 template <
size_t... Is>
62 Poll<TupleOfOutputRvalues> TakeOutputs(std::index_sequence<Is...>) {
63 return Poll<TupleOfOutputRvalues>(
64 std::forward_as_tuple<internal::PendOutputOf<Pendables>...>(
65 TakeOutput<Is>()...));
73 template <
size_t kTupleIndex>
74 bool PendElement(Context& cx) {
75 auto& output = std::get<kTupleIndex>(outputs_);
76 if (output.IsReady()) {
79 output = std::get<kTupleIndex>(pendables_).Pend(cx);
80 return output.IsReady();
84 template <
size_t kTupleIndex>
85 internal::PendOutputOf<
86 typename std::tuple_element<kTupleIndex,
87 std::tuple<Pendables...>>::type>&&
89 return std::move(std::get<kTupleIndex>(outputs_).value());
92 std::tuple<Pendables...> pendables_;
93 std::tuple<Poll<internal::PendOutputOf<Pendables>>...> outputs_;
96template <
typename... Pendables>
97Joiner(Pendables&&...) -> Joiner<Pendables...>;
99template <
typename... Futures>
101 :
public Future<JoinFuture<Futures...>,
102 std::tuple<typename Futures::value_type&&...>> {
104 static constexpr auto kTupleIndexSequence =
105 std::make_index_sequence<
sizeof...(Futures)>();
106 using TupleOfOutputRvalues = std::tuple<
typename Futures::value_type&&...>;
111 template <
typename... Fs>
112 friend constexpr auto Join(Fs&&...);
114 explicit constexpr JoinFuture(Futures&&... futures)
115 : futures_(std::in_place, std::move(futures)...),
121 if (!PendElements(cx, kTupleIndexSequence)) {
124 return TakeOutputs(kTupleIndexSequence);
127 void DoMarkComplete() { futures_.reset(); }
128 bool DoIsComplete()
const {
return !futures_.has_value(); }
133 template <
size_t... Is>
134 bool PendElements(
Context& cx, std::index_sequence<Is...>) {
135 (PendElement<Is>(cx), ...);
136 return (std::get<Is>(outputs_).IsReady() && ...);
141 template <
size_t kTupleIndex>
142 void PendElement(
Context& cx) {
143 auto& output = std::get<kTupleIndex>(outputs_);
144 if (!output.IsReady()) {
145 output = std::get<kTupleIndex>(*futures_).Pend(cx);
150 template <
size_t... Is>
153 std::forward_as_tuple<internal::PendOutputOf<Futures>...>(
154 TakeOutput<Is>()...));
158 template <
size_t kTupleIndex>
159 internal::PendOutputOf<
160 typename std::tuple_element<kTupleIndex, std::tuple<Futures...>>::type>&&
162 return std::move(std::get<kTupleIndex>(outputs_).value());
165 static_assert(std::conjunction_v<is_future<Futures>...>,
166 "All types in JoinFuture must be Future types");
167 std::optional<std::tuple<Futures...>> futures_;
168 std::tuple<Poll<internal::PendOutputOf<Futures>>...> outputs_;
171template <
typename... Futures>
179template <
typename... Futures>
180constexpr auto Join(Futures&&... futures) {
181 static_assert(std::conjunction_v<is_future<Futures>...>,
182 "All arguments to Join must be Future types");
183 return JoinFuture(std::forward<Futures>(futures)...);
Poll< TupleOfOutputRvalues > Pend(Context &cx)
Definition: join.h:44
Joiner(Pendables &&... pendables)
Creates a Joiner from a series of pendable values.
Definition: join.h:38
constexpr auto Join(Futures &&... futures)
Definition: join.h:180
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271