C/C++ API Reference
Loading...
Searching...
No Matches
join.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include "pw_async2/dispatcher.h"
17#include "pw_async2/future.h"
18
19namespace pw::async2 {
20
22
23template <typename... Futures>
25 public:
26 using value_type = std::tuple<FutureValue<Futures>&&...>;
27
28 constexpr JoinFuture() : outputs_{} {}
29
30 [[nodiscard]] bool is_pendable() const { return state_.is_pendable(); }
31
32 [[nodiscard]] bool is_complete() const { return state_.is_complete(); }
33
37 PW_ASSERT(is_pendable());
38 if (!PendElements(cx, kTupleIndexSequence)) {
39 return Pending();
40 }
41
42 state_.MarkComplete();
43 return TakeOutputs(kTupleIndexSequence);
44 }
45
46 private:
47 static_assert(sizeof...(Futures) > 0u, "Cannot join an empty set of futures");
48
49 static constexpr auto kTupleIndexSequence =
50 std::make_index_sequence<sizeof...(Futures)>();
51 using TupleOfOutputRvalues = std::tuple<FutureValue<Futures>&&...>;
52
53 template <typename... Fs>
54 friend constexpr auto Join(Fs&&...);
55
56 explicit constexpr JoinFuture(Futures&&... futures)
57 : futures_(std::move(futures)...),
58 outputs_(Poll<typename Futures::value_type>(Pending())...),
59 state_(FutureState::kPending) {}
60
64 template <size_t... Is>
65 bool PendElements(Context& cx, std::index_sequence<Is...>) {
66 (PendElement<Is>(cx), ...);
67 return (std::get<Is>(outputs_).IsReady() && ...);
68 }
69
72 template <size_t kTupleIndex>
73 void PendElement(Context& cx) {
74 auto& output = std::get<kTupleIndex>(outputs_);
75 if (!output.IsReady()) {
76 output = std::get<kTupleIndex>(futures_).Pend(cx);
77 }
78 }
79
81 template <size_t... Is>
82 Poll<TupleOfOutputRvalues> TakeOutputs(std::index_sequence<Is...>) {
83 return Poll<TupleOfOutputRvalues>(
84 std::forward_as_tuple<FutureValue<Futures>...>(TakeOutput<Is>()...));
85 }
86
88 template <size_t kTupleIndex>
90 typename std::tuple_element<kTupleIndex, std::tuple<Futures...>>::type>&&
91 TakeOutput() {
92 return std::move(std::get<kTupleIndex>(outputs_).value());
93 }
94
95 static_assert((Future<Futures> && ...),
96 "All types in JoinFuture must be Future types");
97 std::tuple<Futures...> futures_;
98 std::tuple<Poll<typename Futures::value_type>...> outputs_;
99 FutureState state_;
100};
101
102template <typename... Futures>
103JoinFuture(Futures&&...) -> JoinFuture<Futures...>;
104
110template <typename... Futures>
111constexpr auto Join(Futures&&... futures) {
112 static_assert((Future<Futures> && ...),
113 "All arguments to Join must be Future types");
114 return JoinFuture(std::forward<Futures>(futures)...);
115}
116
118
119} // namespace pw::async2
Definition: context.h:46
Definition: future.h:111
constexpr bool is_pendable() const
Definition: future.h:149
void MarkComplete()
Definition: future.h:183
constexpr bool is_complete() const
Definition: future.h:154
Definition: join.h:24
Poll< value_type > Pend(Context &cx)
Definition: join.h:36
Definition: poll.h:138
Definition: future.h:47
constexpr auto Join(Futures &&... futures)
Definition: join.h:111
std::conditional_t< std::is_void_v< typename T::value_type >, ReadyType, typename T::value_type > FutureValue
Definition: future.h:107
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:353