/* * Copyright (c) 2024 Huawei Device Co., Ltd. * 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. */ #ifndef META_API_FUTURE_H #define META_API_FUTURE_H #include #include #include #include META_BEGIN_NAMESPACE() /** * @brief Callable implementation for continuation functions used with futures. */ template class ContinuationFunction : public IntroduceInterfaces { META_INTERFACE( IntroduceInterfaces, ContinuationFunction, "f4736552-7365-4c8f-bbe9-a065e2c30382"); public: ContinuationFunction(Func func) : func_(BASE_NS::move(func)) {} IAny::Ptr Invoke(const IAny::Ptr& value) override { using Result = BASE_NS::remove_reference_t; if constexpr (!BASE_NS::is_same_v) { return IAny::Ptr(new Any(func_(value))); } else { func_(value); return nullptr; } } private: Func func_; }; /** * @brief Create continuation function from callable entity (e.g. lambda). * The callable entity has to take IAny::Ptr as parameter which is the value from the future. */ template IFutureContinuation::Ptr CreateContinuation(Func func) { return IFutureContinuation::Ptr(new ContinuationFunction(BASE_NS::move(func))); } template struct ContinuationTypedFuntionTypeImpl { using Type = void(Param); }; template<> struct ContinuationTypedFuntionTypeImpl { using Type = void(); }; template using ContinuationTypedFuntionType = typename ContinuationTypedFuntionTypeImpl::Type; template class Future { public: using StateType = IFuture::StateType; Future(IFuture::Ptr fut) : fut_(BASE_NS::move(fut)) {} StateType GetState() const { return fut_ ? fut_->GetState() : IFuture::ABANDONED; } StateType Wait() const { return fut_ ? fut_->Wait() : IFuture::ABANDONED; } StateType WaitFor(const TimeSpan& time) const { return fut_ ? fut_->WaitFor(time) : IFuture::ABANDONED; } IFuture::Ptr Then(const IFutureContinuation::Ptr& func, const BASE_NS::shared_ptr& queue) { return fut_ ? fut_->Then(func, queue) : nullptr; } template> auto Then(Func func, const BASE_NS::shared_ptr& queue) { return Future(fut_->Then(CreateContinuation(func), queue)); } template>> auto Then(Func func, const BASE_NS::shared_ptr& queue, int = 0) { using ReturnType = decltype(func(Type {})); return Future(fut_->Then(CreateContinuation([f = BASE_NS::move(func)](const IAny::Ptr& v) { if (v) { Type value {}; if (v->GetValue(value)) { return f(value); } CORE_LOG_W("Type mismatch for future then"); } if constexpr (!BASE_NS::is_same_v) { return ReturnType {}; } }), queue)); } Type GetResult() const { if (fut_) { return fut_->GetResultOr(Type {}); } return Type {}; } IFuture::Ptr GetFuture() const { return fut_; } operator IFuture::Ptr() const { return fut_; } explicit operator bool() const { return fut_ != nullptr; } private: IFuture::Ptr fut_; }; template Type GetResultOr(const Future& f, NonDeduced_t def) { auto fut = f.GetFuture(); if (fut) { if (auto p = fut->GetResult()) { return GetValue(*p, BASE_NS::move(def)); } } return BASE_NS::move(def); } META_END_NAMESPACE() #endif