14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2022 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
164d6c458bSopenharmony_ci#include "taskpool.h"
174d6c458bSopenharmony_ci
184d6c458bSopenharmony_ci#include <cinttypes>
194d6c458bSopenharmony_ci
204d6c458bSopenharmony_ci#include "helper/error_helper.h"
214d6c458bSopenharmony_ci#include "helper/hitrace_helper.h"
224d6c458bSopenharmony_ci#include "helper/napi_helper.h"
234d6c458bSopenharmony_ci#include "helper/object_helper.h"
244d6c458bSopenharmony_ci#include "message_queue.h"
254d6c458bSopenharmony_ci#include "task_manager.h"
264d6c458bSopenharmony_ci#include "tools/log.h"
274d6c458bSopenharmony_ci#include "worker.h"
284d6c458bSopenharmony_ci
294d6c458bSopenharmony_cinamespace Commonlibrary::Concurrent::TaskPoolModule {
304d6c458bSopenharmony_ciusing namespace Commonlibrary::Concurrent::Common::Helper;
314d6c458bSopenharmony_ci
324d6c458bSopenharmony_cinapi_value TaskPool::InitTaskPool(napi_env env, napi_value exports)
334d6c458bSopenharmony_ci{
344d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: Import taskpool");
354d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
364d6c458bSopenharmony_ci    napi_value taskClass = nullptr;
374d6c458bSopenharmony_ci    napi_define_class(env, "Task", NAPI_AUTO_LENGTH, Task::TaskConstructor, nullptr, 0, nullptr, &taskClass);
384d6c458bSopenharmony_ci    napi_value longTaskClass = nullptr;
394d6c458bSopenharmony_ci    napi_define_class(env, "LongTask", NAPI_AUTO_LENGTH, Task::LongTaskConstructor,
404d6c458bSopenharmony_ci                      nullptr, 0, nullptr, &longTaskClass);
414d6c458bSopenharmony_ci    napi_value genericsTaskClass = nullptr;
424d6c458bSopenharmony_ci    napi_define_class(env, "GenericsTask", NAPI_AUTO_LENGTH, Task::TaskConstructor,
434d6c458bSopenharmony_ci                      nullptr, 0, nullptr, &genericsTaskClass);
444d6c458bSopenharmony_ci    napi_value isCanceledFunc = nullptr;
454d6c458bSopenharmony_ci    napi_create_function(env, "isCanceled", NAPI_AUTO_LENGTH, Task::IsCanceled, NULL, &isCanceledFunc);
464d6c458bSopenharmony_ci    napi_set_named_property(env, taskClass, "isCanceled", isCanceledFunc);
474d6c458bSopenharmony_ci    napi_value sendDataFunc = nullptr;
484d6c458bSopenharmony_ci    napi_create_function(env, "sendData", NAPI_AUTO_LENGTH, Task::SendData, NULL, &sendDataFunc);
494d6c458bSopenharmony_ci    napi_set_named_property(env, taskClass, "sendData", sendDataFunc);
504d6c458bSopenharmony_ci    napi_value taskGroupClass = nullptr;
514d6c458bSopenharmony_ci    napi_define_class(env, "TaskGroup", NAPI_AUTO_LENGTH, TaskGroup::TaskGroupConstructor, nullptr, 0, nullptr,
524d6c458bSopenharmony_ci                      &taskGroupClass);
534d6c458bSopenharmony_ci    napi_value seqRunnerClass = nullptr;
544d6c458bSopenharmony_ci    napi_define_class(env, "SequenceRunner", NAPI_AUTO_LENGTH, SequenceRunner::SeqRunnerConstructor,
554d6c458bSopenharmony_ci                      nullptr, 0, nullptr, &seqRunnerClass);
564d6c458bSopenharmony_ci
574d6c458bSopenharmony_ci    // define priority
584d6c458bSopenharmony_ci    napi_value priorityObj = NapiHelper::CreateObject(env);
594d6c458bSopenharmony_ci    napi_value highPriority = NapiHelper::CreateUint32(env, Priority::HIGH);
604d6c458bSopenharmony_ci    napi_value mediumPriority = NapiHelper::CreateUint32(env, Priority::MEDIUM);
614d6c458bSopenharmony_ci    napi_value lowPriority = NapiHelper::CreateUint32(env, Priority::LOW);
624d6c458bSopenharmony_ci    napi_value idlePriority = NapiHelper::CreateUint32(env, Priority::IDLE);
634d6c458bSopenharmony_ci    napi_property_descriptor exportPriority[] = {
644d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("HIGH", highPriority),
654d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("MEDIUM", mediumPriority),
664d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("LOW", lowPriority),
674d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("IDLE", idlePriority),
684d6c458bSopenharmony_ci    };
694d6c458bSopenharmony_ci    napi_define_properties(env, priorityObj, sizeof(exportPriority) / sizeof(exportPriority[0]), exportPriority);
704d6c458bSopenharmony_ci
714d6c458bSopenharmony_ci    // define State
724d6c458bSopenharmony_ci    napi_value stateObj = NapiHelper::CreateObject(env);
734d6c458bSopenharmony_ci    napi_value waitingState = NapiHelper::CreateUint32(env, ExecuteState::WAITING);
744d6c458bSopenharmony_ci    napi_value runningState = NapiHelper::CreateUint32(env, ExecuteState::RUNNING);
754d6c458bSopenharmony_ci    napi_value canceledState = NapiHelper::CreateUint32(env, ExecuteState::CANCELED);
764d6c458bSopenharmony_ci    napi_property_descriptor exportState[] = {
774d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("WAITING", waitingState),
784d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("RUNNING", runningState),
794d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("CANCELED", canceledState),
804d6c458bSopenharmony_ci    };
814d6c458bSopenharmony_ci    napi_define_properties(env, stateObj, sizeof(exportState) / sizeof(exportState[0]), exportState);
824d6c458bSopenharmony_ci
834d6c458bSopenharmony_ci    napi_property_descriptor properties[] = {
844d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("Task", taskClass),
854d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("LongTask", longTaskClass),
864d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("GenericsTask", genericsTaskClass),
874d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("TaskGroup", taskGroupClass),
884d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("SequenceRunner", seqRunnerClass),
894d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("Priority", priorityObj),
904d6c458bSopenharmony_ci        DECLARE_NAPI_PROPERTY("State", stateObj),
914d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("execute", Execute),
924d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("executeDelayed", ExecuteDelayed),
934d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("cancel", Cancel),
944d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("getTaskPoolInfo", GetTaskPoolInfo),
954d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("terminateTask", TerminateTask),
964d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("isConcurrent", IsConcurrent),
974d6c458bSopenharmony_ci        DECLARE_NAPI_FUNCTION("executePeriodically", ExecutePeriodically),
984d6c458bSopenharmony_ci    };
994d6c458bSopenharmony_ci    napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
1004d6c458bSopenharmony_ci
1014d6c458bSopenharmony_ci    TaskManager::GetInstance().InitTaskManager(env);
1024d6c458bSopenharmony_ci    return exports;
1034d6c458bSopenharmony_ci}
1044d6c458bSopenharmony_ci
1054d6c458bSopenharmony_ci// ---------------------------------- SendData ---------------------------------------
1064d6c458bSopenharmony_civoid TaskPool::ExecuteCallback(const uv_async_t* req)
1074d6c458bSopenharmony_ci{
1084d6c458bSopenharmony_ci    auto* msgQueue = TaskManager::GetInstance().GetMessageQueue(req);
1094d6c458bSopenharmony_ci    if (msgQueue == nullptr) {
1104d6c458bSopenharmony_ci        HILOG_ERROR("taskpool:: msgQueue is nullptr");
1114d6c458bSopenharmony_ci        return;
1124d6c458bSopenharmony_ci    }
1134d6c458bSopenharmony_ci    ExecuteCallbackInner(*msgQueue);
1144d6c458bSopenharmony_ci}
1154d6c458bSopenharmony_ci
1164d6c458bSopenharmony_civoid TaskPool::ExecuteCallbackTask(CallbackInfo* callbackInfo)
1174d6c458bSopenharmony_ci{
1184d6c458bSopenharmony_ci    auto* msgQueue = TaskManager::GetInstance().GetMessageQueueFromCallbackInfo(callbackInfo);
1194d6c458bSopenharmony_ci    if (msgQueue == nullptr) {
1204d6c458bSopenharmony_ci        HILOG_ERROR("taskpool:: msgQueue is nullptr");
1214d6c458bSopenharmony_ci        return;
1224d6c458bSopenharmony_ci    }
1234d6c458bSopenharmony_ci    ExecuteCallbackInner(*msgQueue);
1244d6c458bSopenharmony_ci}
1254d6c458bSopenharmony_ci
1264d6c458bSopenharmony_civoid TaskPool::ExecuteCallbackInner(MsgQueue& msgQueue)
1274d6c458bSopenharmony_ci{
1284d6c458bSopenharmony_ci    while (!msgQueue.IsEmpty()) {
1294d6c458bSopenharmony_ci        auto resultInfo = msgQueue.DeQueue();
1304d6c458bSopenharmony_ci        if (resultInfo == nullptr) {
1314d6c458bSopenharmony_ci            HILOG_DEBUG("taskpool:: resultInfo is nullptr");
1324d6c458bSopenharmony_ci            continue;
1334d6c458bSopenharmony_ci        }
1344d6c458bSopenharmony_ci        ObjectScope<TaskResultInfo> resultInfoScope(resultInfo, false);
1354d6c458bSopenharmony_ci        napi_status status = napi_ok;
1364d6c458bSopenharmony_ci        CallbackScope callbackScope(resultInfo->hostEnv, resultInfo->workerEnv, resultInfo->taskId, status);
1374d6c458bSopenharmony_ci        if (status != napi_ok) {
1384d6c458bSopenharmony_ci            HILOG_ERROR("napi_open_handle_scope failed");
1394d6c458bSopenharmony_ci            return;
1404d6c458bSopenharmony_ci        }
1414d6c458bSopenharmony_ci        auto env = resultInfo->hostEnv;
1424d6c458bSopenharmony_ci        auto callbackInfo = TaskManager::GetInstance().GetCallbackInfo(resultInfo->taskId);
1434d6c458bSopenharmony_ci        if (callbackInfo == nullptr) {
1444d6c458bSopenharmony_ci            HILOG_ERROR("taskpool:: the callback in SendData is not registered on the host side");
1454d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_REGISTERED);
1464d6c458bSopenharmony_ci            continue;
1474d6c458bSopenharmony_ci        }
1484d6c458bSopenharmony_ci        auto func = NapiHelper::GetReferenceValue(env, callbackInfo->callbackRef);
1494d6c458bSopenharmony_ci        napi_value args;
1504d6c458bSopenharmony_ci        napi_value result;
1514d6c458bSopenharmony_ci        status = napi_deserialize(env, resultInfo->serializationArgs, &args);
1524d6c458bSopenharmony_ci        napi_delete_serialization_data(env, resultInfo->serializationArgs);
1534d6c458bSopenharmony_ci        if (status != napi_ok || args == nullptr) {
1544d6c458bSopenharmony_ci            std::string errMessage = "taskpool:: failed to serialize function";
1554d6c458bSopenharmony_ci            HILOG_ERROR("%{public}s in SendData", errMessage.c_str());
1564d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1574d6c458bSopenharmony_ci            continue;
1584d6c458bSopenharmony_ci        }
1594d6c458bSopenharmony_ci        uint32_t argsNum = NapiHelper::GetArrayLength(env, args);
1604d6c458bSopenharmony_ci        napi_value argsArray[argsNum];
1614d6c458bSopenharmony_ci        for (size_t i = 0; i < argsNum; i++) {
1624d6c458bSopenharmony_ci            argsArray[i] = NapiHelper::GetElement(env, args, i);
1634d6c458bSopenharmony_ci        }
1644d6c458bSopenharmony_ci        napi_call_function(env, NapiHelper::GetGlobalObject(env), func, argsNum, argsArray, &result);
1654d6c458bSopenharmony_ci        if (NapiHelper::IsExceptionPending(env)) {
1664d6c458bSopenharmony_ci            napi_value exception = nullptr;
1674d6c458bSopenharmony_ci            napi_get_and_clear_last_exception(env, &exception);
1684d6c458bSopenharmony_ci            HILOG_ERROR("taskpool:: an exception has occurred in napi_call_function");
1694d6c458bSopenharmony_ci        }
1704d6c458bSopenharmony_ci    }
1714d6c458bSopenharmony_ci}
1724d6c458bSopenharmony_ci// ---------------------------------- SendData ---------------------------------------
1734d6c458bSopenharmony_ci
1744d6c458bSopenharmony_cinapi_value TaskPool::GetTaskPoolInfo(napi_env env, [[maybe_unused]] napi_callback_info cbinfo)
1754d6c458bSopenharmony_ci{
1764d6c458bSopenharmony_ci    napi_value result = nullptr;
1774d6c458bSopenharmony_ci    napi_create_object(env, &result);
1784d6c458bSopenharmony_ci    napi_value threadInfos = TaskManager::GetInstance().GetThreadInfos(env);
1794d6c458bSopenharmony_ci    napi_value taskInfos = TaskManager::GetInstance().GetTaskInfos(env);
1804d6c458bSopenharmony_ci    napi_set_named_property(env, result, "threadInfos", threadInfos);
1814d6c458bSopenharmony_ci    napi_set_named_property(env, result, "taskInfos", taskInfos);
1824d6c458bSopenharmony_ci    return result;
1834d6c458bSopenharmony_ci}
1844d6c458bSopenharmony_ci
1854d6c458bSopenharmony_cinapi_value TaskPool::TerminateTask(napi_env env, napi_callback_info cbinfo)
1864d6c458bSopenharmony_ci{
1874d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
1884d6c458bSopenharmony_ci    size_t argc = 1; // 1: long task
1894d6c458bSopenharmony_ci    napi_value args[1];
1904d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
1914d6c458bSopenharmony_ci    if (argc < 1) {
1924d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of the params must be one.");
1934d6c458bSopenharmony_ci        return nullptr;
1944d6c458bSopenharmony_ci    }
1954d6c458bSopenharmony_ci    if (!NapiHelper::IsObject(env, args[0])) {
1964d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the params must be object.");
1974d6c458bSopenharmony_ci        return nullptr;
1984d6c458bSopenharmony_ci    }
1994d6c458bSopenharmony_ci    napi_value napiTaskId = NapiHelper::GetNameProperty(env, args[0], TASKID_STR);
2004d6c458bSopenharmony_ci    uint64_t taskId = NapiHelper::GetUint64Value(env, napiTaskId);
2014d6c458bSopenharmony_ci    auto task = TaskManager::GetInstance().GetTask(taskId);
2024d6c458bSopenharmony_ci    if (task == nullptr || !task->IsLongTask()) {
2034d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the params must be long task.");
2044d6c458bSopenharmony_ci        return nullptr;
2054d6c458bSopenharmony_ci    }
2064d6c458bSopenharmony_ci    TaskManager::GetInstance().TerminateTask(taskId);
2074d6c458bSopenharmony_ci    return nullptr;
2084d6c458bSopenharmony_ci}
2094d6c458bSopenharmony_ci
2104d6c458bSopenharmony_cinapi_value TaskPool::Execute(napi_env env, napi_callback_info cbinfo)
2114d6c458bSopenharmony_ci{
2124d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
2134d6c458bSopenharmony_ci    size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
2144d6c458bSopenharmony_ci    if (argc < 1) {
2154d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of params must be at least one.");
2164d6c458bSopenharmony_ci        return nullptr;
2174d6c458bSopenharmony_ci    }
2184d6c458bSopenharmony_ci    napi_value* args = new napi_value[argc];
2194d6c458bSopenharmony_ci    ObjectScope<napi_value> scope(args, true);
2204d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
2214d6c458bSopenharmony_ci    napi_valuetype type = napi_undefined;
2224d6c458bSopenharmony_ci    napi_typeof(env, args[0], &type);
2234d6c458bSopenharmony_ci    if (type == napi_object) {
2244d6c458bSopenharmony_ci        uint32_t priority = Priority::DEFAULT; // DEFAULT priority is MEDIUM
2254d6c458bSopenharmony_ci        if (argc > 1) {
2264d6c458bSopenharmony_ci            if (!NapiHelper::IsNumber(env, args[1])) {
2274d6c458bSopenharmony_ci                ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the second param must be number.");
2284d6c458bSopenharmony_ci                return nullptr;
2294d6c458bSopenharmony_ci            }
2304d6c458bSopenharmony_ci            priority = NapiHelper::GetUint32Value(env, args[1]);
2314d6c458bSopenharmony_ci            if (priority >= Priority::NUMBER) {
2324d6c458bSopenharmony_ci                ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value is error");
2334d6c458bSopenharmony_ci                return nullptr;
2344d6c458bSopenharmony_ci            }
2354d6c458bSopenharmony_ci        }
2364d6c458bSopenharmony_ci        if (NapiHelper::HasNameProperty(env, args[0], GROUP_ID_STR)) {
2374d6c458bSopenharmony_ci            return ExecuteGroup(env, args[0], static_cast<Priority>(priority));
2384d6c458bSopenharmony_ci        }
2394d6c458bSopenharmony_ci        Task* task = nullptr;
2404d6c458bSopenharmony_ci        napi_unwrap(env, args[0], reinterpret_cast<void**>(&task));
2414d6c458bSopenharmony_ci        if (task == nullptr) {
2424d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be task.");
2434d6c458bSopenharmony_ci            return nullptr;
2444d6c458bSopenharmony_ci        }
2454d6c458bSopenharmony_ci        if (!task->CanExecute(env)) {
2464d6c458bSopenharmony_ci            return nullptr;
2474d6c458bSopenharmony_ci        }
2484d6c458bSopenharmony_ci        napi_value promise = task->GetTaskInfoPromise(env, args[0], TaskType::COMMON_TASK,
2494d6c458bSopenharmony_ci                                                      static_cast<Priority>(priority));
2504d6c458bSopenharmony_ci        if (promise == nullptr) {
2514d6c458bSopenharmony_ci            return nullptr;
2524d6c458bSopenharmony_ci        }
2534d6c458bSopenharmony_ci        ExecuteTask(env, task, static_cast<Priority>(priority));
2544d6c458bSopenharmony_ci        return promise;
2554d6c458bSopenharmony_ci    }
2564d6c458bSopenharmony_ci    if (type != napi_function) {
2574d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
2584d6c458bSopenharmony_ci            "the type of the first param must be object or function.");
2594d6c458bSopenharmony_ci        return nullptr;
2604d6c458bSopenharmony_ci    }
2614d6c458bSopenharmony_ci    Task* task = Task::GenerateFunctionTask(env, args[0], args + 1, argc - 1, TaskType::FUNCTION_TASK);
2624d6c458bSopenharmony_ci    if (task == nullptr) {
2634d6c458bSopenharmony_ci        HILOG_ERROR("taskpool:: GenerateFunctionTask failed");
2644d6c458bSopenharmony_ci        return nullptr;
2654d6c458bSopenharmony_ci    }
2664d6c458bSopenharmony_ci    TaskManager::GetInstance().StoreTask(task->taskId_, task);
2674d6c458bSopenharmony_ci    napi_value promise = NapiHelper::CreatePromise(env, &task->currentTaskInfo_->deferred);
2684d6c458bSopenharmony_ci    ExecuteTask(env, task);
2694d6c458bSopenharmony_ci    return promise;
2704d6c458bSopenharmony_ci}
2714d6c458bSopenharmony_ci
2724d6c458bSopenharmony_civoid TaskPool::DelayTask(uv_timer_t* handle)
2734d6c458bSopenharmony_ci{
2744d6c458bSopenharmony_ci    TaskMessage *taskMessage = static_cast<TaskMessage *>(handle->data);
2754d6c458bSopenharmony_ci    auto task = TaskManager::GetInstance().GetTask(taskMessage->taskId);
2764d6c458bSopenharmony_ci    if (task == nullptr) {
2774d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: task is nullptr");
2784d6c458bSopenharmony_ci    } else if (task->taskState_ == ExecuteState::CANCELED) {
2794d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: DelayTask task has been canceled");
2804d6c458bSopenharmony_ci        napi_value error = ErrorHelper::NewError(task->env_, 0, "taskpool:: task has been canceled");
2814d6c458bSopenharmony_ci        napi_reject_deferred(task->env_, taskMessage->deferred, error);
2824d6c458bSopenharmony_ci    } else {
2834d6c458bSopenharmony_ci        HILOG_INFO("taskpool:: DelayTask taskId %{public}s", std::to_string(taskMessage->taskId).c_str());
2844d6c458bSopenharmony_ci        TaskManager::GetInstance().IncreaseRefCount(taskMessage->taskId);
2854d6c458bSopenharmony_ci        task->IncreaseRefCount();
2864d6c458bSopenharmony_ci        napi_value napiTask = NapiHelper::GetReferenceValue(task->env_, task->taskRef_);
2874d6c458bSopenharmony_ci        TaskInfo* taskInfo = task->GetTaskInfo(task->env_, napiTask, taskMessage->priority);
2884d6c458bSopenharmony_ci        if (taskInfo != nullptr) {
2894d6c458bSopenharmony_ci            taskInfo->deferred = taskMessage->deferred;
2904d6c458bSopenharmony_ci            if (task->taskState_ == ExecuteState::DELAYED || task->taskState_ == ExecuteState::FINISHED) {
2914d6c458bSopenharmony_ci                task->taskState_ = ExecuteState::WAITING;
2924d6c458bSopenharmony_ci                TaskManager::GetInstance().EnqueueTaskId(taskMessage->taskId, Priority(taskMessage->priority));
2934d6c458bSopenharmony_ci            }
2944d6c458bSopenharmony_ci        } else {
2954d6c458bSopenharmony_ci            napi_value execption = nullptr;
2964d6c458bSopenharmony_ci            napi_get_and_clear_last_exception(task->env_, &execption);
2974d6c458bSopenharmony_ci            if (execption != nullptr) {
2984d6c458bSopenharmony_ci                napi_reject_deferred(task->env_, taskMessage->deferred, execption);
2994d6c458bSopenharmony_ci            }
3004d6c458bSopenharmony_ci        }
3014d6c458bSopenharmony_ci    }
3024d6c458bSopenharmony_ci    if (task != nullptr) {
3034d6c458bSopenharmony_ci        std::lock_guard<RECURSIVE_MUTEX> lock(task->taskMutex_);
3044d6c458bSopenharmony_ci        task->delayedTimers_.erase(handle);
3054d6c458bSopenharmony_ci    }
3064d6c458bSopenharmony_ci    uv_timer_stop(handle);
3074d6c458bSopenharmony_ci    uv_close(reinterpret_cast<uv_handle_t*>(handle), [](uv_handle_t* handle) {
3084d6c458bSopenharmony_ci        delete reinterpret_cast<uv_timer_t*>(handle);
3094d6c458bSopenharmony_ci        handle = nullptr;
3104d6c458bSopenharmony_ci    });
3114d6c458bSopenharmony_ci    delete taskMessage;
3124d6c458bSopenharmony_ci    taskMessage = nullptr;
3134d6c458bSopenharmony_ci}
3144d6c458bSopenharmony_ci
3154d6c458bSopenharmony_cinapi_value TaskPool::ExecuteDelayed(napi_env env, napi_callback_info cbinfo)
3164d6c458bSopenharmony_ci{
3174d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
3184d6c458bSopenharmony_ci    uint32_t priority = Priority::DEFAULT; // DEFAULT priority is MEDIUM
3194d6c458bSopenharmony_ci    int32_t delayTime = 0;
3204d6c458bSopenharmony_ci    Task* task = nullptr;
3214d6c458bSopenharmony_ci    if (!CheckDelayedParams(env, cbinfo, priority, delayTime, task)) {
3224d6c458bSopenharmony_ci        return nullptr;
3234d6c458bSopenharmony_ci    }
3244d6c458bSopenharmony_ci
3254d6c458bSopenharmony_ci    if (!task->IsExecuted() || task->taskState_ == ExecuteState::CANCELED ||
3264d6c458bSopenharmony_ci        task->taskState_ == ExecuteState::FINISHED) {
3274d6c458bSopenharmony_ci        task->taskState_ = ExecuteState::DELAYED;
3284d6c458bSopenharmony_ci    }
3294d6c458bSopenharmony_ci    task->UpdateTaskType(TaskType::COMMON_TASK);
3304d6c458bSopenharmony_ci
3314d6c458bSopenharmony_ci    uv_loop_t* loop = NapiHelper::GetLibUV(env);
3324d6c458bSopenharmony_ci    uv_update_time(loop);
3334d6c458bSopenharmony_ci    uv_timer_t* timer = new uv_timer_t;
3344d6c458bSopenharmony_ci    uv_timer_init(loop, timer);
3354d6c458bSopenharmony_ci    TaskMessage *taskMessage = new TaskMessage();
3364d6c458bSopenharmony_ci    taskMessage->priority = static_cast<Priority>(priority);
3374d6c458bSopenharmony_ci    taskMessage->taskId = task->taskId_;
3384d6c458bSopenharmony_ci    napi_value promise = NapiHelper::CreatePromise(env, &taskMessage->deferred);
3394d6c458bSopenharmony_ci    timer->data = taskMessage;
3404d6c458bSopenharmony_ci
3414d6c458bSopenharmony_ci    std::string strTrace = "ExecuteDelayed: taskId: " + std::to_string(task->taskId_);
3424d6c458bSopenharmony_ci    strTrace += ", priority: " + std::to_string(priority);
3434d6c458bSopenharmony_ci    strTrace += ", delayTime " + std::to_string(delayTime);
3444d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(strTrace);
3454d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: %{public}s", strTrace.c_str());
3464d6c458bSopenharmony_ci
3474d6c458bSopenharmony_ci    uv_timer_start(timer, reinterpret_cast<uv_timer_cb>(DelayTask), delayTime, 0);
3484d6c458bSopenharmony_ci    {
3494d6c458bSopenharmony_ci        std::lock_guard<RECURSIVE_MUTEX> lock(task->taskMutex_);
3504d6c458bSopenharmony_ci        task->delayedTimers_.insert(timer);
3514d6c458bSopenharmony_ci    }
3524d6c458bSopenharmony_ci    NativeEngine* engine = reinterpret_cast<NativeEngine*>(env);
3534d6c458bSopenharmony_ci    if (engine->IsMainThread()) {
3544d6c458bSopenharmony_ci        uv_async_send(&loop->wq_async);
3554d6c458bSopenharmony_ci    } else {
3564d6c458bSopenharmony_ci        uv_work_t *work = new uv_work_t;
3574d6c458bSopenharmony_ci        uv_queue_work_with_qos(loop, work, [](uv_work_t *) {},
3584d6c458bSopenharmony_ci                               [](uv_work_t *work, int32_t) {delete work; }, uv_qos_user_initiated);
3594d6c458bSopenharmony_ci    }
3604d6c458bSopenharmony_ci    return promise;
3614d6c458bSopenharmony_ci}
3624d6c458bSopenharmony_ci
3634d6c458bSopenharmony_cinapi_value TaskPool::ExecuteGroup(napi_env env, napi_value napiTaskGroup, Priority priority)
3644d6c458bSopenharmony_ci{
3654d6c458bSopenharmony_ci    napi_value napiGroupId = NapiHelper::GetNameProperty(env, napiTaskGroup, GROUP_ID_STR);
3664d6c458bSopenharmony_ci    uint64_t groupId = NapiHelper::GetUint64Value(env, napiGroupId);
3674d6c458bSopenharmony_ci    HILOG_INFO("taskpool::ExecuteGroup groupId %{public}s", std::to_string(groupId).c_str());
3684d6c458bSopenharmony_ci    auto taskGroup = TaskGroupManager::GetInstance().GetTaskGroup(groupId);
3694d6c458bSopenharmony_ci    napi_reference_ref(env, taskGroup->groupRef_, nullptr);
3704d6c458bSopenharmony_ci    if (taskGroup->groupState_ == ExecuteState::NOT_FOUND || taskGroup->groupState_ == ExecuteState::FINISHED ||
3714d6c458bSopenharmony_ci        taskGroup->groupState_ == ExecuteState::CANCELED) {
3724d6c458bSopenharmony_ci        taskGroup->groupState_ = ExecuteState::WAITING;
3734d6c458bSopenharmony_ci    }
3744d6c458bSopenharmony_ci    GroupInfo* groupInfo = new GroupInfo();
3754d6c458bSopenharmony_ci    groupInfo->priority = priority;
3764d6c458bSopenharmony_ci    napi_value resArr;
3774d6c458bSopenharmony_ci    napi_create_array_with_length(env, taskGroup->taskIds_.size(), &resArr);
3784d6c458bSopenharmony_ci    napi_ref arrRef = NapiHelper::CreateReference(env, resArr, 1);
3794d6c458bSopenharmony_ci    groupInfo->resArr = arrRef;
3804d6c458bSopenharmony_ci    napi_value promise = NapiHelper::CreatePromise(env, &groupInfo->deferred);
3814d6c458bSopenharmony_ci    {
3824d6c458bSopenharmony_ci        std::lock_guard<RECURSIVE_MUTEX> lock(taskGroup->taskGroupMutex_);
3834d6c458bSopenharmony_ci        if (taskGroup->currentGroupInfo_ == nullptr) {
3844d6c458bSopenharmony_ci            taskGroup->currentGroupInfo_ = groupInfo;
3854d6c458bSopenharmony_ci            for (auto iter = taskGroup->taskRefs_.begin(); iter != taskGroup->taskRefs_.end(); iter++) {
3864d6c458bSopenharmony_ci                napi_value napiTask = NapiHelper::GetReferenceValue(env, *iter);
3874d6c458bSopenharmony_ci                Task* task = nullptr;
3884d6c458bSopenharmony_ci                napi_unwrap(env, napiTask, reinterpret_cast<void**>(&task));
3894d6c458bSopenharmony_ci                if (task == nullptr) {
3904d6c458bSopenharmony_ci                    HILOG_ERROR("taskpool::ExecuteGroup task is nullptr");
3914d6c458bSopenharmony_ci                    return nullptr;
3924d6c458bSopenharmony_ci                }
3934d6c458bSopenharmony_ci                napi_reference_ref(env, task->taskRef_, nullptr);
3944d6c458bSopenharmony_ci                if (task->IsGroupCommonTask()) {
3954d6c458bSopenharmony_ci                    task->GetTaskInfo(env, napiTask, static_cast<Priority>(priority));
3964d6c458bSopenharmony_ci                }
3974d6c458bSopenharmony_ci                ExecuteTask(env, task, static_cast<Priority>(priority));
3984d6c458bSopenharmony_ci            }
3994d6c458bSopenharmony_ci        } else {
4004d6c458bSopenharmony_ci            taskGroup->pendingGroupInfos_.push_back(groupInfo);
4014d6c458bSopenharmony_ci        }
4024d6c458bSopenharmony_ci    }
4034d6c458bSopenharmony_ci    return promise;
4044d6c458bSopenharmony_ci}
4054d6c458bSopenharmony_ci
4064d6c458bSopenharmony_civoid TaskPool::HandleTaskResult(const uv_async_t* req)
4074d6c458bSopenharmony_ci{
4084d6c458bSopenharmony_ci    HILOG_DEBUG("taskpool:: HandleTaskResult task");
4094d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
4104d6c458bSopenharmony_ci    auto task = static_cast<Task*>(req->data);
4114d6c458bSopenharmony_ci    if (task == nullptr) { // LCOV_EXCL_BR_LINE
4124d6c458bSopenharmony_ci        HILOG_FATAL("taskpool:: HandleTaskResult task is null");
4134d6c458bSopenharmony_ci        return;
4144d6c458bSopenharmony_ci    }
4154d6c458bSopenharmony_ci    if (!task->IsMainThreadTask()) {
4164d6c458bSopenharmony_ci        if (task->ShouldDeleteTask(false)) {
4174d6c458bSopenharmony_ci            delete task;
4184d6c458bSopenharmony_ci            return;
4194d6c458bSopenharmony_ci        }
4204d6c458bSopenharmony_ci        if (task->IsFunctionTask()) {
4214d6c458bSopenharmony_ci            napi_remove_env_cleanup_hook(task->env_, Task::CleanupHookFunc, task);
4224d6c458bSopenharmony_ci        }
4234d6c458bSopenharmony_ci    }
4244d6c458bSopenharmony_ci    task->DecreaseTaskRefCount();
4254d6c458bSopenharmony_ci    HandleTaskResultCallback(task);
4264d6c458bSopenharmony_ci}
4274d6c458bSopenharmony_ci
4284d6c458bSopenharmony_civoid TaskPool::HandleTaskResultCallback(Task* task)
4294d6c458bSopenharmony_ci{
4304d6c458bSopenharmony_ci    napi_handle_scope scope = nullptr;
4314d6c458bSopenharmony_ci    NAPI_CALL_RETURN_VOID(task->env_, napi_open_handle_scope(task->env_, &scope));
4324d6c458bSopenharmony_ci    napi_value napiTaskResult = nullptr;
4334d6c458bSopenharmony_ci    napi_status status = napi_deserialize(task->env_, task->result_, &napiTaskResult);
4344d6c458bSopenharmony_ci    napi_delete_serialization_data(task->env_, task->result_);
4354d6c458bSopenharmony_ci
4364d6c458bSopenharmony_ci    // tag for trace parse: Task PerformTask End
4374d6c458bSopenharmony_ci    std::string strTrace = "Task PerformTask End: taskId : " + std::to_string(task->taskId_);
4384d6c458bSopenharmony_ci    if (task->taskState_ == ExecuteState::CANCELED) {
4394d6c458bSopenharmony_ci        strTrace += ", performResult : IsCanceled";
4404d6c458bSopenharmony_ci        napiTaskResult = ErrorHelper::NewError(task->env_, 0, "taskpool:: task has been canceled");
4414d6c458bSopenharmony_ci    } else if (status != napi_ok) {
4424d6c458bSopenharmony_ci        HILOG_ERROR("taskpool: failed to deserialize result");
4434d6c458bSopenharmony_ci        strTrace += ", performResult : DeserializeFailed";
4444d6c458bSopenharmony_ci    } else if (task->success_) {
4454d6c458bSopenharmony_ci        strTrace += ", performResult : Successful";
4464d6c458bSopenharmony_ci    } else {
4474d6c458bSopenharmony_ci        strTrace += ", performResult : Unsuccessful";
4484d6c458bSopenharmony_ci    }
4494d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(strTrace);
4504d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: %{public}s", strTrace.c_str());
4514d6c458bSopenharmony_ci    if (napiTaskResult == nullptr) {
4524d6c458bSopenharmony_ci        napi_get_undefined(task->env_, &napiTaskResult);
4534d6c458bSopenharmony_ci    }
4544d6c458bSopenharmony_ci    reinterpret_cast<NativeEngine*>(task->env_)->DecreaseSubEnvCounter();
4554d6c458bSopenharmony_ci    bool success = ((status == napi_ok) && (task->taskState_ != ExecuteState::CANCELED)) && (task->success_);
4564d6c458bSopenharmony_ci    task->taskState_ = ExecuteState::ENDING;
4574d6c458bSopenharmony_ci    if (task->IsGroupTask()) {
4584d6c458bSopenharmony_ci        UpdateGroupInfoByResult(task->env_, task, napiTaskResult, success);
4594d6c458bSopenharmony_ci    } else if (!task->IsPeriodicTask()) {
4604d6c458bSopenharmony_ci        if (success) {
4614d6c458bSopenharmony_ci            napi_resolve_deferred(task->env_, task->currentTaskInfo_->deferred, napiTaskResult);
4624d6c458bSopenharmony_ci            if (task->onExecutionSucceededCallBackInfo_ != nullptr) {
4634d6c458bSopenharmony_ci                task->ExecuteListenerCallback(task->onExecutionSucceededCallBackInfo_);
4644d6c458bSopenharmony_ci            }
4654d6c458bSopenharmony_ci        } else {
4664d6c458bSopenharmony_ci            napi_reject_deferred(task->env_, task->currentTaskInfo_->deferred, napiTaskResult);
4674d6c458bSopenharmony_ci            if (task->onExecutionFailedCallBackInfo_ != nullptr) {
4684d6c458bSopenharmony_ci                task->onExecutionFailedCallBackInfo_->taskError_ = napiTaskResult;
4694d6c458bSopenharmony_ci                task->ExecuteListenerCallback(task->onExecutionFailedCallBackInfo_);
4704d6c458bSopenharmony_ci            }
4714d6c458bSopenharmony_ci        }
4724d6c458bSopenharmony_ci    }
4734d6c458bSopenharmony_ci    NAPI_CALL_RETURN_VOID(task->env_, napi_close_handle_scope(task->env_, scope));
4744d6c458bSopenharmony_ci    TriggerTask(task);
4754d6c458bSopenharmony_ci}
4764d6c458bSopenharmony_ci
4774d6c458bSopenharmony_civoid TaskPool::TriggerTask(Task* task)
4784d6c458bSopenharmony_ci{
4794d6c458bSopenharmony_ci    HILOG_DEBUG("taskpool:: task:%{public}s TriggerTask", std::to_string(task->taskId_).c_str());
4804d6c458bSopenharmony_ci    if (task->IsGroupTask()) {
4814d6c458bSopenharmony_ci        return;
4824d6c458bSopenharmony_ci    }
4834d6c458bSopenharmony_ci    TaskManager::GetInstance().DecreaseRefCount(task->env_, task->taskId_);
4844d6c458bSopenharmony_ci    task->taskState_ = ExecuteState::FINISHED;
4854d6c458bSopenharmony_ci    // seqRunnerTask will trigger the next
4864d6c458bSopenharmony_ci    if (task->IsSeqRunnerTask()) {
4874d6c458bSopenharmony_ci        if (!TaskGroupManager::GetInstance().TriggerSeqRunner(task->env_, task)) {
4884d6c458bSopenharmony_ci            HILOG_ERROR("seqRunner:: task %{public}s trigger in seqRunner %{public}s failed",
4894d6c458bSopenharmony_ci                        std::to_string(task->taskId_).c_str(), std::to_string(task->seqRunnerId_).c_str());
4904d6c458bSopenharmony_ci        }
4914d6c458bSopenharmony_ci    } else if (task->IsCommonTask()) {
4924d6c458bSopenharmony_ci        task->NotifyPendingTask();
4934d6c458bSopenharmony_ci    }
4944d6c458bSopenharmony_ci    if (task->IsPeriodicTask()) {
4954d6c458bSopenharmony_ci        return;
4964d6c458bSopenharmony_ci    }
4974d6c458bSopenharmony_ci    if (!task->IsFunctionTask()) {
4984d6c458bSopenharmony_ci        napi_reference_unref(task->env_, task->taskRef_, nullptr);
4994d6c458bSopenharmony_ci        return;
5004d6c458bSopenharmony_ci    }
5014d6c458bSopenharmony_ci    TaskManager::GetInstance().RemoveTask(task->taskId_);
5024d6c458bSopenharmony_ci    delete task;
5034d6c458bSopenharmony_ci}
5044d6c458bSopenharmony_ci
5054d6c458bSopenharmony_civoid TaskPool::UpdateGroupInfoByResult(napi_env env, Task* task, napi_value res, bool success)
5064d6c458bSopenharmony_ci{
5074d6c458bSopenharmony_ci    HILOG_DEBUG("taskpool:: task:%{public}s UpdateGroupInfoByResult", std::to_string(task->taskId_).c_str());
5084d6c458bSopenharmony_ci    TaskManager::GetInstance().DecreaseRefCount(task->env_, task->taskId_);
5094d6c458bSopenharmony_ci    task->taskState_ = ExecuteState::FINISHED;
5104d6c458bSopenharmony_ci    napi_reference_unref(env, task->taskRef_, nullptr);
5114d6c458bSopenharmony_ci    if (task->IsGroupCommonTask()) {
5124d6c458bSopenharmony_ci        delete task->currentTaskInfo_;
5134d6c458bSopenharmony_ci        task->currentTaskInfo_ = nullptr;
5144d6c458bSopenharmony_ci    }
5154d6c458bSopenharmony_ci    TaskGroup* taskGroup = TaskGroupManager::GetInstance().GetTaskGroup(task->groupId_);
5164d6c458bSopenharmony_ci    if (taskGroup == nullptr) {
5174d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: taskGroup has been released");
5184d6c458bSopenharmony_ci        return;
5194d6c458bSopenharmony_ci    }
5204d6c458bSopenharmony_ci    if (taskGroup->currentGroupInfo_ == nullptr) {
5214d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: taskGroup has been canceled");
5224d6c458bSopenharmony_ci        return;
5234d6c458bSopenharmony_ci    }
5244d6c458bSopenharmony_ci    uint32_t index = taskGroup->GetTaskIndex(task->taskId_);
5254d6c458bSopenharmony_ci    auto groupInfo = taskGroup->currentGroupInfo_;
5264d6c458bSopenharmony_ci    if (success) {
5274d6c458bSopenharmony_ci        // Update res at resArr
5284d6c458bSopenharmony_ci        napi_ref arrRef = groupInfo->resArr;
5294d6c458bSopenharmony_ci        napi_value resArr = NapiHelper::GetReferenceValue(env, arrRef);
5304d6c458bSopenharmony_ci        napi_set_element(env, resArr, index, res);
5314d6c458bSopenharmony_ci
5324d6c458bSopenharmony_ci        groupInfo->finishedTask++;
5334d6c458bSopenharmony_ci        if (groupInfo->finishedTask < taskGroup->taskNum_) {
5344d6c458bSopenharmony_ci            return;
5354d6c458bSopenharmony_ci        }
5364d6c458bSopenharmony_ci        HILOG_INFO("taskpool:: taskGroup perform end, taskGroupId %{public}s", std::to_string(task->groupId_).c_str());
5374d6c458bSopenharmony_ci        napi_resolve_deferred(env, groupInfo->deferred, resArr);
5384d6c458bSopenharmony_ci        for (uint64_t taskId : taskGroup->taskIds_) {
5394d6c458bSopenharmony_ci            auto task = TaskManager::GetInstance().GetTask(taskId);
5404d6c458bSopenharmony_ci            if (task->onExecutionSucceededCallBackInfo_ != nullptr) {
5414d6c458bSopenharmony_ci                task->ExecuteListenerCallback(task->onExecutionSucceededCallBackInfo_);
5424d6c458bSopenharmony_ci            }
5434d6c458bSopenharmony_ci        }
5444d6c458bSopenharmony_ci    } else {
5454d6c458bSopenharmony_ci        napi_reject_deferred(env, groupInfo->deferred, res);
5464d6c458bSopenharmony_ci        if (task->onExecutionFailedCallBackInfo_ != nullptr) {
5474d6c458bSopenharmony_ci            task->onExecutionFailedCallBackInfo_->taskError_ = res;
5484d6c458bSopenharmony_ci            task->ExecuteListenerCallback(task->onExecutionFailedCallBackInfo_);
5494d6c458bSopenharmony_ci        }
5504d6c458bSopenharmony_ci    }
5514d6c458bSopenharmony_ci    taskGroup->groupState_ = ExecuteState::FINISHED;
5524d6c458bSopenharmony_ci    napi_delete_reference(env, groupInfo->resArr);
5534d6c458bSopenharmony_ci    napi_reference_unref(env, taskGroup->groupRef_, nullptr);
5544d6c458bSopenharmony_ci    delete groupInfo;
5554d6c458bSopenharmony_ci    taskGroup->currentGroupInfo_ = nullptr;
5564d6c458bSopenharmony_ci    taskGroup->NotifyGroupTask(env);
5574d6c458bSopenharmony_ci}
5584d6c458bSopenharmony_ci
5594d6c458bSopenharmony_civoid TaskPool::ExecuteTask(napi_env env, Task* task, Priority priority)
5604d6c458bSopenharmony_ci{
5614d6c458bSopenharmony_ci    // tag for trace parse: Task Allocation
5624d6c458bSopenharmony_ci    std::string strTrace = "Task Allocation: taskId : " + std::to_string(task->taskId_)
5634d6c458bSopenharmony_ci        + ", priority : " + std::to_string(priority)
5644d6c458bSopenharmony_ci        + ", executeState : " + std::to_string(ExecuteState::WAITING);
5654d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(strTrace);
5664d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: %{public}s", strTrace.c_str());
5674d6c458bSopenharmony_ci    task->IncreaseRefCount();
5684d6c458bSopenharmony_ci    TaskManager::GetInstance().IncreaseRefCount(task->taskId_);
5694d6c458bSopenharmony_ci    if (task->IsFunctionTask() || (task->taskState_ != ExecuteState::WAITING &&
5704d6c458bSopenharmony_ci        task->taskState_ != ExecuteState::RUNNING && task->taskState_ != ExecuteState::ENDING)) {
5714d6c458bSopenharmony_ci        task->taskState_ = ExecuteState::WAITING;
5724d6c458bSopenharmony_ci        TaskManager::GetInstance().EnqueueTaskId(task->taskId_, priority);
5734d6c458bSopenharmony_ci    }
5744d6c458bSopenharmony_ci}
5754d6c458bSopenharmony_ci
5764d6c458bSopenharmony_cinapi_value TaskPool::Cancel(napi_env env, napi_callback_info cbinfo)
5774d6c458bSopenharmony_ci{
5784d6c458bSopenharmony_ci    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
5794d6c458bSopenharmony_ci    size_t argc = 1;
5804d6c458bSopenharmony_ci    napi_value args[1];
5814d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
5824d6c458bSopenharmony_ci    if (argc < 1) {
5834d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of the params must be 1.");
5844d6c458bSopenharmony_ci        return nullptr;
5854d6c458bSopenharmony_ci    }
5864d6c458bSopenharmony_ci
5874d6c458bSopenharmony_ci    if (!NapiHelper::IsObject(env, args[0])) {
5884d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the params must be object.");
5894d6c458bSopenharmony_ci        return nullptr;
5904d6c458bSopenharmony_ci    }
5914d6c458bSopenharmony_ci
5924d6c458bSopenharmony_ci    if (!NapiHelper::HasNameProperty(env, args[0], GROUP_ID_STR)) {
5934d6c458bSopenharmony_ci        napi_value napiTaskId = NapiHelper::GetNameProperty(env, args[0], TASKID_STR);
5944d6c458bSopenharmony_ci        if (napiTaskId == nullptr) {
5954d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the params must be task.");
5964d6c458bSopenharmony_ci            return nullptr;
5974d6c458bSopenharmony_ci        }
5984d6c458bSopenharmony_ci        uint64_t taskId = NapiHelper::GetUint64Value(env, napiTaskId);
5994d6c458bSopenharmony_ci        TaskManager::GetInstance().CancelTask(env, taskId);
6004d6c458bSopenharmony_ci    } else {
6014d6c458bSopenharmony_ci        napi_value napiGroupId = NapiHelper::GetNameProperty(env, args[0], GROUP_ID_STR);
6024d6c458bSopenharmony_ci        if (napiGroupId == nullptr) {
6034d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the params must be taskGroup.");
6044d6c458bSopenharmony_ci            return nullptr;
6054d6c458bSopenharmony_ci        }
6064d6c458bSopenharmony_ci        uint64_t groupId = NapiHelper::GetUint64Value(env, napiGroupId);
6074d6c458bSopenharmony_ci        TaskGroupManager::GetInstance().CancelGroup(env, groupId);
6084d6c458bSopenharmony_ci    }
6094d6c458bSopenharmony_ci    return nullptr;
6104d6c458bSopenharmony_ci}
6114d6c458bSopenharmony_ci
6124d6c458bSopenharmony_cinapi_value TaskPool::IsConcurrent(napi_env env, napi_callback_info cbinfo)
6134d6c458bSopenharmony_ci{
6144d6c458bSopenharmony_ci    size_t argc = 1;
6154d6c458bSopenharmony_ci    napi_value args[1];
6164d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
6174d6c458bSopenharmony_ci    if (argc != 1) {
6184d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of the params must be 1.");
6194d6c458bSopenharmony_ci        return nullptr;
6204d6c458bSopenharmony_ci    }
6214d6c458bSopenharmony_ci
6224d6c458bSopenharmony_ci    if (!NapiHelper::IsFunction(env, args[0])) {
6234d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be function.");
6244d6c458bSopenharmony_ci        return nullptr;
6254d6c458bSopenharmony_ci    }
6264d6c458bSopenharmony_ci
6274d6c458bSopenharmony_ci    bool isConcurrent = NapiHelper::IsConcurrentFunction(env, args[0]);
6284d6c458bSopenharmony_ci    return NapiHelper::CreateBooleanValue(env, isConcurrent);
6294d6c458bSopenharmony_ci}
6304d6c458bSopenharmony_ci
6314d6c458bSopenharmony_civoid TaskPool::PeriodicTaskCallback(uv_timer_t* handle)
6324d6c458bSopenharmony_ci{
6334d6c458bSopenharmony_ci    Task* task = reinterpret_cast<Task*>(handle->data);
6344d6c458bSopenharmony_ci    if (task == nullptr) {
6354d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: the task is nullptr");
6364d6c458bSopenharmony_ci        return;
6374d6c458bSopenharmony_ci    } else if (!task->IsPeriodicTask()) {
6384d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: the current task is not a periodic task");
6394d6c458bSopenharmony_ci        return;
6404d6c458bSopenharmony_ci    } else if (task->taskState_ == ExecuteState::CANCELED) {
6414d6c458bSopenharmony_ci        HILOG_DEBUG("taskpool:: the periodic task has been canceled");
6424d6c458bSopenharmony_ci        return;
6434d6c458bSopenharmony_ci    }
6444d6c458bSopenharmony_ci    TaskManager::GetInstance().IncreaseRefCount(task->taskId_);
6454d6c458bSopenharmony_ci
6464d6c458bSopenharmony_ci    if (!task->isFirstTaskInfo_) {
6474d6c458bSopenharmony_ci        napi_value napiTask = NapiHelper::GetReferenceValue(task->env_, task->taskRef_);
6484d6c458bSopenharmony_ci        TaskInfo* taskInfo = task->GetTaskInfo(task->env_, napiTask, task->periodicTaskPriority_);
6494d6c458bSopenharmony_ci        if (taskInfo == nullptr) {
6504d6c458bSopenharmony_ci            HILOG_DEBUG("taskpool:: the periodic task taskInfo is nullptr");
6514d6c458bSopenharmony_ci            return;
6524d6c458bSopenharmony_ci        }
6534d6c458bSopenharmony_ci    }
6544d6c458bSopenharmony_ci    task->isFirstTaskInfo_ = false;
6554d6c458bSopenharmony_ci
6564d6c458bSopenharmony_ci    task->IncreaseRefCount();
6574d6c458bSopenharmony_ci    HILOG_INFO("taskpool:: PeriodicTaskCallback taskId %{public}s", std::to_string(task->taskId_).c_str());
6584d6c458bSopenharmony_ci    if (task->taskState_ == ExecuteState::NOT_FOUND || task->taskState_ == ExecuteState::FINISHED) {
6594d6c458bSopenharmony_ci        task->taskState_ = ExecuteState::WAITING;
6604d6c458bSopenharmony_ci        TaskManager::GetInstance().EnqueueTaskId(task->taskId_, task->periodicTaskPriority_);
6614d6c458bSopenharmony_ci    }
6624d6c458bSopenharmony_ci}
6634d6c458bSopenharmony_ci
6644d6c458bSopenharmony_cinapi_value TaskPool::ExecutePeriodically(napi_env env, napi_callback_info cbinfo)
6654d6c458bSopenharmony_ci{
6664d6c458bSopenharmony_ci    int32_t period = 0;
6674d6c458bSopenharmony_ci    uint32_t priority = Priority::DEFAULT;
6684d6c458bSopenharmony_ci    Task* periodicTask = nullptr;
6694d6c458bSopenharmony_ci    if (!CheckPeriodicallyParams(env, cbinfo, period, priority, periodicTask)) {
6704d6c458bSopenharmony_ci        return nullptr;
6714d6c458bSopenharmony_ci    }
6724d6c458bSopenharmony_ci
6734d6c458bSopenharmony_ci    if (!periodicTask->CanExecutePeriodically(env)) {
6744d6c458bSopenharmony_ci        return nullptr;
6754d6c458bSopenharmony_ci    }
6764d6c458bSopenharmony_ci    periodicTask->UpdatePeriodicTask();
6774d6c458bSopenharmony_ci
6784d6c458bSopenharmony_ci    periodicTask->periodicTaskPriority_ = static_cast<Priority>(priority);
6794d6c458bSopenharmony_ci    napi_value napiTask = NapiHelper::GetReferenceValue(env, periodicTask->taskRef_);
6804d6c458bSopenharmony_ci    TaskInfo* taskInfo = periodicTask->GetTaskInfo(env, napiTask, periodicTask->periodicTaskPriority_);
6814d6c458bSopenharmony_ci    if (taskInfo == nullptr) {
6824d6c458bSopenharmony_ci        return nullptr;
6834d6c458bSopenharmony_ci    }
6844d6c458bSopenharmony_ci
6854d6c458bSopenharmony_ci    periodicTask->isFirstTaskInfo_ = true; // periodic task first Generate TaskInfo
6864d6c458bSopenharmony_ci
6874d6c458bSopenharmony_ci    TriggerTimer(env, periodicTask, period);
6884d6c458bSopenharmony_ci    return nullptr;
6894d6c458bSopenharmony_ci}
6904d6c458bSopenharmony_ci
6914d6c458bSopenharmony_civoid TaskPool::TriggerTimer(napi_env env, Task* task, int32_t period)
6924d6c458bSopenharmony_ci{
6934d6c458bSopenharmony_ci    HILOG_INFO("taskpool::TriggerTimer taskId %{public}s", std::to_string(task->taskId_).c_str());
6944d6c458bSopenharmony_ci    uv_loop_t* loop = NapiHelper::GetLibUV(env);
6954d6c458bSopenharmony_ci    task->timer_ = new uv_timer_t;
6964d6c458bSopenharmony_ci    uv_timer_init(loop, task->timer_);
6974d6c458bSopenharmony_ci    task->timer_->data = task;
6984d6c458bSopenharmony_ci    uv_update_time(loop);
6994d6c458bSopenharmony_ci    uv_timer_start(task->timer_, PeriodicTaskCallback, period, period);
7004d6c458bSopenharmony_ci    NativeEngine* engine = reinterpret_cast<NativeEngine*>(env);
7014d6c458bSopenharmony_ci    if (engine->IsMainThread()) {
7024d6c458bSopenharmony_ci        uv_async_send(&loop->wq_async);
7034d6c458bSopenharmony_ci    } else {
7044d6c458bSopenharmony_ci        uv_work_t* work = new uv_work_t;
7054d6c458bSopenharmony_ci        uv_queue_work_with_qos(loop, work, [](uv_work_t*) {},
7064d6c458bSopenharmony_ci                               [](uv_work_t* work, int32_t) { delete work; }, uv_qos_user_initiated);
7074d6c458bSopenharmony_ci    }
7084d6c458bSopenharmony_ci}
7094d6c458bSopenharmony_ci
7104d6c458bSopenharmony_cibool TaskPool::CheckDelayedParams(napi_env env, napi_callback_info cbinfo, uint32_t &priority, int32_t &delayTime,
7114d6c458bSopenharmony_ci                                  Task* &task)
7124d6c458bSopenharmony_ci{
7134d6c458bSopenharmony_ci    size_t argc = 3; // 3: delayTime, task and priority
7144d6c458bSopenharmony_ci    napi_value args[3]; // 3: delayTime, task and priority
7154d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
7164d6c458bSopenharmony_ci    if (argc < 2 || argc > 3) { // 2: delayTime and task 3: delayTime, task and priority
7174d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of params must be two or three.");
7184d6c458bSopenharmony_ci        return false;
7194d6c458bSopenharmony_ci    }
7204d6c458bSopenharmony_ci
7214d6c458bSopenharmony_ci    if (!NapiHelper::IsNumber(env, args[0])) {
7224d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be number.");
7234d6c458bSopenharmony_ci        return false;
7244d6c458bSopenharmony_ci    }
7254d6c458bSopenharmony_ci
7264d6c458bSopenharmony_ci    if (!NapiHelper::IsObject(env, args[1])) {
7274d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the second param must be object.");
7284d6c458bSopenharmony_ci        return false;
7294d6c458bSopenharmony_ci    }
7304d6c458bSopenharmony_ci
7314d6c458bSopenharmony_ci    delayTime = NapiHelper::GetInt32Value(env, args[0]);
7324d6c458bSopenharmony_ci    if (delayTime < 0) {
7334d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::ERR_DELAY_TIME_ERROR, "The delayTime is less than zero");
7344d6c458bSopenharmony_ci        return false;
7354d6c458bSopenharmony_ci    }
7364d6c458bSopenharmony_ci
7374d6c458bSopenharmony_ci    if (argc > 2) { // 2: the params might have priority
7384d6c458bSopenharmony_ci        if (!NapiHelper::IsNumber(env, args[2])) {
7394d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the third param must be number.");
7404d6c458bSopenharmony_ci            return false;
7414d6c458bSopenharmony_ci        }
7424d6c458bSopenharmony_ci        priority = NapiHelper::GetUint32Value(env, args[2]); // 2: get task priority
7434d6c458bSopenharmony_ci        if (priority >= Priority::NUMBER) {
7444d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value is error.");
7454d6c458bSopenharmony_ci            return false;
7464d6c458bSopenharmony_ci        }
7474d6c458bSopenharmony_ci    }
7484d6c458bSopenharmony_ci
7494d6c458bSopenharmony_ci    napi_unwrap(env, args[1], reinterpret_cast<void**>(&task));
7504d6c458bSopenharmony_ci    if (task == nullptr) {
7514d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of second param must be task");
7524d6c458bSopenharmony_ci        return false;
7534d6c458bSopenharmony_ci    }
7544d6c458bSopenharmony_ci    if (!task->CanExecuteDelayed(env)) {
7554d6c458bSopenharmony_ci        return false;
7564d6c458bSopenharmony_ci    }
7574d6c458bSopenharmony_ci    return true;
7584d6c458bSopenharmony_ci}
7594d6c458bSopenharmony_ci
7604d6c458bSopenharmony_cibool TaskPool::CheckPeriodicallyParams(napi_env env, napi_callback_info cbinfo, int32_t &period,
7614d6c458bSopenharmony_ci                                       uint32_t &priority, Task* &periodicTask)
7624d6c458bSopenharmony_ci{
7634d6c458bSopenharmony_ci    size_t argc = 3; // 3 : period, task, priority
7644d6c458bSopenharmony_ci    napi_value args[3]; // 3 : period, task, priority
7654d6c458bSopenharmony_ci    napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
7664d6c458bSopenharmony_ci    if (argc < 2 || argc > 3) { // 2 : period, task and 3 : period, task, priority
7674d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of params must be two or three.");
7684d6c458bSopenharmony_ci        return false;
7694d6c458bSopenharmony_ci    }
7704d6c458bSopenharmony_ci    if (!NapiHelper::IsNumber(env, args[0])) {
7714d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be number.");
7724d6c458bSopenharmony_ci        return false;
7734d6c458bSopenharmony_ci    }
7744d6c458bSopenharmony_ci    period = NapiHelper::GetInt32Value(env, args[0]);
7754d6c458bSopenharmony_ci    if (period < 0) {
7764d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::ERR_DELAY_TIME_ERROR, "The period value is less than zero.");
7774d6c458bSopenharmony_ci        return false;
7784d6c458bSopenharmony_ci    }
7794d6c458bSopenharmony_ci    if (!NapiHelper::IsObject(env, args[1])) {
7804d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the second param must be task.");
7814d6c458bSopenharmony_ci        return false;
7824d6c458bSopenharmony_ci    }
7834d6c458bSopenharmony_ci
7844d6c458bSopenharmony_ci    if (argc >= 3) { // 3 : third param maybe priority
7854d6c458bSopenharmony_ci        if (!NapiHelper::IsNumber(env, args[2])) { // 2 : priority
7864d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the third param must be priority.");
7874d6c458bSopenharmony_ci            return false;
7884d6c458bSopenharmony_ci        }
7894d6c458bSopenharmony_ci        priority = NapiHelper::GetUint32Value(env, args[2]); // 2 : priority
7904d6c458bSopenharmony_ci        if (priority >= Priority::NUMBER) {
7914d6c458bSopenharmony_ci            ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the value of the priority is invalid.");
7924d6c458bSopenharmony_ci            return false;
7934d6c458bSopenharmony_ci        }
7944d6c458bSopenharmony_ci    }
7954d6c458bSopenharmony_ci
7964d6c458bSopenharmony_ci    napi_unwrap(env, args[1], reinterpret_cast<void**>(&periodicTask));
7974d6c458bSopenharmony_ci    if (periodicTask == nullptr) {
7984d6c458bSopenharmony_ci        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the second param must be task.");
7994d6c458bSopenharmony_ci        return false;
8004d6c458bSopenharmony_ci    }
8014d6c458bSopenharmony_ci
8024d6c458bSopenharmony_ci    return true;
8034d6c458bSopenharmony_ci}
8044d6c458bSopenharmony_ci} // namespace Commonlibrary::Concurrent::TaskPoolModule
805