1 /* 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 19 namespace android::ftl { 20 21 template <typename, template <typename> class> 22 class Future; 23 24 namespace details { 25 26 template <typename T> 27 struct future_result { 28 using type = T; 29 }; 30 31 template <typename T> 32 struct future_result<std::future<T>> { 33 using type = T; 34 }; 35 36 template <typename T> 37 struct future_result<std::shared_future<T>> { 38 using type = T; 39 }; 40 41 template <typename T, template <typename> class FutureImpl> 42 struct future_result<Future<T, FutureImpl>> { 43 using type = T; 44 }; 45 46 template <typename T> 47 using future_result_t = typename future_result<T>::type; 48 49 struct ValueTag {}; 50 51 template <typename, typename T, template <typename> class> 52 class BaseFuture; 53 54 template <typename Self, typename T> 55 class 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 76 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 85 private: 86 auto& self() { return static_cast<Self&>(*this).future_; } 87 const auto& self() const { return static_cast<const Self&>(*this).future_; } 88 }; 89 90 template <typename Self, typename T> 91 class 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 103 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 112 private: 113 const auto& self() const { return static_cast<const Self&>(*this).future_; } 114 }; 115 116 } // namespace details 117 } // namespace android::ftl 118