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 Future<JoinFuture<Futures...>,
26 std::tuple<typename Futures::value_type&&...>> {
27 private:
28 static constexpr auto kTupleIndexSequence =
29 std::make_index_sequence<sizeof...(Futures)>();
30 using TupleOfOutputRvalues = std::tuple<typename Futures::value_type&&...>;
31
32 using Base = Future<JoinFuture<Futures...>, TupleOfOutputRvalues>;
33 friend Base;
34
35 template <typename... Fs>
36 friend constexpr auto Join(Fs&&...);
37
38 explicit constexpr JoinFuture(Futures&&... futures)
39 : futures_(std::in_place, std::move(futures)...),
41
45 if (!PendElements(cx, kTupleIndexSequence)) {
46 return Pending();
47 }
48 return TakeOutputs(kTupleIndexSequence);
49 }
50
51 void DoMarkComplete() { futures_.reset(); }
52 bool DoIsComplete() const { return !futures_.has_value(); }
53
57 template <size_t... Is>
58 bool PendElements(Context& cx, std::index_sequence<Is...>) {
59 (PendElement<Is>(cx), ...);
60 return (std::get<Is>(outputs_).IsReady() && ...);
61 }
62
65 template <size_t kTupleIndex>
66 void PendElement(Context& cx) {
67 auto& output = std::get<kTupleIndex>(outputs_);
68 if (!output.IsReady()) {
69 output = std::get<kTupleIndex>(*futures_).Pend(cx);
70 }
71 }
72
74 template <size_t... Is>
75 Poll<TupleOfOutputRvalues> TakeOutputs(std::index_sequence<Is...>) {
77 std::forward_as_tuple<internal::PendOutputOf<Futures>...>(
78 TakeOutput<Is>()...));
79 }
80
82 template <size_t kTupleIndex>
83 internal::PendOutputOf<
84 typename std::tuple_element<kTupleIndex, std::tuple<Futures...>>::type>&&
85 TakeOutput() {
86 return std::move(std::get<kTupleIndex>(outputs_).value());
87 }
88
89 static_assert(std::conjunction_v<is_future<Futures>...>,
90 "All types in JoinFuture must be Future types");
91 std::optional<std::tuple<Futures...>> futures_;
92 std::tuple<Poll<internal::PendOutputOf<Futures>>...> outputs_;
93};
94
95template <typename... Futures>
96JoinFuture(Futures&&...) -> JoinFuture<Futures...>;
97
103template <typename... Futures>
104constexpr auto Join(Futures&&... futures) {
105 static_assert(std::conjunction_v<is_future<Futures>...>,
106 "All arguments to Join must be Future types");
107 return JoinFuture(std::forward<Futures>(futures)...);
108}
109
111
112} // namespace pw::async2
Definition: context.h:54
Definition: future.h:65
Definition: join.h:26
Definition: poll.h:60
constexpr auto Join(Futures &&... futures)
Definition: join.h:104
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271