C/C++ API Reference
Loading...
Searching...
No Matches
value_future.h
1// Copyright 2025 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_assert/assert.h"
17#include "pw_async2/future.h"
18
19namespace pw::async2 {
20
21template <typename T>
22class ValueProvider;
23template <typename T>
24class BroadcastValueProvider;
25
31template <typename T>
32class ValueFuture : public ListableFutureWithWaker<ValueFuture<T>, T> {
33 public:
35
36 ValueFuture(ValueFuture&& other) noexcept
37 : Base(Base::kMovedFrom), value_(std::move(other.value_)) {
38 Base::MoveFrom(other);
39 }
40
41 ValueFuture& operator=(ValueFuture&& other) noexcept {
42 if (this != &other) {
43 value_ = std::move(other.value_);
44 Base::MoveFrom(other);
45 }
46 return *this;
47 }
48
50 static ValueFuture Resolved(T value) {
51 return ValueFuture(std::in_place, std::move(value));
52 }
53
56 template <typename... Args>
57 static ValueFuture Resolved(Args&&... args) {
58 return ValueFuture(std::in_place, std::forward<Args>(args)...);
59 }
60
61 private:
62 friend Base;
63 friend class ValueProvider<T>;
64 friend class BroadcastValueProvider<T>;
65
66 static constexpr const char kWaitReason[] = "ValueFuture";
67
69 : Base(provider) {}
70 explicit ValueFuture(SingleFutureProvider<ValueFuture<T>>& provider)
71 : Base(provider) {}
72
73 template <typename... Args>
74 explicit ValueFuture(std::in_place_t, Args&&... args)
75 : Base(Base::kReadyForCompletion),
76 value_(std::in_place, std::forward<Args>(args)...) {}
77
78 template <typename... Args>
79 void Resolve(Args&&... args) {
80 {
81 std::lock_guard guard(Base::lock());
82 PW_ASSERT(!value_.has_value());
83 value_.emplace(std::forward<Args>(args)...);
84 this->unlist();
85 }
86 Base::Wake();
87 }
88
89 Poll<T> DoPend(Context&) {
90 std::lock_guard guard(Base::lock());
91 if (value_.has_value()) {
92 T value = std::move(value_.value());
93 value_.reset();
94 return Ready(std::move(value));
95 }
96 return Pending();
97 }
98
99 std::optional<T> value_;
100};
101
104template <>
105class ValueFuture<void>
106 : public ListableFutureWithWaker<ValueFuture<void>, void> {
107 public:
109
110 ValueFuture(ValueFuture&& other) noexcept
111 : Base(Base::kMovedFrom),
112 completed_(std::exchange(other.completed_, true)) {
113 Base::MoveFrom(other);
114 }
115
116 ValueFuture& operator=(ValueFuture&& other) noexcept {
117 completed_ = std::exchange(other.completed_, true);
118 Base::MoveFrom(other);
119 return *this;
120 }
121
122 static ValueFuture Resolved() { return ValueFuture(std::in_place); }
123
124 private:
125 friend Base;
126 friend class ValueProvider<void>;
127 friend class BroadcastValueProvider<void>;
128
129 static constexpr const char kWaitReason[] = "ValueFuture";
130
132 : Base(provider) {}
134 : Base(provider) {}
135
136 explicit ValueFuture(std::in_place_t)
137 : Base(Base::kReadyForCompletion), completed_(true) {}
138
139 void Resolve() {
140 {
141 std::lock_guard guard(Base::lock());
142 PW_ASSERT(!completed_);
143 completed_ = true;
144 this->unlist();
145 }
146 Base::Wake();
147 }
148
149 Poll<> DoPend(Context&) {
150 std::lock_guard guard(Base::lock());
151 if (completed_) {
152 return Ready();
153 }
154 return Pending();
155 }
156
157 bool completed_ = false;
158};
159
162
171template <typename T>
173 public:
177 ValueFuture<T> Get() { return ValueFuture<T>(provider_); }
178
180 template <typename U = T, std::enable_if_t<!std::is_void_v<U>, int> = 0>
181 void Resolve(const U& value) {
182 while (auto future = provider_.Pop()) {
183 future->get().Resolve(value);
184 }
185 }
186
188 template <typename U = T, std::enable_if_t<std::is_void_v<U>, int> = 0>
189 void Resolve() {
190 while (auto future = provider_.Pop()) {
191 future->get().Resolve();
192 }
193 }
194
195 private:
197};
198
205template <typename T>
207 public:
212 PW_ASSERT(!has_future());
213 return ValueFuture<T>(provider_);
214 }
215
220 std::optional<ValueFuture<T>> TryGet() {
221 if (has_future()) {
222 return std::nullopt;
223 }
224 return ValueFuture<T>(provider_);
225 }
226
228 bool has_future() { return provider_.has_future(); }
229
231 template <typename... Args,
232 typename U = T,
233 std::enable_if_t<!std::is_void_v<U>, int> = 0>
234 void Resolve(Args&&... args) {
235 if (auto future = provider_.Take()) {
236 future->get().Resolve(std::forward<Args>(args)...);
237 }
238 }
239
241 template <typename U = T, std::enable_if_t<std::is_void_v<U>, int> = 0>
242 void Resolve() {
243 if (auto future = provider_.Take()) {
244 future->get().Resolve();
245 }
246 }
247
248 private:
250};
251
252} // namespace pw::async2
Definition: value_future.h:172
ValueFuture< T > Get()
Definition: value_future.h:177
void Resolve(const U &value)
Resolves every pending ValueFuture with a copy of the provided value.
Definition: value_future.h:181
void Resolve()
Resolves every pending ValueFuture.
Definition: value_future.h:189
Definition: context.h:54
Definition: future.h:135
Definition: future.h:283
void Wake()
Wakes the task waiting on the future.
Definition: future.h:386
Definition: poll.h:60
Definition: future.h:192
Definition: value_future.h:106
Definition: value_future.h:32
static ValueFuture Resolved(Args &&... args)
Definition: value_future.h:57
static ValueFuture Resolved(T value)
Creates a ValueFuture that is already resolved with the given value.
Definition: value_future.h:50
Definition: value_future.h:206
ValueFuture< T > Get()
Definition: value_future.h:211
void Resolve(Args &&... args)
Resolves the pending ValueFuture by constructing its value in-place.
Definition: value_future.h:234
bool has_future()
Returns true if the provider stores a pending future.
Definition: value_future.h:228
void Resolve()
Resolves the pending ValueFuture.
Definition: value_future.h:242
std::optional< ValueFuture< T > > TryGet()
Definition: value_future.h:220
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255