18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "future.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <meta/interface/object_type_info.h>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ciFuture::StateType Future::GetState() const
238bf80f4bSopenharmony_ci{
248bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
258bf80f4bSopenharmony_ci    return state_;
268bf80f4bSopenharmony_ci}
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ciFuture::StateType Future::Wait() const
298bf80f4bSopenharmony_ci{
308bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
318bf80f4bSopenharmony_ci    while (state_ == IFuture::WAITING) {
328bf80f4bSopenharmony_ci        cond_.wait(lock);
338bf80f4bSopenharmony_ci    }
348bf80f4bSopenharmony_ci    return state_;
358bf80f4bSopenharmony_ci}
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ciFuture::StateType Future::WaitFor(const TimeSpan& time) const
388bf80f4bSopenharmony_ci{
398bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
408bf80f4bSopenharmony_ci    while (state_ == IFuture::WAITING) {
418bf80f4bSopenharmony_ci        if (cond_.wait_for(lock, std::chrono::microseconds(time.ToMicroseconds())) == std::cv_status::timeout) {
428bf80f4bSopenharmony_ci            return IFuture::WAITING;
438bf80f4bSopenharmony_ci        }
448bf80f4bSopenharmony_ci    }
458bf80f4bSopenharmony_ci    return state_;
468bf80f4bSopenharmony_ci}
478bf80f4bSopenharmony_ci
488bf80f4bSopenharmony_ciIAny::Ptr Future::GetResult() const
498bf80f4bSopenharmony_ci{
508bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
518bf80f4bSopenharmony_ci    while (state_ == IFuture::WAITING) {
528bf80f4bSopenharmony_ci        cond_.wait(lock);
538bf80f4bSopenharmony_ci    }
548bf80f4bSopenharmony_ci    return result_;
558bf80f4bSopenharmony_ci}
568bf80f4bSopenharmony_ci
578bf80f4bSopenharmony_ciIFuture::Ptr Future::Then(const IFutureContinuation::Ptr& func, const ITaskQueue::Ptr& queue)
588bf80f4bSopenharmony_ci{
598bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
608bf80f4bSopenharmony_ci    IFuture::Ptr result;
618bf80f4bSopenharmony_ci    if (state_ == IFuture::ABANDONED) {
628bf80f4bSopenharmony_ci        BASE_NS::shared_ptr<Future> f(new Future);
638bf80f4bSopenharmony_ci        f->SetAbandoned();
648bf80f4bSopenharmony_ci        result = BASE_NS::move(f);
658bf80f4bSopenharmony_ci    } else {
668bf80f4bSopenharmony_ci        ContinuationData d { queue == nullptr, queue };
678bf80f4bSopenharmony_ci        d.continuation.reset(new ContinuationQueueTask(func));
688bf80f4bSopenharmony_ci        result = d.continuation->GetFuture();
698bf80f4bSopenharmony_ci        continuations_.push_back(BASE_NS::move(d));
708bf80f4bSopenharmony_ci        if (state_ == IFuture::COMPLETED) {
718bf80f4bSopenharmony_ci            ActivateContinuation(lock);
728bf80f4bSopenharmony_ci        }
738bf80f4bSopenharmony_ci    }
748bf80f4bSopenharmony_ci    return result;
758bf80f4bSopenharmony_ci}
768bf80f4bSopenharmony_ci
778bf80f4bSopenharmony_civoid Future::Cancel()
788bf80f4bSopenharmony_ci{
798bf80f4bSopenharmony_ci    bool notify = false;
808bf80f4bSopenharmony_ci    ITaskQueue::Token token {};
818bf80f4bSopenharmony_ci    {
828bf80f4bSopenharmony_ci        std::unique_lock lock { mutex_ };
838bf80f4bSopenharmony_ci        if (state_ != IFuture::COMPLETED) {
848bf80f4bSopenharmony_ci            notify = true;
858bf80f4bSopenharmony_ci            token = token_;
868bf80f4bSopenharmony_ci            token_ = {};
878bf80f4bSopenharmony_ci            for (auto&& v : continuations_) {
888bf80f4bSopenharmony_ci                v.continuation->SetAbandoned();
898bf80f4bSopenharmony_ci            }
908bf80f4bSopenharmony_ci            continuations_.clear();
918bf80f4bSopenharmony_ci            state_ = IFuture::ABANDONED;
928bf80f4bSopenharmony_ci        }
938bf80f4bSopenharmony_ci    }
948bf80f4bSopenharmony_ci    if (token) {
958bf80f4bSopenharmony_ci        if (auto q = queue_.lock()) {
968bf80f4bSopenharmony_ci            q->CancelTask(token);
978bf80f4bSopenharmony_ci        }
988bf80f4bSopenharmony_ci    }
998bf80f4bSopenharmony_ci    if (notify) {
1008bf80f4bSopenharmony_ci        cond_.notify_all();
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci}
1038bf80f4bSopenharmony_ci
1048bf80f4bSopenharmony_civoid Future::ActivateContinuation(const ContinuationData& d, const IAny::Ptr& result)
1058bf80f4bSopenharmony_ci{
1068bf80f4bSopenharmony_ci    if (auto q = d.queue.lock()) {
1078bf80f4bSopenharmony_ci        d.continuation->SetParam(result);
1088bf80f4bSopenharmony_ci        auto token = q->AddTask(d.continuation);
1098bf80f4bSopenharmony_ci        d.continuation->SetQueueInfo(q, token);
1108bf80f4bSopenharmony_ci    } else if (d.runInline) {
1118bf80f4bSopenharmony_ci        d.continuation->SetParam(result);
1128bf80f4bSopenharmony_ci        d.continuation->Invoke();
1138bf80f4bSopenharmony_ci    } else {
1148bf80f4bSopenharmony_ci        d.continuation->SetAbandoned();
1158bf80f4bSopenharmony_ci    }
1168bf80f4bSopenharmony_ci}
1178bf80f4bSopenharmony_ci
1188bf80f4bSopenharmony_civoid Future::ActivateContinuation(std::unique_lock<std::mutex>& lock)
1198bf80f4bSopenharmony_ci{
1208bf80f4bSopenharmony_ci    BASE_NS::vector<ContinuationData> cdata = BASE_NS::move(continuations_);
1218bf80f4bSopenharmony_ci    auto result = result_;
1228bf80f4bSopenharmony_ci    lock.unlock();
1238bf80f4bSopenharmony_ci    for (auto&& v : cdata) {
1248bf80f4bSopenharmony_ci        ActivateContinuation(v, result);
1258bf80f4bSopenharmony_ci    }
1268bf80f4bSopenharmony_ci}
1278bf80f4bSopenharmony_ci
1288bf80f4bSopenharmony_civoid Future::SetResult(IAny::Ptr p)
1298bf80f4bSopenharmony_ci{
1308bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
1318bf80f4bSopenharmony_ci    token_ = {};
1328bf80f4bSopenharmony_ci    if (state_ == IFuture::WAITING) {
1338bf80f4bSopenharmony_ci        result_ = BASE_NS::move(p);
1348bf80f4bSopenharmony_ci        state_ = IFuture::COMPLETED;
1358bf80f4bSopenharmony_ci        ActivateContinuation(lock);
1368bf80f4bSopenharmony_ci        cond_.notify_all();
1378bf80f4bSopenharmony_ci    }
1388bf80f4bSopenharmony_ci}
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_civoid Future::SetAbandoned()
1418bf80f4bSopenharmony_ci{
1428bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
1438bf80f4bSopenharmony_ci    if (state_ == IFuture::WAITING) {
1448bf80f4bSopenharmony_ci        state_ = IFuture::ABANDONED;
1458bf80f4bSopenharmony_ci        token_ = {};
1468bf80f4bSopenharmony_ci
1478bf80f4bSopenharmony_ci        for (auto&& v : continuations_) {
1488bf80f4bSopenharmony_ci            v.continuation->SetAbandoned();
1498bf80f4bSopenharmony_ci        }
1508bf80f4bSopenharmony_ci        continuations_.clear();
1518bf80f4bSopenharmony_ci        cond_.notify_all();
1528bf80f4bSopenharmony_ci    }
1538bf80f4bSopenharmony_ci}
1548bf80f4bSopenharmony_ci
1558bf80f4bSopenharmony_civoid Future::SetQueueInfo(const ITaskQueue::Ptr& queue, ITaskQueue::Token token)
1568bf80f4bSopenharmony_ci{
1578bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
1588bf80f4bSopenharmony_ci    if (state_ == IFuture::WAITING) {
1598bf80f4bSopenharmony_ci        queue_ = queue;
1608bf80f4bSopenharmony_ci        token_ = token;
1618bf80f4bSopenharmony_ci    }
1628bf80f4bSopenharmony_ci}
1638bf80f4bSopenharmony_ci
1648bf80f4bSopenharmony_ciPromise::~Promise()
1658bf80f4bSopenharmony_ci{
1668bf80f4bSopenharmony_ci    SetAbandoned();
1678bf80f4bSopenharmony_ci}
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_civoid Promise::Set(const IAny::Ptr& res)
1708bf80f4bSopenharmony_ci{
1718bf80f4bSopenharmony_ci    if (future_) {
1728bf80f4bSopenharmony_ci        future_->SetResult(res);
1738bf80f4bSopenharmony_ci        future_ = nullptr;
1748bf80f4bSopenharmony_ci    }
1758bf80f4bSopenharmony_ci}
1768bf80f4bSopenharmony_ci
1778bf80f4bSopenharmony_civoid Promise::SetAbandoned()
1788bf80f4bSopenharmony_ci{
1798bf80f4bSopenharmony_ci    if (future_) {
1808bf80f4bSopenharmony_ci        future_->SetAbandoned();
1818bf80f4bSopenharmony_ci        future_ = nullptr;
1828bf80f4bSopenharmony_ci    }
1838bf80f4bSopenharmony_ci}
1848bf80f4bSopenharmony_ci
1858bf80f4bSopenharmony_ciIFuture::Ptr Promise::GetFuture()
1868bf80f4bSopenharmony_ci{
1878bf80f4bSopenharmony_ci    if (!future_) {
1888bf80f4bSopenharmony_ci        future_.reset(new Future);
1898bf80f4bSopenharmony_ci    }
1908bf80f4bSopenharmony_ci    return future_;
1918bf80f4bSopenharmony_ci}
1928bf80f4bSopenharmony_ci
1938bf80f4bSopenharmony_civoid Promise::SetQueueInfo(const ITaskQueue::Ptr& queue, ITaskQueue::Token token)
1948bf80f4bSopenharmony_ci{
1958bf80f4bSopenharmony_ci    if (future_) {
1968bf80f4bSopenharmony_ci        future_->SetQueueInfo(queue, token);
1978bf80f4bSopenharmony_ci    }
1988bf80f4bSopenharmony_ci}
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_cinamespace Internal {
2018bf80f4bSopenharmony_ci
2028bf80f4bSopenharmony_ciIObjectFactory::Ptr GetPromiseFactory()
2038bf80f4bSopenharmony_ci{
2048bf80f4bSopenharmony_ci    return Promise::GetFactory();
2058bf80f4bSopenharmony_ci}
2068bf80f4bSopenharmony_ci
2078bf80f4bSopenharmony_ci} // namespace Internal
2088bf80f4bSopenharmony_ci
2098bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
210