14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License.
54d6c458bSopenharmony_ci * You may obtain a copy of the License at
64d6c458bSopenharmony_ci *
74d6c458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84d6c458bSopenharmony_ci *
94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and
134d6c458bSopenharmony_ci * limitations under the License.
144d6c458bSopenharmony_ci */
154d6c458bSopenharmony_ci#include "sequence_runner.h"
164d6c458bSopenharmony_ci
174d6c458bSopenharmony_ci#include <cinttypes>
184d6c458bSopenharmony_ci
194d6c458bSopenharmony_ci#include "helper/error_helper.h"
204d6c458bSopenharmony_ci#include "helper/napi_helper.h"
214d6c458bSopenharmony_ci#include "helper/object_helper.h"
224d6c458bSopenharmony_ci#include "task_manager.h"
234d6c458bSopenharmony_ci#include "tools/log.h"
244d6c458bSopenharmony_ci
254d6c458bSopenharmony_cinamespace Commonlibrary::Concurrent::TaskPoolModule {
264d6c458bSopenharmony_ciusing namespace Commonlibrary::Concurrent::Common::Helper;
274d6c458bSopenharmony_cistatic constexpr char EXECUTE_STR[] = "execute";
284d6c458bSopenharmony_cistatic constexpr char SEQ_RUNNER_ID_STR[] = "seqRunnerId";
294d6c458bSopenharmony_ci
304d6c458bSopenharmony_civoid SequenceRunner::SeqRunnerConstructorInner(napi_env env, napi_value &thisVar, SequenceRunner *seqRunner)
314d6c458bSopenharmony_ci{
324d6c458bSopenharmony_ci    // update seqRunner.seqRunnerId
334d6c458bSopenharmony_ci    uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
344d6c458bSopenharmony_ci    napi_value napiSeqRunnerId = NapiHelper::CreateUint64(env, seqRunnerId);
354d6c458bSopenharmony_ci    TaskGroupManager::GetInstance().StoreSequenceRunner(seqRunnerId, seqRunner);
364d6c458bSopenharmony_ci    napi_property_descriptor properties[] = {
374d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY(SEQ_RUNNER_ID_STR, napiSeqRunnerId),
384d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION(EXECUTE_STR, Execute),
394d6c458bSopenharmony_ci    };
404d6c458bSopenharmony_ci    napi_define_properties(env, thisVar, sizeof(properties) / sizeof(properties[0]), properties);
414d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: construct seqRunner name is %{public}s, seqRunnerid %{public}s.",
424d6c458bSopenharmony_ci               seqRunner->seqName_.c_str(), std::to_string(seqRunnerId).c_str());
434d6c458bSopenharmony_ci
444d6c458bSopenharmony_ci    seqRunner->seqRunnerId_ = seqRunnerId;
454d6c458bSopenharmony_ci    napi_wrap(env, thisVar, seqRunner, SequenceRunnerDestructor, nullptr, nullptr);
464d6c458bSopenharmony_ci}
474d6c458bSopenharmony_ci
484d6c458bSopenharmony_cinapi_value SequenceRunner::SeqRunnerConstructor(napi_env env, napi_callback_info cbinfo)
494d6c458bSopenharmony_ci{
504d6c458bSopenharmony_ci    // get input args out of env and cbinfo
514d6c458bSopenharmony_ci    size_t argc = 2; // 2: The maximum number of parameters is 2
524d6c458bSopenharmony_ci    napi_value args[2]; // 2: The maximum number of parameters is 2
534d6c458bSopenharmony_ci    napi_value thisVar;
544d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
554d6c458bSopenharmony_ci
564d6c458bSopenharmony_ci    uint32_t priority = Priority::DEFAULT;
574d6c458bSopenharmony_ci    std::string name = "";
584d6c458bSopenharmony_ci    if (argc == 2) { // 2: The number of parameters is 2, if the first is seqRunner name, the second must be priority
594d6c458bSopenharmony_ci        if (NapiHelper::IsString(env, args[0]) && NapiHelper::IsNumber(env, args[1])) {
604d6c458bSopenharmony_ci            name = NapiHelper::GetString(env, args[0]);
614d6c458bSopenharmony_ci            priority = NapiHelper::GetUint32Value(env, args[1]);
624d6c458bSopenharmony_ci            if (priority >= Priority::NUMBER) {
634d6c458bSopenharmony_ci                ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied.");
644d6c458bSopenharmony_ci                return nullptr;
654d6c458bSopenharmony_ci            }
664d6c458bSopenharmony_ci        } else {
674d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
684d6c458bSopenharmony_ci                "the type of first param must be string and the type of second param must be string.");
694d6c458bSopenharmony_ci            return nullptr;
704d6c458bSopenharmony_ci        }
714d6c458bSopenharmony_ci    } else if (argc == 1) {
724d6c458bSopenharmony_ci        if (NapiHelper::IsString(env, args[0])) {
734d6c458bSopenharmony_ci            name = NapiHelper::GetString(env, args[0]);
744d6c458bSopenharmony_ci        } else if (NapiHelper::IsNumber(env, args[0])) {
754d6c458bSopenharmony_ci            priority = NapiHelper::GetUint32Value(env, args[0]);
764d6c458bSopenharmony_ci            if (priority >= Priority::NUMBER) {
774d6c458bSopenharmony_ci                ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied.");
784d6c458bSopenharmony_ci                return nullptr;
794d6c458bSopenharmony_ci            }
804d6c458bSopenharmony_ci        } else {
814d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of first param must be string or number.");
824d6c458bSopenharmony_ci            return nullptr;
834d6c458bSopenharmony_ci        }
844d6c458bSopenharmony_ci    }
854d6c458bSopenharmony_ci
864d6c458bSopenharmony_ci    SequenceRunner* seqRunner = nullptr;
874d6c458bSopenharmony_ci    if (name != "") {
884d6c458bSopenharmony_ci        seqRunner = SequenceRunnerManager::GetInstance().CreateOrGetGlobalRunner(env, thisVar, argc, name, priority);
894d6c458bSopenharmony_ci        if (seqRunner == nullptr) {
904d6c458bSopenharmony_ci            HILOG_ERROR("taskpool:: create or get globalRunner failed");
914d6c458bSopenharmony_ci            return nullptr;
924d6c458bSopenharmony_ci        }
934d6c458bSopenharmony_ci    } else {
944d6c458bSopenharmony_ci        seqRunner = new SequenceRunner();
954d6c458bSopenharmony_ci        seqRunner->priority_ = static_cast<Priority>(priority);
964d6c458bSopenharmony_ci        napi_create_reference(env, thisVar, 0, &seqRunner->seqRunnerRef_);
974d6c458bSopenharmony_ci    }
984d6c458bSopenharmony_ci
994d6c458bSopenharmony_ci    SeqRunnerConstructorInner(env, thisVar, seqRunner);
1004d6c458bSopenharmony_ci    return thisVar;
1014d6c458bSopenharmony_ci}
1024d6c458bSopenharmony_ci
1034d6c458bSopenharmony_cinapi_value SequenceRunner::Execute(napi_env env, napi_callback_info cbinfo)
1044d6c458bSopenharmony_ci{
1054d6c458bSopenharmony_ci    size_t argc = 1;
1064d6c458bSopenharmony_ci    napi_value args[1];
1074d6c458bSopenharmony_ci    napi_value thisVar;
1084d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
1094d6c458bSopenharmony_ci    std::string errMessage = "";
1104d6c458bSopenharmony_ci    if (argc < 1) {
1114d6c458bSopenharmony_ci        errMessage = "seqRunner:: number of params at least one";
1124d6c458bSopenharmony_ci        HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1134d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of param at least one.");
1144d6c458bSopenharmony_ci        return nullptr;
1154d6c458bSopenharmony_ci    }
1164d6c458bSopenharmony_ci    if (!NapiHelper::IsObject(env, args[0]) || !NapiHelper::HasNameProperty(env, args[0], TASKID_STR)) {
1174d6c458bSopenharmony_ci        errMessage = "seqRunner:: first param must be task.";
1184d6c458bSopenharmony_ci        HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1194d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be task.");
1204d6c458bSopenharmony_ci        return nullptr;
1214d6c458bSopenharmony_ci    }
1224d6c458bSopenharmony_ci    napi_value napiSeqRunnerId = NapiHelper::GetNameProperty(env, thisVar, SEQ_RUNNER_ID_STR);
1234d6c458bSopenharmony_ci    uint64_t seqRunnerId = NapiHelper::GetUint64Value(env, napiSeqRunnerId);
1244d6c458bSopenharmony_ci    SequenceRunner* seqRunner = TaskGroupManager::GetInstance().GetSeqRunner(seqRunnerId);
1254d6c458bSopenharmony_ci    if (seqRunner == nullptr) {
1264d6c458bSopenharmony_ci        return nullptr;
1274d6c458bSopenharmony_ci    }
1284d6c458bSopenharmony_ci    Task* task = nullptr;
1294d6c458bSopenharmony_ci    napi_unwrap(env, args[0], reinterpret_cast<void**>(&task));
1304d6c458bSopenharmony_ci    if (task == nullptr) {
1314d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of param must be task.");
1324d6c458bSopenharmony_ci        return nullptr;
1334d6c458bSopenharmony_ci    }
1344d6c458bSopenharmony_ci    if (!task->CanForSequenceRunner(env)) {
1354d6c458bSopenharmony_ci        return nullptr;
1364d6c458bSopenharmony_ci    }
1374d6c458bSopenharmony_ci    task->seqRunnerId_ = seqRunnerId;
1384d6c458bSopenharmony_ci    napi_value promise = task->GetTaskInfoPromise(env, args[0], TaskType::SEQRUNNER_TASK, seqRunner->priority_);
1394d6c458bSopenharmony_ci    if (promise == nullptr) {
1404d6c458bSopenharmony_ci        return nullptr;
1414d6c458bSopenharmony_ci    }
1424d6c458bSopenharmony_ci    napi_reference_ref(env, seqRunner->seqRunnerRef_, nullptr);
1434d6c458bSopenharmony_ci    if (seqRunner->currentTaskId_ == 0) {
1444d6c458bSopenharmony_ci        HILOG_INFO("taskpool:: taskId %{public}s in seqRunner %{public}s immediately.",
1454d6c458bSopenharmony_ci                   std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str());
1464d6c458bSopenharmony_ci        seqRunner->currentTaskId_ = task->taskId_;
1474d6c458bSopenharmony_ci        task->IncreaseRefCount();
1484d6c458bSopenharmony_ci        task->taskState_ = ExecuteState::WAITING;
1494d6c458bSopenharmony_ci        ExecuteTaskImmediately(task->taskId_, seqRunner->priority_);
1504d6c458bSopenharmony_ci    } else {
1514d6c458bSopenharmony_ci        HILOG_INFO("taskpool:: add taskId: %{public}s to seqRunner %{public}s.",
1524d6c458bSopenharmony_ci                   std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str());
1534d6c458bSopenharmony_ci        TaskGroupManager::GetInstance().AddTaskToSeqRunner(seqRunnerId, task);
1544d6c458bSopenharmony_ci    }
1554d6c458bSopenharmony_ci    return promise;
1564d6c458bSopenharmony_ci}
1574d6c458bSopenharmony_ci
1584d6c458bSopenharmony_civoid SequenceRunner::ExecuteTaskImmediately(uint64_t taskId, Priority priority)
1594d6c458bSopenharmony_ci{
1604d6c458bSopenharmony_ci    TaskManager::GetInstance().EnqueueTaskId(taskId, priority);
1614d6c458bSopenharmony_ci}
1624d6c458bSopenharmony_ci
1634d6c458bSopenharmony_civoid SequenceRunner::SequenceRunnerDestructor(napi_env env, void* data, [[maybe_unused]] void* hint)
1644d6c458bSopenharmony_ci{
1654d6c458bSopenharmony_ci    SequenceRunner* seqRunner = static_cast<SequenceRunner*>(data);
1664d6c458bSopenharmony_ci    if (seqRunner->isGlobalRunner_) {
1674d6c458bSopenharmony_ci        SequenceRunnerManager::GetInstance().GlobalSequenceRunnerDestructor(env, seqRunner);
1684d6c458bSopenharmony_ci    } else {
1694d6c458bSopenharmony_ci        TaskGroupManager::GetInstance().RemoveSequenceRunner(seqRunner->seqRunnerId_);
1704d6c458bSopenharmony_ci        napi_delete_reference(env, seqRunner->seqRunnerRef_);
1714d6c458bSopenharmony_ci        delete seqRunner;
1724d6c458bSopenharmony_ci    }
1734d6c458bSopenharmony_ci}
1744d6c458bSopenharmony_ci} // namespace Commonlibrary::Concurrent::TaskPoolModule