blob: 8d82e0ffd20e247791cb9683aa5b8858f58fac37 [file] [log] [blame]
Dominik Laskowskib17c6212022-05-09 09:36:19 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19namespace android::ftl {
20
21template <typename, template <typename> class>
22class Future;
23
24namespace details {
25
26template <typename T>
27struct future_result {
28 using type = T;
29};
30
31template <typename T>
32struct future_result<std::future<T>> {
33 using type = T;
34};
35
36template <typename T>
37struct future_result<std::shared_future<T>> {
38 using type = T;
39};
40
41template <typename T, template <typename> class FutureImpl>
42struct future_result<Future<T, FutureImpl>> {
43 using type = T;
44};
45
46template <typename T>
47using future_result_t = typename future_result<T>::type;
48
49struct ValueTag {};
50
51template <typename, typename T, template <typename> class>
52class BaseFuture;
53
54template <typename Self, typename T>
55class BaseFuture<Self, T, std::future> {
56 using Impl = std::future<T>;
57
58 public:
59 Future<T, std::shared_future> share() {
60 if (T* value = std::get_if<T>(&self())) {
61 return {ValueTag{}, std::move(*value)};
62 }
63
64 return std::get<Impl>(self()).share();
65 }
66
67 protected:
68 T get() {
69 if (T* value = std::get_if<T>(&self())) {
70 return std::move(*value);
71 }
72
73 return std::get<Impl>(self()).get();
74 }
75
Alec Mouri9892aac2023-12-11 21:16:59 +000076 template <class Rep, class Period>
77 std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) const {
78 if (std::holds_alternative<T>(self())) {
79 return std::future_status::ready;
80 }
81
82 return std::get<Impl>(self()).wait_for(timeout_duration);
83 }
84
Dominik Laskowskib17c6212022-05-09 09:36:19 -070085 private:
86 auto& self() { return static_cast<Self&>(*this).future_; }
Alec Mouri9892aac2023-12-11 21:16:59 +000087 const auto& self() const { return static_cast<const Self&>(*this).future_; }
Dominik Laskowskib17c6212022-05-09 09:36:19 -070088};
89
90template <typename Self, typename T>
91class BaseFuture<Self, T, std::shared_future> {
92 using Impl = std::shared_future<T>;
93
94 protected:
95 const T& get() const {
96 if (const T* value = std::get_if<T>(&self())) {
97 return *value;
98 }
99
100 return std::get<Impl>(self()).get();
101 }
102
Alec Mouri9892aac2023-12-11 21:16:59 +0000103 template <class Rep, class Period>
104 std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) const {
105 if (std::holds_alternative<T>(self())) {
106 return std::future_status::ready;
107 }
108
109 return std::get<Impl>(self()).wait_for(timeout_duration);
110 }
111
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700112 private:
113 const auto& self() const { return static_cast<const Self&>(*this).future_; }
114};
115
116} // namespace details
117} // namespace android::ftl