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