1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker /**
18*14675a02SAndroid Build Coastguard Worker * This file provides a pair of types Future<T> (a value to wait for) and
19*14675a02SAndroid Build Coastguard Worker * Promise<T> (allows providing the value for an associated future).
20*14675a02SAndroid Build Coastguard Worker *
21*14675a02SAndroid Build Coastguard Worker * These serve the same purpose as std::future and std::promise, but with a few
22*14675a02SAndroid Build Coastguard Worker * differences:
23*14675a02SAndroid Build Coastguard Worker * - They do not represent exceptions (i.e. std::promise::set_exception).
24*14675a02SAndroid Build Coastguard Worker * Consider representing failure conditions with StatusOr or std::variant
25*14675a02SAndroid Build Coastguard Worker * - They do not throw future-related exceptions (e.g. std::future::get throws
26*14675a02SAndroid Build Coastguard Worker * if the promise was 'abandoned'; this one indicates that with a value).
27*14675a02SAndroid Build Coastguard Worker * - There is no integration with std::async etc.
28*14675a02SAndroid Build Coastguard Worker * - They use absl::Duration / absl::Time for waiting with a timeout.
29*14675a02SAndroid Build Coastguard Worker * - They are created as a pair (vs. std::promise::get_future(), which throws
30*14675a02SAndroid Build Coastguard Worker * an exception if called twice).
31*14675a02SAndroid Build Coastguard Worker * - Setting (promise) and taking (future) require rvalues (you might need to
32*14675a02SAndroid Build Coastguard Worker * use std::move). This is to indicate that these are 'consuming' operations
33*14675a02SAndroid Build Coastguard Worker * (to humans and static analysis tools).
34*14675a02SAndroid Build Coastguard Worker */
35*14675a02SAndroid Build Coastguard Worker
36*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_FUTURE_H_
37*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_FUTURE_H_
38*14675a02SAndroid Build Coastguard Worker
39*14675a02SAndroid Build Coastguard Worker #include <memory>
40*14675a02SAndroid Build Coastguard Worker #include <optional>
41*14675a02SAndroid Build Coastguard Worker #include <tuple>
42*14675a02SAndroid Build Coastguard Worker #include <variant>
43*14675a02SAndroid Build Coastguard Worker
44*14675a02SAndroid Build Coastguard Worker #include "absl/base/macros.h"
45*14675a02SAndroid Build Coastguard Worker #include "absl/synchronization/notification.h"
46*14675a02SAndroid Build Coastguard Worker #include "fcp/base/meta.h"
47*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
48*14675a02SAndroid Build Coastguard Worker #include "fcp/base/move_to_lambda.h"
49*14675a02SAndroid Build Coastguard Worker #include "fcp/base/scheduler.h"
50*14675a02SAndroid Build Coastguard Worker #include "fcp/base/unique_value.h"
51*14675a02SAndroid Build Coastguard Worker
52*14675a02SAndroid Build Coastguard Worker namespace fcp {
53*14675a02SAndroid Build Coastguard Worker
54*14675a02SAndroid Build Coastguard Worker // Since fcp::Promise is already defined by the reactive streams library
55*14675a02SAndroid Build Coastguard Worker // (fcp/reactive/), we'll define fcp::thread::{Promise, Future}.
56*14675a02SAndroid Build Coastguard Worker namespace thread {
57*14675a02SAndroid Build Coastguard Worker
58*14675a02SAndroid Build Coastguard Worker // Forward declarations; see doc comments below
59*14675a02SAndroid Build Coastguard Worker template <typename T>
60*14675a02SAndroid Build Coastguard Worker class Future;
61*14675a02SAndroid Build Coastguard Worker template <typename T>
62*14675a02SAndroid Build Coastguard Worker class Promise;
63*14675a02SAndroid Build Coastguard Worker
64*14675a02SAndroid Build Coastguard Worker template <typename T>
65*14675a02SAndroid Build Coastguard Worker struct FuturePair {
66*14675a02SAndroid Build Coastguard Worker Promise<T> promise;
67*14675a02SAndroid Build Coastguard Worker Future<T> future;
68*14675a02SAndroid Build Coastguard Worker };
69*14675a02SAndroid Build Coastguard Worker
70*14675a02SAndroid Build Coastguard Worker namespace future_internal {
71*14675a02SAndroid Build Coastguard Worker // We want Promise and Future to be created only as a pair, with MakeFuture.
72*14675a02SAndroid Build Coastguard Worker // This type is given permission to construct them.
73*14675a02SAndroid Build Coastguard Worker struct Maker {
74*14675a02SAndroid Build Coastguard Worker template <typename T>
75*14675a02SAndroid Build Coastguard Worker static FuturePair<T> Make();
76*14675a02SAndroid Build Coastguard Worker };
77*14675a02SAndroid Build Coastguard Worker
78*14675a02SAndroid Build Coastguard Worker // Common state of a Promise / Future pair. Destructed when *both* the promise
79*14675a02SAndroid Build Coastguard Worker // and future are gone.
80*14675a02SAndroid Build Coastguard Worker //
81*14675a02SAndroid Build Coastguard Worker // States: NotSet, Set, Taken
82*14675a02SAndroid Build Coastguard Worker // Transitions:
83*14675a02SAndroid Build Coastguard Worker // NotSet -> Set: When a value is provided (std::nullopt indicates an
84*14675a02SAndroid Build Coastguard Worker // abandoned promise). *Before* ready_ is signalled.
85*14675a02SAndroid Build Coastguard Worker // Set -> Taken: When a future takes a value. *After* ready_ is signalled.
86*14675a02SAndroid Build Coastguard Worker template <typename T>
87*14675a02SAndroid Build Coastguard Worker class FutureState {
88*14675a02SAndroid Build Coastguard Worker public:
89*14675a02SAndroid Build Coastguard Worker bool Wait(absl::Duration timeout) const;
90*14675a02SAndroid Build Coastguard Worker std::optional<T> Take();
91*14675a02SAndroid Build Coastguard Worker void Set(std::optional<T> val);
92*14675a02SAndroid Build Coastguard Worker
93*14675a02SAndroid Build Coastguard Worker private:
94*14675a02SAndroid Build Coastguard Worker enum class State { kNotSet, kSet, kTaken };
95*14675a02SAndroid Build Coastguard Worker
96*14675a02SAndroid Build Coastguard Worker absl::Notification ready_;
97*14675a02SAndroid Build Coastguard Worker State state_ = State::kNotSet;
98*14675a02SAndroid Build Coastguard Worker std::optional<T> value_;
99*14675a02SAndroid Build Coastguard Worker };
100*14675a02SAndroid Build Coastguard Worker
101*14675a02SAndroid Build Coastguard Worker // A Future and Promise share a single FutureState. That is, FutureState
102*14675a02SAndroid Build Coastguard Worker // is ref-counted, with two initial refs (no additional refs can be created,
103*14675a02SAndroid Build Coastguard Worker // since Future and Promise are move-only). So, we define FutureStateRef as a
104*14675a02SAndroid Build Coastguard Worker // move-only std::shared_ptr.
105*14675a02SAndroid Build Coastguard Worker template <typename T>
106*14675a02SAndroid Build Coastguard Worker using FutureStateRef = UniqueValue<std::shared_ptr<FutureState<T>>>;
107*14675a02SAndroid Build Coastguard Worker } // namespace future_internal
108*14675a02SAndroid Build Coastguard Worker
109*14675a02SAndroid Build Coastguard Worker /**
110*14675a02SAndroid Build Coastguard Worker * Allows waiting for and retrieving a value (provided eventually by a paired
111*14675a02SAndroid Build Coastguard Worker * Promise).
112*14675a02SAndroid Build Coastguard Worker *
113*14675a02SAndroid Build Coastguard Worker * If the paired Promise is 'abandoned' (destructed without having a value set),
114*14675a02SAndroid Build Coastguard Worker * then the Future's value is std::nullopt.
115*14675a02SAndroid Build Coastguard Worker */
116*14675a02SAndroid Build Coastguard Worker template <typename T>
117*14675a02SAndroid Build Coastguard Worker class Future {
118*14675a02SAndroid Build Coastguard Worker public:
119*14675a02SAndroid Build Coastguard Worker Future(Future&&) = default;
120*14675a02SAndroid Build Coastguard Worker Future& operator=(Future&&) = default;
121*14675a02SAndroid Build Coastguard Worker
122*14675a02SAndroid Build Coastguard Worker /**
123*14675a02SAndroid Build Coastguard Worker * Retrieves the future value, waiting until it is available.
124*14675a02SAndroid Build Coastguard Worker * Taking from a future *consumes* it, and so requires an rvalue. To take
125*14675a02SAndroid Build Coastguard Worker * from a Future<T> f:
126*14675a02SAndroid Build Coastguard Worker * std::move(f).Take()
127*14675a02SAndroid Build Coastguard Worker *
128*14675a02SAndroid Build Coastguard Worker * If the paired promise is 'abandoned' (destructed before a real value is
129*14675a02SAndroid Build Coastguard Worker * provided), the value is std::nullopt.
130*14675a02SAndroid Build Coastguard Worker */
131*14675a02SAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT
Take()132*14675a02SAndroid Build Coastguard Worker std::optional<T> Take() && {
133*14675a02SAndroid Build Coastguard Worker future_internal::FutureStateRef<T> state = std::move(state_);
134*14675a02SAndroid Build Coastguard Worker FCP_CHECK(state.has_value());
135*14675a02SAndroid Build Coastguard Worker return (*state)->Take();
136*14675a02SAndroid Build Coastguard Worker }
137*14675a02SAndroid Build Coastguard Worker
138*14675a02SAndroid Build Coastguard Worker /**
139*14675a02SAndroid Build Coastguard Worker * Waits for the value to become available, with a timeout. Unlike Take(),
140*14675a02SAndroid Build Coastguard Worker * this does *not* consume the value.
141*14675a02SAndroid Build Coastguard Worker *
142*14675a02SAndroid Build Coastguard Worker * Returns a bool indicating if the value is available (if so, Take() will
143*14675a02SAndroid Build Coastguard Worker * return immediately).
144*14675a02SAndroid Build Coastguard Worker */
145*14675a02SAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT
Wait(absl::Duration timeout)146*14675a02SAndroid Build Coastguard Worker bool Wait(absl::Duration timeout) const {
147*14675a02SAndroid Build Coastguard Worker FCP_CHECK(state_.has_value());
148*14675a02SAndroid Build Coastguard Worker return (*state_)->Wait(timeout);
149*14675a02SAndroid Build Coastguard Worker }
150*14675a02SAndroid Build Coastguard Worker
151*14675a02SAndroid Build Coastguard Worker private:
152*14675a02SAndroid Build Coastguard Worker friend struct future_internal::Maker;
153*14675a02SAndroid Build Coastguard Worker
Future(future_internal::FutureStateRef<T> state)154*14675a02SAndroid Build Coastguard Worker explicit Future(future_internal::FutureStateRef<T> state)
155*14675a02SAndroid Build Coastguard Worker : state_(std::move(state)) {}
156*14675a02SAndroid Build Coastguard Worker
157*14675a02SAndroid Build Coastguard Worker future_internal::FutureStateRef<T> state_;
158*14675a02SAndroid Build Coastguard Worker };
159*14675a02SAndroid Build Coastguard Worker
160*14675a02SAndroid Build Coastguard Worker /**
161*14675a02SAndroid Build Coastguard Worker * Allows providing a value to satisfy a paired Future.
162*14675a02SAndroid Build Coastguard Worker *
163*14675a02SAndroid Build Coastguard Worker * If this Promise is 'abandoned' (destructed without having a value set),
164*14675a02SAndroid Build Coastguard Worker * then the Future gets the value std::nullopt.
165*14675a02SAndroid Build Coastguard Worker */
166*14675a02SAndroid Build Coastguard Worker template <typename T>
167*14675a02SAndroid Build Coastguard Worker class Promise {
168*14675a02SAndroid Build Coastguard Worker public:
169*14675a02SAndroid Build Coastguard Worker Promise(Promise&&) = default;
170*14675a02SAndroid Build Coastguard Worker Promise& operator=(Promise&&) = default;
171*14675a02SAndroid Build Coastguard Worker
~Promise()172*14675a02SAndroid Build Coastguard Worker ~Promise() {
173*14675a02SAndroid Build Coastguard Worker if (state_.has_value()) {
174*14675a02SAndroid Build Coastguard Worker // Abandoned
175*14675a02SAndroid Build Coastguard Worker (*state_)->Set(std::nullopt);
176*14675a02SAndroid Build Coastguard Worker }
177*14675a02SAndroid Build Coastguard Worker }
178*14675a02SAndroid Build Coastguard Worker
179*14675a02SAndroid Build Coastguard Worker /**
180*14675a02SAndroid Build Coastguard Worker * Provides a value to the paired Future. Setting a promise *consumes* it,
181*14675a02SAndroid Build Coastguard Worker * and so requires an rvalue. To set a Promise<T> p:
182*14675a02SAndroid Build Coastguard Worker * std::move(p).Set(...)
183*14675a02SAndroid Build Coastguard Worker */
Set(T value)184*14675a02SAndroid Build Coastguard Worker void Set(T value) && {
185*14675a02SAndroid Build Coastguard Worker future_internal::FutureStateRef<T> state = std::move(state_);
186*14675a02SAndroid Build Coastguard Worker FCP_CHECK(state.has_value());
187*14675a02SAndroid Build Coastguard Worker (*state)->Set(std::move(value));
188*14675a02SAndroid Build Coastguard Worker }
189*14675a02SAndroid Build Coastguard Worker
190*14675a02SAndroid Build Coastguard Worker private:
191*14675a02SAndroid Build Coastguard Worker friend struct future_internal::Maker;
192*14675a02SAndroid Build Coastguard Worker
Promise(future_internal::FutureStateRef<T> state)193*14675a02SAndroid Build Coastguard Worker explicit Promise(future_internal::FutureStateRef<T> state)
194*14675a02SAndroid Build Coastguard Worker : state_(std::move(state)) {}
195*14675a02SAndroid Build Coastguard Worker
196*14675a02SAndroid Build Coastguard Worker future_internal::FutureStateRef<T> state_;
197*14675a02SAndroid Build Coastguard Worker };
198*14675a02SAndroid Build Coastguard Worker
199*14675a02SAndroid Build Coastguard Worker /** Creates a paired Future and Promise. */
200*14675a02SAndroid Build Coastguard Worker template <typename T>
MakeFuture()201*14675a02SAndroid Build Coastguard Worker FuturePair<T> MakeFuture() {
202*14675a02SAndroid Build Coastguard Worker return future_internal::Maker::Make<T>();
203*14675a02SAndroid Build Coastguard Worker }
204*14675a02SAndroid Build Coastguard Worker
205*14675a02SAndroid Build Coastguard Worker /**
206*14675a02SAndroid Build Coastguard Worker * Schedules a task which calls a function computing a value. Returns a future
207*14675a02SAndroid Build Coastguard Worker * to wait for and access the value once it is computed.
208*14675a02SAndroid Build Coastguard Worker */
209*14675a02SAndroid Build Coastguard Worker template <typename T>
ScheduleFuture(Scheduler * scheduler,std::function<T ()> func)210*14675a02SAndroid Build Coastguard Worker Future<T> ScheduleFuture(Scheduler* scheduler, std::function<T()> func) {
211*14675a02SAndroid Build Coastguard Worker thread::FuturePair<T> p = thread::MakeFuture<T>();
212*14675a02SAndroid Build Coastguard Worker MoveToLambdaWrapper<thread::Promise<T>> promise_capture =
213*14675a02SAndroid Build Coastguard Worker MoveToLambda(std::move(p.promise));
214*14675a02SAndroid Build Coastguard Worker // Lambda is stateful (since the promise is consumed). This is okay, since
215*14675a02SAndroid Build Coastguard Worker // it should only be called once.
216*14675a02SAndroid Build Coastguard Worker scheduler->Schedule([promise_capture, func]() mutable {
217*14675a02SAndroid Build Coastguard Worker std::move(*promise_capture).Set(func());
218*14675a02SAndroid Build Coastguard Worker });
219*14675a02SAndroid Build Coastguard Worker
220*14675a02SAndroid Build Coastguard Worker return std::move(p.future);
221*14675a02SAndroid Build Coastguard Worker }
222*14675a02SAndroid Build Coastguard Worker
223*14675a02SAndroid Build Coastguard Worker namespace future_internal {
224*14675a02SAndroid Build Coastguard Worker
225*14675a02SAndroid Build Coastguard Worker template <typename T>
Make()226*14675a02SAndroid Build Coastguard Worker FuturePair<T> Maker::Make() {
227*14675a02SAndroid Build Coastguard Worker std::shared_ptr<FutureState<T>> state = std::make_shared<FutureState<T>>();
228*14675a02SAndroid Build Coastguard Worker
229*14675a02SAndroid Build Coastguard Worker auto promise_ref = FutureStateRef<T>(state);
230*14675a02SAndroid Build Coastguard Worker // Note that we use std::move this time, to avoid ref-count churn.
231*14675a02SAndroid Build Coastguard Worker auto future_ref = FutureStateRef<T>(std::move(state));
232*14675a02SAndroid Build Coastguard Worker return {Promise<T>(std::move(promise_ref)), Future<T>(std::move(future_ref))};
233*14675a02SAndroid Build Coastguard Worker }
234*14675a02SAndroid Build Coastguard Worker
235*14675a02SAndroid Build Coastguard Worker template <typename T>
Wait(absl::Duration timeout)236*14675a02SAndroid Build Coastguard Worker bool FutureState<T>::Wait(absl::Duration timeout) const {
237*14675a02SAndroid Build Coastguard Worker return ready_.WaitForNotificationWithTimeout(timeout);
238*14675a02SAndroid Build Coastguard Worker }
239*14675a02SAndroid Build Coastguard Worker
240*14675a02SAndroid Build Coastguard Worker template <typename T>
Set(std::optional<T> val)241*14675a02SAndroid Build Coastguard Worker void FutureState<T>::Set(std::optional<T> val) {
242*14675a02SAndroid Build Coastguard Worker FCP_CHECK(!ready_.HasBeenNotified())
243*14675a02SAndroid Build Coastguard Worker << "Attempted to set a FutureState which has already been notified";
244*14675a02SAndroid Build Coastguard Worker // Not notified => value_ has *not* been set, and the Promise has exclusive
245*14675a02SAndroid Build Coastguard Worker // access (no atomics or locks needed below).
246*14675a02SAndroid Build Coastguard Worker switch (state_) {
247*14675a02SAndroid Build Coastguard Worker case State::kNotSet:
248*14675a02SAndroid Build Coastguard Worker state_ = State::kSet;
249*14675a02SAndroid Build Coastguard Worker value_ = std::move(val);
250*14675a02SAndroid Build Coastguard Worker // This has release semantics; stores to state_ and value_ will be visible
251*14675a02SAndroid Build Coastguard Worker // to whomever sees that the notification.
252*14675a02SAndroid Build Coastguard Worker ready_.Notify();
253*14675a02SAndroid Build Coastguard Worker return;
254*14675a02SAndroid Build Coastguard Worker case State::kSet:
255*14675a02SAndroid Build Coastguard Worker FCP_CHECK(false) << "FutureState has been notified, so state_ should be "
256*14675a02SAndroid Build Coastguard Worker "kTaken or kSet";
257*14675a02SAndroid Build Coastguard Worker abort(); // Compiler thinks FCP_CHECK(false) might return
258*14675a02SAndroid Build Coastguard Worker case State::kTaken:
259*14675a02SAndroid Build Coastguard Worker FCP_CHECK(false) << "FutureState has already been taken from";
260*14675a02SAndroid Build Coastguard Worker abort(); // Compiler thinks FCP_CHECK(false) might return
261*14675a02SAndroid Build Coastguard Worker }
262*14675a02SAndroid Build Coastguard Worker }
263*14675a02SAndroid Build Coastguard Worker
264*14675a02SAndroid Build Coastguard Worker template <typename T>
Take()265*14675a02SAndroid Build Coastguard Worker std::optional<T> FutureState<T>::Take() {
266*14675a02SAndroid Build Coastguard Worker ready_.WaitForNotification();
267*14675a02SAndroid Build Coastguard Worker // Notified => value_ has been set, and exclusive access has been transferred
268*14675a02SAndroid Build Coastguard Worker // from the Promise to the Future (no atomics or locks needed below).
269*14675a02SAndroid Build Coastguard Worker switch (state_) {
270*14675a02SAndroid Build Coastguard Worker case State::kSet:
271*14675a02SAndroid Build Coastguard Worker state_ = State::kTaken;
272*14675a02SAndroid Build Coastguard Worker // value_.has_value() will still be set, but we won't read it again
273*14675a02SAndroid Build Coastguard Worker // in the kTaken state.
274*14675a02SAndroid Build Coastguard Worker return std::move(value_);
275*14675a02SAndroid Build Coastguard Worker case State::kNotSet:
276*14675a02SAndroid Build Coastguard Worker FCP_CHECK(false) << "FutureState has been notified, so state_ should be "
277*14675a02SAndroid Build Coastguard Worker "kTaken or kSet";
278*14675a02SAndroid Build Coastguard Worker abort(); // Compiler thinks FCP_CHECK(false) might return
279*14675a02SAndroid Build Coastguard Worker case State::kTaken:
280*14675a02SAndroid Build Coastguard Worker FCP_CHECK(false) << "FutureState has already been taken from";
281*14675a02SAndroid Build Coastguard Worker abort(); // Compiler thinks FCP_CHECK(false) might return
282*14675a02SAndroid Build Coastguard Worker }
283*14675a02SAndroid Build Coastguard Worker }
284*14675a02SAndroid Build Coastguard Worker
285*14675a02SAndroid Build Coastguard Worker } // namespace future_internal
286*14675a02SAndroid Build Coastguard Worker
287*14675a02SAndroid Build Coastguard Worker } // namespace thread
288*14675a02SAndroid Build Coastguard Worker } // namespace fcp
289*14675a02SAndroid Build Coastguard Worker
290*14675a02SAndroid Build Coastguard Worker #endif // FCP_BASE_FUTURE_H_
291