/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once namespace android::ftl { template class> class Future; namespace details { template struct future_result { using type = T; }; template struct future_result> { using type = T; }; template struct future_result> { using type = T; }; template class FutureImpl> struct future_result> { using type = T; }; template using future_result_t = typename future_result::type; struct ValueTag {}; template class> class BaseFuture; template class BaseFuture { using Impl = std::future; public: Future share() { if (T* value = std::get_if(&self())) { return {ValueTag{}, std::move(*value)}; } return std::get(self()).share(); } protected: T get() { if (T* value = std::get_if(&self())) { return std::move(*value); } return std::get(self()).get(); } template std::future_status wait_for(const std::chrono::duration& timeout_duration) const { if (std::holds_alternative(self())) { return std::future_status::ready; } return std::get(self()).wait_for(timeout_duration); } private: auto& self() { return static_cast(*this).future_; } const auto& self() const { return static_cast(*this).future_; } }; template class BaseFuture { using Impl = std::shared_future; protected: const T& get() const { if (const T* value = std::get_if(&self())) { return *value; } return std::get(self()).get(); } template std::future_status wait_for(const std::chrono::duration& timeout_duration) const { if (std::holds_alternative(self())) { return std::future_status::ready; } return std::get(self()).wait_for(timeout_duration); } private: const auto& self() const { return static_cast(*this).future_; } }; } // namespace details } // namespace android::ftl