• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "task.h"
17 
18 #include "async_runner_manager.h"
19 #include "helper/concurrent_helper.h"
20 #include "helper/hitrace_helper.h"
21 #include "sequence_runner_manager.h"
22 #include "taskpool.h"
23 #include "worker.h"
24 
25 namespace Commonlibrary::Concurrent::TaskPoolModule {
26 static constexpr char ONRECEIVEDATA_STR[] = "onReceiveData";
27 static constexpr char SETTRANSFERLIST_STR[] = "setTransferList";
28 static constexpr char SET_CLONE_LIST_STR[] = "setCloneList";
29 static constexpr char ONENQUEUED_STR[] = "onEnqueued";
30 static constexpr char ONSTARTEXECUTION_STR[] = "onStartExecution";
31 static constexpr char ONEXECUTIONFAILED_STR[] = "onExecutionFailed";
32 static constexpr char ONEXECUTIONSUCCEEDED_STR[] = "onExecutionSucceeded";
33 static constexpr char ISDONE_STR[] = "isDone";
34 static constexpr char ON_RESULT_STR[] = "TaskPoolOnResultTask";
35 
36 const std::unordered_map<Priority, napi_event_priority> g_napiPriorityMap = {
37     {Priority::IDLE, napi_eprio_idle},
38     {Priority::LOW, napi_eprio_low},
39     {Priority::MEDIUM, napi_eprio_high},
40     {Priority::HIGH, napi_eprio_immediate},
41 };
42 
43 using namespace Commonlibrary::Concurrent::Common::Helper;
44 
TaskConstructor(napi_env env,napi_callback_info cbinfo)45 napi_value Task::TaskConstructor(napi_env env, napi_callback_info cbinfo)
46 {
47     // check argv count
48     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
49     std::string errMessage = "";
50     if (argc < 1) {
51         errMessage = "taskpool:: create task need more than one param";
52         HILOG_ERROR("%{public}s", errMessage.c_str());
53         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
54         return nullptr;
55     }
56     napi_value* args = new napi_value[argc];
57     ObjectScope<napi_value> scope(args, true);
58     napi_value thisVar = nullptr;
59     napi_value func = nullptr;
60     napi_value name = nullptr;
61     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
62     // if the first is task name, the second might be func
63     if (argc > 1 && NapiHelper::IsString(env, args[0])) {
64         name = args[0];
65         func = args[1];
66         args += 2; // 2: name and func
67         argc -= 2; // 2: name and func
68     } else {
69         func = args[0];
70         args += 1; // 1: func
71         argc -= 1; // 1: func
72     }
73     if (!NapiHelper::IsFunction(env, func)) {
74         errMessage = "taskpool:: the first or second param of task must be function";
75         HILOG_ERROR("%{public}s", errMessage.c_str());
76         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
77             "the type of the first or second param of task must be function.");
78         return nullptr;
79     }
80 
81     Task* task = GenerateTask(env, thisVar, func, name, args, argc);
82     napi_status status = napi_wrap(env, thisVar, task, TaskDestructor, nullptr, nullptr);
83     if (status != napi_ok) {
84         HILOG_ERROR("taskpool::TaskConstructor napi_wrap return value is %{public}d", status);
85         TaskManager::GetInstance().RemoveTask(task->taskId_);
86         delete task;
87         task = nullptr;
88         return nullptr;
89     }
90     napi_create_reference(env, thisVar, 0, &task->taskRef_);
91     if (!task->IsMainThreadTask()) {
92         napi_add_env_cleanup_hook(env, Task::CleanupHookFunc, task);
93     }
94     return thisVar;
95 }
96 
LongTaskConstructor(napi_env env,napi_callback_info cbinfo)97 napi_value Task::LongTaskConstructor(napi_env env, napi_callback_info cbinfo)
98 {
99     auto thisVar = TaskConstructor(env, cbinfo);
100     if (thisVar == nullptr) {
101         return nullptr;
102     }
103     Task* task;
104     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
105     task->isLongTask_ = true;
106     return thisVar;
107 }
108 
TaskDestructor(napi_env env,void * data,void * hint)109 void Task::TaskDestructor(napi_env env, void* data, [[maybe_unused]] void* hint)
110 {
111     Task* task = static_cast<Task*>(data);
112     HILOG_DEBUG("taskpool:: taskId:%{public}s TaskDestructor", std::to_string(task->taskId_).c_str());
113     if (!task->IsMainThreadTask()) {
114         napi_remove_env_cleanup_hook(env, Task::CleanupHookFunc, task);
115     }
116     // for performance, do not lock first
117     if (task->IsMainThreadTask() || task->lifecycleCount_ == 0) {
118         TaskManager::GetInstance().ReleaseTaskData(env, task);
119         napi_delete_reference(env, task->taskRef_);
120         delete task;
121         return;
122     }
123     bool shouldDelete = false;
124     {
125         std::lock_guard<std::recursive_mutex> lock(task->taskMutex_);
126         task->SetValid(false);
127         if (task->lifecycleCount_ == 0) {
128             shouldDelete = true;
129         }
130         TaskManager::GetInstance().ReleaseTaskData(env, task, shouldDelete);
131         napi_delete_reference(env, task->taskRef_);
132     }
133     if (shouldDelete) {
134         delete task;
135     }
136 }
137 
CleanupHookFunc(void * arg)138 void Task::CleanupHookFunc(void* arg)
139 {
140     if (arg == nullptr) {
141         HILOG_ERROR("taskpool:: cleanupHook arg is nullptr");
142         return;
143     }
144     Task* task = static_cast<Task*>(arg);
145     {
146         std::lock_guard<std::recursive_mutex> lock(task->taskMutex_);
147         ConcurrentHelper::UvHandleClose(task->onStartCancelSignal_);
148         ConcurrentHelper::UvHandleClose(task->onStartExecutionSignal_);
149         ConcurrentHelper::UvHandleClose(task->onStartDiscardSignal_);
150         if (task->IsFunctionTask()) {
151             task->SetValid(false);
152         }
153     }
154     if (task->IsAsyncRunnerTask()) {
155         AsyncRunnerManager::GetInstance().RemoveWaitingTask(task);
156     }
157     if (task->IsSeqRunnerTask()) {
158         SequenceRunnerManager::GetInstance().RemoveWaitingTask(task);
159     }
160 }
161 
Cancel(const uv_async_t * req)162 void Task::Cancel(const uv_async_t* req)
163 {
164     auto message = static_cast<CancelTaskMessage*>(req->data);
165     if (message == nullptr) {
166         HILOG_DEBUG("taskpool:: cancel message is nullptr");
167         return;
168     }
169     Task* task = TaskManager::GetInstance().GetTask(message->taskId);
170     if (task == nullptr) {
171         HILOG_DEBUG("taskpool:: cancel task is nullptr");
172         CloseHelp::DeletePointer(message, false);
173         return;
174     }
175     napi_status status = napi_ok;
176     HandleScope scope(task->env_, status);
177     if (status != napi_ok) {
178         HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
179         CloseHelp::DeletePointer(message, false);
180         return;
181     }
182     task->CancelInner(message->state);
183     CloseHelp::DeletePointer(message, false);
184 }
185 
GenerateTask(napi_env env,napi_value napiTask,napi_value func,napi_value name,napi_value * args,size_t argc)186 Task* Task::GenerateTask(napi_env env, napi_value napiTask, napi_value func,
187                          napi_value name, napi_value* args, size_t argc)
188 {
189     HILOG_DEBUG("taskpool:: task GenerateTask");
190     napi_value argsArray = NapiHelper::CreateArrayWithLength(env, argc);
191     for (size_t i = 0; i < argc; i++) {
192         napi_set_element(env, argsArray, i, args[i]);
193     }
194     if (name == nullptr) {
195         name = NapiHelper::GetNameProperty(env, func, NAME);
196     }
197     char* nameStr = NapiHelper::GetChars(env, name);
198     Task* task = new Task(env, TaskType::TASK, nameStr);
199     delete[] nameStr;
200     TaskManager::GetInstance().StoreTask(task);
201     task->InitHandle(env);
202 
203     napi_value taskId = NapiHelper::CreateUint32(env, task->taskId_);
204     napi_set_named_property(env, napiTask, FUNCTION_STR, func);
205     napi_set_named_property(env, napiTask, TASKID_STR, taskId);
206     napi_set_named_property(env, napiTask, ARGUMENTS_STR, argsArray);
207     napi_property_descriptor properties[] = {
208         DECLARE_NAPI_FUNCTION(SETTRANSFERLIST_STR, SetTransferList),
209         DECLARE_NAPI_FUNCTION(SET_CLONE_LIST_STR, SetCloneList),
210         DECLARE_NAPI_FUNCTION(ONRECEIVEDATA_STR, OnReceiveData),
211         DECLARE_NAPI_FUNCTION(ADD_DEPENDENCY_STR, AddDependency),
212         DECLARE_NAPI_FUNCTION(REMOVE_DEPENDENCY_STR, RemoveDependency),
213         DECLARE_NAPI_FUNCTION(ONENQUEUED_STR, OnEnqueued),
214         DECLARE_NAPI_FUNCTION(ONSTARTEXECUTION_STR, OnStartExecution),
215         DECLARE_NAPI_FUNCTION(ONEXECUTIONFAILED_STR, OnExecutionFailed),
216         DECLARE_NAPI_FUNCTION(ONEXECUTIONSUCCEEDED_STR, OnExecutionSucceeded),
217         DECLARE_NAPI_FUNCTION(ISDONE_STR, IsDone),
218         DECLARE_NAPI_GETTER(TASK_TOTAL_TIME, GetTotalDuration),
219         DECLARE_NAPI_GETTER(TASK_CPU_TIME, GetCPUDuration),
220         DECLARE_NAPI_GETTER(TASK_IO_TIME, GetIODuration),
221         DECLARE_NAPI_GETTER(NAME, GetName),
222         DECLARE_NAPI_GETTER(TASKID_STR, GetTaskId)
223     };
224     napi_define_properties(env, napiTask, sizeof(properties) / sizeof(properties[0]), properties);
225     return task;
226 }
227 
GenerateFunctionTask(napi_env env,napi_value func,napi_value * args,size_t argc,TaskType type)228 Task* Task::GenerateFunctionTask(napi_env env, napi_value func, napi_value* args, size_t argc, TaskType type)
229 {
230     HILOG_DEBUG("taskpool:: task GenerateFunctionTask");
231     napi_value argsArray;
232     napi_create_array_with_length(env, argc, &argsArray);
233     for (size_t i = 0; i < argc; i++) {
234         napi_set_element(env, argsArray, i, args[i]);
235     }
236     napi_value undefined = NapiHelper::GetUndefinedValue(env);
237     TaskInfo* taskInfo = GenerateTaskInfo(env, func, argsArray, undefined, undefined, Priority::DEFAULT);
238     if (taskInfo == nullptr) {
239         HILOG_ERROR("taskpool:: task GenerateFunctionTask end, taskInfo is nullptr");
240         return nullptr;
241     }
242     napi_value napiFuncName = NapiHelper::GetNameProperty(env, func, NAME);
243     char* nameStr = NapiHelper::GetChars(env, napiFuncName);
244     Task* task = new Task(env, type, nameStr);
245     delete[] nameStr;
246     task->currentTaskInfo_ = taskInfo;
247     task->InitHandle(env);
248     if (!task->IsMainThreadTask()) {
249         napi_add_env_cleanup_hook(env, CleanupHookFunc, task);
250     }
251     TaskManager::GetInstance().StoreTask(task);
252     return task;
253 }
254 
GetTaskInfoPromise(napi_env env,napi_value task,TaskType taskType,Priority priority)255 napi_value Task::GetTaskInfoPromise(napi_env env, napi_value task, TaskType taskType, Priority priority)
256 {
257     TaskInfo* taskInfo = GetTaskInfo(env, task, priority);
258     if (taskInfo == nullptr) {
259         return nullptr;
260     }
261     UpdateTaskType(taskType);
262     return NapiHelper::CreatePromise(env, &taskInfo->deferred);
263 }
264 
GetTaskInfo(napi_env env,napi_value napiTask,Priority priority)265 TaskInfo* Task::GetTaskInfo(napi_env env, napi_value napiTask, Priority priority)
266 {
267     auto [func, args, transferList, cloneList] = GetSerializeParams(env, napiTask);
268     if (func == nullptr || args == nullptr) {
269         return nullptr;
270     }
271 
272     TaskInfo* pendingInfo = GenerateTaskInfo(env, func, args, transferList, cloneList, priority,
273                                              defaultTransfer_, defaultCloneSendable_);
274     if (pendingInfo == nullptr) {
275         return nullptr;
276     }
277     {
278         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
279         if (currentTaskInfo_ == nullptr) {
280             currentTaskInfo_ = pendingInfo;
281         } else {
282             pendingTaskInfos_.push_back(pendingInfo);
283         }
284     }
285     if (name_.empty()) {
286         napi_value funcName = NapiHelper::GetNameProperty(env, func, NAME);
287         name_ = NapiHelper::GetString(env, funcName);
288     }
289     return pendingInfo;
290 }
291 
SetTransferList(napi_env env,napi_callback_info cbinfo)292 napi_value Task::SetTransferList(napi_env env, napi_callback_info cbinfo)
293 {
294     size_t argc = 1;
295     napi_value args[1];
296     napi_value thisVar;
297     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
298     // Check whether clone list has been set
299     if (NapiHelper::HasNameProperty(env, thisVar, CLONE_LIST_STR)) {
300         ErrorHelper::ThrowError(env, ErrorHelper::ERR_IN_BOTH_CLONE_AND_TRANSFER);
301         return nullptr;
302     }
303     if (argc > 1) {
304         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
305             "the number of setTransferList parma must be less than 2.");
306         return nullptr;
307     }
308     Task* task = nullptr;
309     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
310     if (task == nullptr) {
311         HILOG_ERROR("taskpool:: task is nullptr");
312         return nullptr;
313     }
314     napi_value undefined = NapiHelper::GetUndefinedValue(env);
315     napi_value falseVal = NapiHelper::CreateBooleanValue(env, false);
316     if (argc == 0) {
317         HILOG_DEBUG("taskpool:: set task params not transfer");
318         napi_set_named_property(env, thisVar, TRANSFERLIST_STR, undefined);
319         // set task.defaultTransfer false
320         task->defaultTransfer_ = false;
321         return nullptr;
322     }
323     if (!NapiHelper::IsArray(env, args[0])) {
324         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
325             "the type of setTransferList first param must be array.");
326         return nullptr;
327     }
328     // set task.defaultTransfer false
329     task->defaultTransfer_ = false;
330     uint32_t arrayLength = NapiHelper::GetArrayLength(env, args[0]);
331     if (arrayLength == 0) {
332         HILOG_DEBUG("taskpool:: set task params not transfer");
333         napi_set_named_property(env, thisVar, TRANSFERLIST_STR, undefined);
334         return nullptr;
335     }
336     for (size_t i = 0; i < arrayLength; i++) {
337         napi_value transferVal = NapiHelper::GetElement(env, args[0], i);
338         if (!NapiHelper::IsArrayBuffer(env, transferVal)) {
339             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
340                 "the type of the element in array must be arraybuffer.");
341             return nullptr;
342         }
343     }
344     HILOG_DEBUG("taskpool:: check setTransferList param success");
345     napi_set_named_property(env, thisVar, TRANSFERLIST_STR, args[0]);
346     return nullptr;
347 }
348 
SetCloneList(napi_env env,napi_callback_info cbinfo)349 napi_value Task::SetCloneList(napi_env env, napi_callback_info cbinfo)
350 {
351     size_t argc = 1;
352     napi_value args[1];
353     napi_value thisVar;
354     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
355     // Check whether transfer list has been set
356     if (NapiHelper::HasNameProperty(env, thisVar, TRANSFERLIST_STR)) {
357         ErrorHelper::ThrowError(env, ErrorHelper::ERR_IN_BOTH_CLONE_AND_TRANSFER);
358         return nullptr;
359     }
360     if (argc != 1) {
361         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of setCloneList parma must be 1.");
362         return nullptr;
363     }
364     if (!NapiHelper::IsArray(env, args[0])) {
365         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of setCloneList first param must be array.");
366         return nullptr;
367     }
368     Task* task = nullptr;
369     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
370     if (task == nullptr) {
371         HILOG_ERROR("taskpool:: task is nullptr");
372         return nullptr;
373     }
374     napi_value undefined = NapiHelper::GetUndefinedValue(env);
375     uint32_t arrayLength = NapiHelper::GetArrayLength(env, args[0]);
376     if (arrayLength == 0) {
377         HILOG_DEBUG("taskpool:: clone list is empty");
378         napi_set_named_property(env, thisVar, CLONE_LIST_STR, undefined);
379         return nullptr;
380     }
381     for (size_t i = 0; i < arrayLength; i++) {
382         napi_value cloneVal = NapiHelper::GetElement(env, args[0], i);
383         if (NapiHelper::IsBitVector(env, cloneVal)) {
384             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "BitVector not support setCloneList.");
385             return nullptr;
386         }
387         if (!NapiHelper::IsArrayBuffer(env, cloneVal) && !NapiHelper::IsSendable(env, cloneVal)) {
388             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
389                 "the type of setCloneList elements in array must be arraybuffer or sendable.");
390             return nullptr;
391         }
392     }
393     napi_set_named_property(env, thisVar, CLONE_LIST_STR, args[0]);
394     return nullptr;
395 }
396 
IsCanceled(napi_env env,napi_callback_info cbinfo)397 napi_value Task::IsCanceled(napi_env env, napi_callback_info cbinfo)
398 {
399     bool isCanceled = false;
400     auto engine = reinterpret_cast<NativeEngine*>(env);
401     if (!engine->IsTaskPoolThread()) {
402         HILOG_ERROR("taskpool:: call isCanceled not in taskpool thread");
403         return NapiHelper::CreateBooleanValue(env, isCanceled);
404     }
405     // Get task and query task cancel state
406     void* data = engine->GetCurrentTaskInfo();
407     if (data == nullptr) {
408         HILOG_ERROR("taskpool:: call isCanceled not in Concurrent function");
409     } else {
410         Task* task = static_cast<Task*>(data);
411         isCanceled = task->taskState_ == ExecuteState::CANCELED ? true : false;
412     }
413     return NapiHelper::CreateBooleanValue(env, isCanceled);
414 }
415 
OnReceiveData(napi_env env,napi_callback_info cbinfo)416 napi_value Task::OnReceiveData(napi_env env, napi_callback_info cbinfo)
417 {
418     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
419     if (argc >= 2) { // 2: the number of parmas
420         HILOG_ERROR("taskpool:: the number of OnReceiveData parma must be less than 2");
421         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
422             "the number of OnReceiveData parma must be less than 2.");
423         return nullptr;
424     }
425 
426     napi_value thisVar;
427     if (argc == 0) {
428         HILOG_INFO("taskpool:: Set taskpool.Task.onReceiveData to undefined");
429         napi_get_cb_info(env, cbinfo, &argc, nullptr, &thisVar, nullptr);
430         napi_value id = NapiHelper::GetNameProperty(env, thisVar, "taskId");
431         uint32_t taskId = NapiHelper::GetUint32Value(env, id);
432         TaskManager::GetInstance().RegisterCallback(env, taskId, nullptr, "OnReceiveData: Cancel listener");
433         return nullptr;
434     }
435 
436     napi_value args[1];
437     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
438     napi_valuetype type;
439     NAPI_CALL(env, napi_typeof(env, args[0], &type));
440     if (type != napi_function) {
441         HILOG_ERROR("taskpool:: OnReceiveData's parameter should be function");
442         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
443             "the type of onReceiveData's parameter must be function.");
444         return nullptr;
445     }
446     // store callbackInfo
447     napi_value napiTaskId = NapiHelper::GetNameProperty(env, thisVar, "taskId");
448     uint32_t taskId = NapiHelper::GetUint32Value(env, napiTaskId);
449     auto task = TaskManager::GetInstance().GetTask(taskId);
450     if (task == nullptr) {
451         HILOG_ERROR("taskpool:: OnReceiveData's task is nullptr");
452         return nullptr;
453     }
454     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
455     std::shared_ptr<CallbackInfo> callbackInfo = std::make_shared<CallbackInfo>(env, 1, callbackRef);
456     TaskManager::GetInstance().RegisterCallback(env, taskId, callbackInfo, "OnReceiveData: Add listener");
457     return nullptr;
458 }
459 
SendData(napi_env env,napi_callback_info cbinfo)460 napi_value Task::SendData(napi_env env, napi_callback_info cbinfo)
461 {
462     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
463     napi_value args[argc];
464     napi_get_cb_info(env, cbinfo, &argc, args, nullptr, nullptr);
465 
466     napi_value argsArray;
467     napi_create_array_with_length(env, argc, &argsArray);
468     for (size_t i = 0; i < argc; i++) {
469         napi_set_element(env, argsArray, i, args[i]);
470     }
471 
472     auto engine = reinterpret_cast<NativeEngine*>(env);
473     if (!engine->IsTaskPoolThread()) {
474         HILOG_ERROR("taskpool:: SendData is not called in the taskpool thread");
475         ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_IN_TASKPOOL_THREAD);
476         return nullptr;
477     }
478     void* data = engine->GetCurrentTaskInfo();
479     if (data == nullptr) {
480         HILOG_ERROR("taskpool:: SendData is not called in the concurrent function");
481         ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_IN_CONCURRENT_FUNCTION);
482         return nullptr;
483     }
484 
485     Task* task = static_cast<Task*>(data);
486     napi_value undefined = NapiHelper::GetUndefinedValue(env);
487     void* serializationArgs = nullptr;
488     bool defaultClone = false;
489     bool defaultTransfer = true;
490     std::string errString = "";
491     napi_status status = napi_serialize_inner_with_error(env, argsArray, undefined, undefined, defaultTransfer,
492                                                          defaultClone, &serializationArgs, errString);
493     if (status != napi_ok || serializationArgs == nullptr) {
494         std::string errMessage = "taskpool:: failed to serialize function.\nSerialize error: " + errString;
495         HILOG_ERROR("%{public}s in SendData", errMessage.c_str());
496         ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
497         return nullptr;
498     }
499 
500     TaskResultInfo* resultInfo = new TaskResultInfo(env, task->GetTaskId(), serializationArgs);
501     TaskManager::GetInstance().ExecuteSendData(env, resultInfo, task);
502     return nullptr;
503 }
504 
AddDependency(napi_env env,napi_callback_info cbinfo)505 napi_value Task::AddDependency(napi_env env, napi_callback_info cbinfo)
506 {
507     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
508     if (argc == 0) {
509         std::string errMessage = "taskpool:: addDependency has no params";
510         HILOG_ERROR("%{public}s", errMessage.c_str());
511         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "addDependency has no params.");
512         return nullptr;
513     }
514 
515     napi_status status = napi_ok;
516     HandleScope scope(env, status);
517     napi_value args[argc];
518     napi_value napiTask;
519     napi_get_cb_info(env, cbinfo, &argc, args, &napiTask, nullptr);
520     Task* task = nullptr;
521     napi_unwrap(env, napiTask, reinterpret_cast<void**>(&task));
522     if (task == nullptr) {
523         HILOG_ERROR("taskpool:: task is nullptr");
524         return nullptr;
525     }
526     std::string errMessage = "";
527     if (task->IsPeriodicTask()) {
528         HILOG_ERROR("taskpool:: the periodic task cannot have a dependency");
529         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
530         return nullptr;
531     }
532     if (task->IsCommonTask() || task->IsSeqRunnerTask()) {
533         errMessage = "taskpool:: seqRunnerTask or executedTask cannot addDependency";
534         HILOG_ERROR("%{public}s", errMessage.c_str());
535         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
536         return nullptr;
537     }
538     if (task->IsAsyncRunnerTask()) {
539         HILOG_ERROR("taskpool:: AsyncRunnerTask cannot addDependency.");
540         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY);
541         return nullptr;
542     }
543     if (task->IsGroupCommonTask()) {
544         errMessage = "taskpool:: groupTask cannot addDependency";
545         HILOG_ERROR("%{public}s", errMessage.c_str());
546         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
547         return nullptr;
548     }
549     task->SetHasDependency(true);
550     std::set<uint32_t> idSet;
551     for (size_t i = 0; i < argc; i++) {
552         if (!NapiHelper::HasNameProperty(env, args[i], TASKID_STR)) {
553             errMessage = "taskpool:: addDependency param is not task";
554             HILOG_ERROR("%{public}s", errMessage.c_str());
555             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the addDependency param must be task.");
556             return nullptr;
557         } else {
558             Task* dependentTask = nullptr;
559             napi_unwrap(env, args[i], reinterpret_cast<void**>(&dependentTask));
560             if (dependentTask == nullptr) {
561                 HILOG_ERROR("taskpool:: dependentTask is nullptr");
562                 return nullptr;
563             }
564             if (dependentTask->taskId_ == task->taskId_) {
565                 HILOG_ERROR("taskpool:: there is a circular dependency");
566                 ErrorHelper::ThrowError(env, ErrorHelper::ERR_CIRCULAR_DEPENDENCY);
567                 return nullptr;
568             }
569             if (dependentTask->IsPeriodicTask()) {
570                 HILOG_ERROR("taskpool:: the periodic task cannot have a dependency");
571                 ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
572                 return nullptr;
573             }
574             if (dependentTask->IsCommonTask() || dependentTask->IsSeqRunnerTask()) {
575                 errMessage = "taskpool:: seqRunnerTask or executedTask cannot be relied on";
576                 HILOG_ERROR("%{public}s", errMessage.c_str());
577                 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
578                 return nullptr;
579             }
580             if (dependentTask->IsAsyncRunnerTask()) {
581                 HILOG_ERROR("taskpool:: AsyncRunnerTask cannot be relied on.");
582                 ErrorHelper::ThrowError(env, ErrorHelper::ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY);
583                 return nullptr;
584             }
585             if (dependentTask->IsGroupCommonTask()) {
586                 errMessage = "taskpool:: groupTask cannot be relied on";
587                 HILOG_ERROR("%{public}s", errMessage.c_str());
588                 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
589                 return nullptr;
590             }
591             idSet.emplace(dependentTask->taskId_);
592             dependentTask->SetHasDependency(true);
593         }
594     }
595     if (!TaskManager::GetInstance().StoreTaskDependency(task->taskId_, idSet)) {
596         HILOG_ERROR("taskpool:: there is a circular dependency");
597         ErrorHelper::ThrowError(env, ErrorHelper::ERR_CIRCULAR_DEPENDENCY);
598     }
599     std::string strTrace = "Task::AddDependency: ";
600     HITRACE_HELPER_METER_NAME(strTrace + TaskManager::GetInstance().GetTaskDependInfoToString(task->taskId_));
601     return nullptr;
602 }
603 
RemoveDependency(napi_env env,napi_callback_info cbinfo)604 napi_value Task::RemoveDependency(napi_env env, napi_callback_info cbinfo)
605 {
606     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
607     if (argc == 0) {
608         std::string errMessage = "taskpool:: removeDependency has no params";
609         HILOG_ERROR("%{public}s", errMessage.c_str());
610         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "removeDependency has no params.");
611         return nullptr;
612     }
613     napi_status status = napi_ok;
614     HandleScope scope(env, status);
615     napi_value args[argc];
616     napi_value napiTask;
617     napi_get_cb_info(env, cbinfo, &argc, args, &napiTask, nullptr);
618     Task* task = nullptr;
619     napi_unwrap(env, napiTask, reinterpret_cast<void**>(&task));
620     if (task == nullptr) {
621         HILOG_ERROR("taskpool:: the task is nullptr");
622         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the task is nullptr");
623         return nullptr;
624     }
625     if (!task->HasDependency()) {
626         ThrowNoDependencyError(env);
627         return nullptr;
628     }
629     if (task->IsPeriodicTask()) {
630         HILOG_ERROR("taskpool:: the periodic task cannot call removeDependency");
631         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
632         return nullptr;
633     }
634     if (task->IsCommonTask()) {
635         std::string errMessage = "taskpool:: executedTask cannot removeDependency";
636         HILOG_ERROR("%{public}s", errMessage.c_str());
637         ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY, errMessage.c_str());
638         return nullptr;
639     }
640     if (task->IsAsyncRunnerTask()) {
641         HILOG_ERROR("taskpool:: AsyncRunnerTask cannot call removeDependency.");
642         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY);
643         return nullptr;
644     }
645     for (size_t i = 0; i < argc; i++) {
646         if (!NapiHelper::HasNameProperty(env, args[i], TASKID_STR)) {
647             std::string errMessage = "taskpool:: removeDependency param is not task";
648             HILOG_ERROR("%{public}s", errMessage.c_str());
649             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of removeDependency param must be task.");
650             return nullptr;
651         }
652         Task* dependentTask = nullptr;
653         napi_unwrap(env, args[i], reinterpret_cast<void**>(&dependentTask));
654         if (dependentTask == nullptr) {
655             HILOG_ERROR("taskpool:: the dependent task is nullptr");
656             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,  "the dependent task is nullptr");
657             return nullptr;
658         }
659         if (!dependentTask->HasDependency()) {
660             ThrowNoDependencyError(env);
661             return nullptr;
662         }
663         if (dependentTask->IsPeriodicTask()) {
664             HILOG_ERROR("taskpool:: the periodic task cannot call removeDependency");
665             ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
666             return nullptr;
667         }
668         if (dependentTask->IsCommonTask()) {
669             std::string errMessage = "taskpool:: cannot removeDependency on a dependent and executed task";
670             HILOG_ERROR("%{public}s", errMessage.c_str());
671             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
672             return nullptr;
673         }
674         if (dependentTask->IsAsyncRunnerTask()) {
675             HILOG_ERROR("taskpool:: AsyncRunnerTask cannot call removeDependency.");
676             ErrorHelper::ThrowError(env, ErrorHelper::ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY);
677             return nullptr;
678         }
679         if (!TaskManager::GetInstance().RemoveTaskDependency(task->taskId_, dependentTask->taskId_)) {
680             HILOG_ERROR("taskpool:: the dependency does not exist");
681             ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY);
682             return nullptr;
683         }
684         dependentTask->TryClearHasDependency();
685     }
686     task->TryClearHasDependency();
687     std::string strTrace = "Task::RemoveDependency: ";
688     HITRACE_HELPER_METER_NAME(strTrace + TaskManager::GetInstance().GetTaskDependInfoToString(task->taskId_));
689     return nullptr;
690 }
691 
StartExecutionCallback(const uv_async_t * req)692 void Task::StartExecutionCallback(const uv_async_t* req)
693 {
694     HILOG_DEBUG("taskpool:: task StartExecutionCallback");
695     auto listenerCallBackInfo = static_cast<ListenerCallBackInfo*>(req->data);
696     if (listenerCallBackInfo == nullptr) { // LCOV_EXCL_BR_LINE
697         HILOG_FATAL("taskpool:: StartExecutionCallBackInfo is null");
698         return;
699     }
700     StartExecutionTask(listenerCallBackInfo);
701 }
702 
StartExecutionTask(ListenerCallBackInfo * listenerCallBackInfo)703 void Task::StartExecutionTask(ListenerCallBackInfo* listenerCallBackInfo)
704 {
705     auto env = listenerCallBackInfo->env_;
706     napi_status status = napi_ok;
707     HandleScope scope(env, status);
708     if (status != napi_ok) {
709         HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
710         return;
711     }
712     auto func = NapiHelper::GetReferenceValue(env, listenerCallBackInfo->callbackRef_);
713     if (func == nullptr) {
714         HILOG_INFO("taskpool:: StartExecutionCallback func is null");
715         return;
716     }
717 
718     napi_value result;
719     napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 0, nullptr, &result);
720     if (NapiHelper::IsExceptionPending(env)) {
721         napi_value exception = nullptr;
722         napi_get_and_clear_last_exception(env, &exception);
723         std::string funcStr = NapiHelper::GetPrintString(env, func);
724         HILOG_ERROR("taskpool:: an exception has occurred napi_call_function, func is %{public}s", funcStr.c_str());
725     }
726 }
727 
ExecuteListenerCallback(ListenerCallBackInfo * listenerCallBackInfo,uint32_t taskId)728 void Task::ExecuteListenerCallback(ListenerCallBackInfo* listenerCallBackInfo, uint32_t taskId)
729 {
730     HILOG_DEBUG("taskpool:: task ExecuteListenerCallback");
731     if (listenerCallBackInfo == nullptr) { // LCOV_EXCL_BR_LINE
732         HILOG_FATAL("taskpool:: listenerCallBackInfo is null");
733         return;
734     }
735 
736     napi_env env = listenerCallBackInfo->env_;
737     napi_value func = NapiHelper::GetReferenceValue(env, listenerCallBackInfo->callbackRef_);
738     if (func == nullptr) {
739         HILOG_INFO("taskpool:: ExecuteListenerCallback func is null");
740         return;
741     }
742 
743     std::string callbackType = listenerCallBackInfo->type_;
744     HITRACE_HELPER_METER_NAME("ExecuteListenerCallback: type = " + callbackType + ", taskId = " +
745         std::to_string(taskId));
746 
747     napi_value result;
748     napi_value args = listenerCallBackInfo->taskError_;
749     if (args != nullptr) {
750         napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 1, &args, &result);
751     } else {
752         napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 0, nullptr, &result);
753     }
754 
755     if (NapiHelper::IsExceptionPending(env)) {
756         napi_value exception = nullptr;
757         napi_get_and_clear_last_exception(env, &exception);
758         std::string funcStr = NapiHelper::GetPrintString(env, func);
759         HILOG_ERROR("taskpool:: an exception has occurred napi_call_function, func is %{public}s", funcStr.c_str());
760     }
761 }
762 
OnEnqueued(napi_env env,napi_callback_info cbinfo)763 napi_value Task::OnEnqueued(napi_env env, napi_callback_info cbinfo)
764 {
765     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
766     napi_value thisVar;
767     if (argc == 0) {
768         HILOG_INFO("taskpool:: the number of the params must be one");
769         return nullptr;
770     }
771 
772     napi_value args[1];
773     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
774     napi_valuetype type;
775     NAPI_CALL(env, napi_typeof(env, args[0], &type));
776     if (type != napi_function) {
777         HILOG_ERROR("taskpool:: OnEnqueued's parameter should be function");
778         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of OnEnqueued's parameter must be function.");
779         return nullptr;
780     }
781 
782     Task* task = nullptr;
783     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
784     if (task == nullptr) {
785         HILOG_ERROR("taskpool:: task is nullptr");
786         return nullptr;
787     }
788 
789     if (task->taskState_ != ExecuteState::NOT_FOUND) {
790         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
791         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
792         return nullptr;
793     }
794 
795     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
796     task->onEnqueuedCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
797     task->onEnqueuedCallBackInfo_->type_ = "onEnqueued";
798     return nullptr;
799 }
800 
OnStartExecution(napi_env env,napi_callback_info cbinfo)801 napi_value Task::OnStartExecution(napi_env env, napi_callback_info cbinfo)
802 {
803     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
804     napi_value thisVar;
805     if (argc == 0) {
806         HILOG_INFO("taskpool:: the number of the params must be one");
807         return nullptr;
808     }
809 
810     napi_value args[1];
811     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
812     napi_valuetype type;
813     NAPI_CALL(env, napi_typeof(env, args[0], &type));
814     if (type != napi_function) {
815         HILOG_ERROR("taskpool:: OnStartExecution's parameter should be function");
816         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
817             "the type of OnStartExecution's parameter must be function.");
818         return nullptr;
819     }
820 
821     Task* task = nullptr;
822     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
823     if (task == nullptr) {
824         HILOG_ERROR("taskpool:: task is nullptr");
825         return nullptr;
826     }
827 
828     if (task->taskState_ != ExecuteState::NOT_FOUND) {
829         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
830         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
831         return nullptr;
832     }
833 
834     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
835     task->onStartExecutionCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
836     task->onStartExecutionCallBackInfo_->type_ = "onStartExecution";
837 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
838     if (!task->IsMainThreadTask()) {
839         auto loop = NapiHelper::GetLibUV(env);
840         ConcurrentHelper::UvHandleInit(loop, task->onStartExecutionSignal_,
841             Task::StartExecutionCallback, task->onStartExecutionCallBackInfo_);
842     }
843 #else
844     auto loop = NapiHelper::GetLibUV(env);
845     ConcurrentHelper::UvHandleInit(loop, task->onStartExecutionSignal_,
846         Task::StartExecutionCallback, task->onStartExecutionCallBackInfo_);
847 #endif
848 
849     return nullptr;
850 }
851 
OnExecutionFailed(napi_env env,napi_callback_info cbinfo)852 napi_value Task::OnExecutionFailed(napi_env env, napi_callback_info cbinfo)
853 {
854     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
855     napi_value thisVar;
856     if (argc == 0) {
857         HILOG_INFO("taskpool:: the number of the params must be one");
858         return nullptr;
859     }
860 
861     napi_value args[1];
862     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
863     napi_valuetype type;
864     NAPI_CALL(env, napi_typeof(env, args[0], &type));
865     if (type != napi_function) {
866         HILOG_ERROR("taskpool:: OnExecutionFailed's parameter should be function");
867         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
868             "the type of OnExecutionFailed's parameter must be function.");
869         return nullptr;
870     }
871 
872     Task* task = nullptr;
873     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
874     if (task == nullptr) {
875         HILOG_ERROR("taskpool:: task is nullptr");
876         return nullptr;
877     }
878 
879     if (task->taskState_ != ExecuteState::NOT_FOUND) {
880         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
881         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
882         return nullptr;
883     }
884 
885     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
886     task->onExecutionFailedCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
887     task->onExecutionFailedCallBackInfo_->type_ = "onExecutionFailed";
888     return nullptr;
889 }
890 
OnExecutionSucceeded(napi_env env,napi_callback_info cbinfo)891 napi_value Task::OnExecutionSucceeded(napi_env env, napi_callback_info cbinfo)
892 {
893     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
894     napi_value thisVar;
895     if (argc == 0) {
896         HILOG_INFO("taskpool:: the number of the params must be one");
897         return nullptr;
898     }
899 
900     napi_value args[1];
901     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
902     napi_valuetype type;
903     NAPI_CALL(env, napi_typeof(env, args[0], &type));
904     if (type != napi_function) {
905         HILOG_ERROR("taskpool:: OnExecutionSucceeded's parameter should be function");
906         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
907             "the type of OnExecutionSucceeded's parameter must be function");
908         return nullptr;
909     }
910 
911     Task* task = nullptr;
912     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
913     if (task == nullptr) {
914         HILOG_ERROR("taskpool:: task is nullptr");
915         return nullptr;
916     }
917 
918     if (task->taskState_ != ExecuteState::NOT_FOUND) {
919         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
920         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
921         return nullptr;
922     }
923 
924     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
925     task->onExecutionSucceededCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
926     task->onExecutionSucceededCallBackInfo_->type_ = "onExecutionSucceeded";
927     return nullptr;
928 }
929 
IsDone(napi_env env,napi_callback_info cbinfo)930 napi_value Task::IsDone(napi_env env, napi_callback_info cbinfo)
931 {
932     napi_value thisVar = nullptr;
933     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
934     Task* task = nullptr;
935     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
936     if (task == nullptr) {
937         HILOG_ERROR("taskpool:: task is nullptr");
938         return NapiHelper::CreateBooleanValue(env, false);
939     }
940 
941     if (task->taskState_ == ExecuteState::FINISHED || task->taskState_ == ExecuteState::ENDING) {
942         return NapiHelper::CreateBooleanValue(env, true);
943     }
944     return NapiHelper::CreateBooleanValue(env, false);
945 }
946 
GetTaskDuration(napi_env env,napi_callback_info & cbinfo,std::string durationType)947 napi_value Task::GetTaskDuration(napi_env env, napi_callback_info& cbinfo, std::string durationType)
948 {
949     napi_value thisVar = nullptr;
950     Task* task = nullptr;
951     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
952     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
953     if (task == nullptr) {
954         uint64_t totalDuration = 0;
955         return NapiHelper::CreateUint32(env, totalDuration);
956     }
957     uint64_t totalDuration = TaskManager::GetInstance().GetTaskDuration(task->taskId_, durationType);
958     return NapiHelper::CreateUint32(env, totalDuration);
959 }
960 
GetTotalDuration(napi_env env,napi_callback_info cbinfo)961 napi_value Task::GetTotalDuration(napi_env env, napi_callback_info cbinfo)
962 {
963     return GetTaskDuration(env, cbinfo, TASK_TOTAL_TIME);
964 }
965 
GetCPUDuration(napi_env env,napi_callback_info cbinfo)966 napi_value Task::GetCPUDuration(napi_env env, napi_callback_info cbinfo)
967 {
968     return GetTaskDuration(env, cbinfo, TASK_CPU_TIME);
969 }
970 
GetIODuration(napi_env env,napi_callback_info cbinfo)971 napi_value Task::GetIODuration(napi_env env, napi_callback_info cbinfo)
972 {
973     return GetTaskDuration(env, cbinfo, TASK_IO_TIME);
974 }
975 
GetName(napi_env env,napi_callback_info cbinfo)976 napi_value Task::GetName(napi_env env, napi_callback_info cbinfo)
977 {
978     napi_value thisVar = nullptr;
979     Task* task = nullptr;
980     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
981     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
982     if (task == nullptr) {
983         return NapiHelper::CreateEmptyString(env);
984     }
985     napi_value name = nullptr;
986     napi_create_string_utf8(env, task->name_.c_str(), NAPI_AUTO_LENGTH, &name);
987     return name;
988 }
989 
GetTaskId(napi_env env,napi_callback_info cbinfo)990 napi_value Task::GetTaskId(napi_env env, napi_callback_info cbinfo)
991 {
992     napi_value thisVar = nullptr;
993     Task* task = nullptr;
994     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
995     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
996     if (task == nullptr) {
997         return NapiHelper::CreateUint32(env, 0); // 0 : default value
998     }
999     return NapiHelper::CreateUint32(env, task->taskId_);
1000 }
1001 
UpdateTaskType(TaskType taskType)1002 void Task::UpdateTaskType(TaskType taskType)
1003 {
1004     taskType_ = taskType;
1005     napi_reference_ref(env_, taskRef_, nullptr);
1006 }
1007 
IsRepeatableTask() const1008 bool Task::IsRepeatableTask() const
1009 {
1010     return IsCommonTask() || IsGroupCommonTask() || IsGroupFunctionTask();
1011 }
1012 
IsGroupTask() const1013 bool Task::IsGroupTask() const
1014 {
1015     return IsGroupCommonTask() || IsGroupFunctionTask();
1016 }
1017 
IsGroupCommonTask() const1018 bool Task::IsGroupCommonTask() const
1019 {
1020     return taskType_ == TaskType::GROUP_COMMON_TASK;
1021 }
1022 
IsGroupFunctionTask() const1023 bool Task::IsGroupFunctionTask() const
1024 {
1025     return taskType_ == TaskType::GROUP_FUNCTION_TASK;
1026 }
1027 
IsCommonTask() const1028 bool Task::IsCommonTask() const
1029 {
1030     return taskType_ == TaskType::COMMON_TASK;
1031 }
1032 
IsSeqRunnerTask() const1033 bool Task::IsSeqRunnerTask() const
1034 {
1035     return taskType_ == TaskType::SEQRUNNER_TASK;
1036 }
1037 
IsFunctionTask() const1038 bool Task::IsFunctionTask() const
1039 {
1040     return taskType_ == TaskType::FUNCTION_TASK;
1041 }
1042 
IsLongTask() const1043 bool Task::IsLongTask() const
1044 {
1045     return isLongTask_;
1046 }
1047 
IsPeriodicTask() const1048 bool Task::IsPeriodicTask() const
1049 {
1050     return isPeriodicTask_;
1051 }
1052 
IsMainThreadTask() const1053 bool Task::IsMainThreadTask() const
1054 {
1055     return isMainThreadTask_;
1056 }
1057 
1058 // The uninitialized state is Task, and then taskType_ will be updated based on the task type.
IsExecuted() const1059 bool Task::IsExecuted() const
1060 {
1061     return taskType_ != TaskType::TASK;
1062 }
1063 
GenerateTaskInfo(napi_env env,napi_value func,napi_value args,napi_value transferList,napi_value cloneList,Priority priority,bool defaultTransfer,bool defaultCloneSendable)1064 TaskInfo* Task::GenerateTaskInfo(napi_env env, napi_value func, napi_value args,
1065                                  napi_value transferList, napi_value cloneList, Priority priority,
1066                                  bool defaultTransfer, bool defaultCloneSendable)
1067 {
1068     HILOG_DEBUG("taskpool:: task GenerateTaskInfo");
1069     std::tuple<napi_value, napi_value, bool, bool> params = {
1070         transferList, cloneList, defaultTransfer, defaultCloneSendable
1071     };
1072     auto [serializationFunction, serializationArguments] = GetSerializeResult(env, func, args, params);
1073     if (serializationFunction == nullptr || serializationArguments == nullptr) {
1074         return nullptr;
1075     }
1076     TaskInfo* taskInfo = new TaskInfo();
1077     taskInfo->serializationFunction = serializationFunction;
1078     taskInfo->serializationArguments = serializationArguments;
1079     taskInfo->priority = priority;
1080     reinterpret_cast<NativeEngine*>(env)->IncreaseSubEnvCounter();
1081     return taskInfo;
1082 }
1083 
IncreaseRefCount()1084 void Task::IncreaseRefCount()
1085 {
1086     taskRefCount_.fetch_add(2); // 2 : for PerformTask and TaskResultCallback
1087 }
1088 
DecreaseRefCount()1089 void Task::DecreaseRefCount()
1090 {
1091     taskRefCount_.fetch_sub(1);
1092 }
1093 
IsReadyToHandle() const1094 bool Task::IsReadyToHandle() const
1095 {
1096     return (taskRefCount_ & 1) == 0;
1097 }
1098 
NotifyPendingTask()1099 void Task::NotifyPendingTask()
1100 {
1101     HILOG_DEBUG("taskpool:: task:%{public}s NotifyPendingTask", std::to_string(taskId_).c_str());
1102     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1103     delete currentTaskInfo_;
1104     if (pendingTaskInfos_.empty()) {
1105         currentTaskInfo_ = nullptr;
1106         HILOG_DEBUG("taskpool:: task:%{public}s NotifyPendingTask end, currentTaskInfo_ nullptr",
1107                     std::to_string(taskId_).c_str());
1108         return;
1109     }
1110     if (IsPeriodicTask() && taskState_ == ExecuteState::CANCELED) {
1111         currentTaskInfo_ = nullptr;
1112         HILOG_DEBUG("taskpool:: task:%{public}s NotifyPendingTask end, periodicTask is canceled",
1113                     std::to_string(taskId_).c_str());
1114         return;
1115     }
1116     currentTaskInfo_ = pendingTaskInfos_.front();
1117     pendingTaskInfos_.pop_front();
1118     taskState_ = ExecuteState::WAITING;
1119     TaskManager::GetInstance().EnqueueTaskId(taskId_, currentTaskInfo_->priority);
1120 }
1121 
CancelPendingTask(napi_env env)1122 void Task::CancelPendingTask(napi_env env)
1123 {
1124     HILOG_DEBUG("taskpool:: task:%{public}s CancelPendingTask", std::to_string(taskId_).c_str());
1125     std::list<napi_deferred> deferreds {};
1126     {
1127         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1128         if (pendingTaskInfos_.empty()) {
1129             HILOG_DEBUG("taskpool:: task CancelPendingTask end, pendingTaskInfos_ nullptr");
1130             return;
1131         }
1132         auto engine = reinterpret_cast<NativeEngine*>(env);
1133         for (const auto& info : pendingTaskInfos_) {
1134             engine->DecreaseSubEnvCounter();
1135             if (!IsPeriodicTask()) {
1136                 deferreds.push_back(info->deferred);
1137             }
1138             napi_reference_unref(env, taskRef_, nullptr);
1139             delete info;
1140         }
1141         pendingTaskInfos_.clear();
1142     }
1143     std::string error = "taskpool:: task has been canceled";
1144     TaskManager::GetInstance().BatchRejectDeferred(env_, deferreds, error);
1145 }
1146 
UpdateTask(uint64_t startTime,void * worker)1147 bool Task::UpdateTask(uint64_t startTime, void* worker)
1148 {
1149     HILOG_DEBUG("taskpool:: task:%{public}s UpdateTask", std::to_string(taskId_).c_str());
1150     UpdateTaskStateToRunning();
1151     startTime_ = startTime;
1152     worker_ = worker;
1153     return true;
1154 }
1155 
DeserializeValue(napi_env env,napi_value * func,napi_value * args)1156 napi_value Task::DeserializeValue(napi_env env, napi_value* func, napi_value* args)
1157 {
1158     void* serializationFunction = nullptr;
1159     void* serializationArguments = nullptr;
1160     {
1161         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1162         if (UNLIKELY(currentTaskInfo_ == nullptr)) {
1163             HILOG_ERROR("taskpool:: the currentTaskInfo is nullptr, the task may have been cancelled");
1164             return nullptr;
1165         }
1166         serializationFunction = currentTaskInfo_->serializationFunction;
1167         serializationArguments = currentTaskInfo_->serializationArguments;
1168     }
1169     napi_status status = napi_ok;
1170     std::string errMessage = "";
1171     status = napi_deserialize(env, serializationFunction, func);
1172     if (!IsGroupFunctionTask()) {
1173         napi_delete_serialization_data(env, serializationFunction);
1174     }
1175     if (status != napi_ok || func == nullptr) {
1176         errMessage = "taskpool:: failed to deserialize function.";
1177         HILOG_ERROR("%{public}s", errMessage.c_str());
1178         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1179         success_ = false;
1180         return err;
1181     }
1182 
1183     status = napi_deserialize(env, serializationArguments, args);
1184     if (!IsGroupFunctionTask()) {
1185         napi_delete_serialization_data(env, serializationArguments);
1186     }
1187     if (status != napi_ok || args == nullptr) {
1188         errMessage = "taskpool:: failed to deserialize function.";
1189         HILOG_ERROR("%{public}s", errMessage.c_str());
1190         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1191         success_ = false;
1192         return err;
1193     }
1194     return nullptr;
1195 }
1196 
StoreTaskDuration()1197 void Task::StoreTaskDuration()
1198 {
1199     HILOG_DEBUG("taskpool:: task:%{public}s StoreTaskDuration", std::to_string(taskId_).c_str());
1200     cpuTime_ = ConcurrentHelper::GetMilliseconds();
1201     uint64_t cpuDuration = cpuTime_ - startTime_;
1202     if (ioTime_ != 0) {
1203         uint64_t ioDuration = ioTime_ - startTime_;
1204         TaskManager::GetInstance().StoreTaskDuration(taskId_, std::max(cpuDuration, ioDuration), cpuDuration);
1205     } else {
1206         TaskManager::GetInstance().StoreTaskDuration(taskId_, 0, cpuDuration);
1207     }
1208 }
1209 
CanForSequenceRunner(napi_env env)1210 bool Task::CanForSequenceRunner(napi_env env)
1211 {
1212     std::string errMessage = "";
1213     // task with dependence is not allowed
1214     if (HasDependency()) {
1215         errMessage = "seqRunner:: dependent task not allowed.";
1216         HILOG_ERROR("%{public}s", errMessage.c_str());
1217         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ADD_DEPENDENT_TASK_TO_SEQRUNNER, errMessage.c_str());
1218         return false;
1219     }
1220     if (IsPeriodicTask()) {
1221         errMessage = "taskpool:: SequenceRunner cannot execute the periodicTask";
1222         HILOG_ERROR("%{public}s", errMessage.c_str());
1223         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1224         return false;
1225     }
1226     if (IsCommonTask() || IsSeqRunnerTask()) {
1227         errMessage = "taskpool:: SequenceRunner cannot execute seqRunnerTask or executedTask";
1228         HILOG_ERROR("%{public}s", errMessage.c_str());
1229         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1230         return false;
1231     }
1232     if (IsGroupCommonTask()) {
1233         errMessage = "taskpool:: SequenceRunner cannot execute groupTask";
1234         HILOG_ERROR("%{public}s", errMessage.c_str());
1235         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1236         return false;
1237     }
1238     if (IsAsyncRunnerTask()) {
1239         errMessage = "SequenceRunner cannot execute asyncRunnerTask.";
1240         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1241         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1242         return false;
1243     }
1244     return true;
1245 }
1246 
CanForTaskGroup(napi_env env)1247 bool Task::CanForTaskGroup(napi_env env)
1248 {
1249     std::string errMessage = "";
1250     if (HasDependency()) {
1251         errMessage = "taskpool:: dependent task not allowed.";
1252         HILOG_ERROR("%{public}s", errMessage.c_str());
1253         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1254         return false;
1255     }
1256     if (IsPeriodicTask()) {
1257         errMessage = "taskpool:: The interface does not support the periodicTask";
1258         HILOG_ERROR("%{public}s", errMessage.c_str());
1259         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1260         return false;
1261     }
1262     if (IsCommonTask() || IsSeqRunnerTask()) {
1263         errMessage = "taskpool:: taskGroup cannot add seqRunnerTask or executedTask";
1264         HILOG_ERROR("%{public}s", errMessage.c_str());
1265         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1266         return false;
1267     }
1268     if (IsGroupCommonTask()) {
1269         errMessage = "taskpool:: taskGroup cannot add groupTask";
1270         HILOG_ERROR("%{public}s", errMessage.c_str());
1271         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1272         return false;
1273     }
1274     if (IsLongTask()) {
1275         errMessage = "taskpool:: The interface does not support the long task";
1276         HILOG_ERROR("%{public}s", errMessage.c_str());
1277         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1278         return false;
1279     }
1280     if (IsAsyncRunnerTask()) {
1281         errMessage = "TaskGroup cannot execute asyncRunnerTask.";
1282         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1283         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1284         return false;
1285     }
1286     taskType_ = TaskType::GROUP_COMMON_TASK;
1287     return true;
1288 }
1289 
CanExecute(napi_env env)1290 bool Task::CanExecute(napi_env env)
1291 {
1292     std::string errMessage = "";
1293     if (IsGroupCommonTask()) {
1294         errMessage = "taskpool:: groupTask cannot execute outside";
1295         HILOG_ERROR("%{public}s", errMessage.c_str());
1296         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1297         return false;
1298     }
1299     if (IsSeqRunnerTask()) {
1300         errMessage = "taskpool:: seqRunnerTask cannot execute outside";
1301         HILOG_ERROR("%{public}s", errMessage.c_str());
1302         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1303         return false;
1304     }
1305     if (IsCommonTask() && HasDependency()) {
1306         errMessage = "taskpool:: executedTask with dependency cannot execute again";
1307         HILOG_ERROR("%{public}s", errMessage.c_str());
1308         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1309         return false;
1310     }
1311     if (IsExecuted() && IsLongTask()) {
1312         errMessage = "taskpool:: The long task can only be executed once";
1313         HILOG_ERROR("%{public}s", errMessage.c_str());
1314         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1315         return false;
1316     }
1317     if (IsPeriodicTask()) {
1318         errMessage = "taskpool:: the periodicTask cannot execute again";
1319         HILOG_ERROR("%{public}s", errMessage.c_str());
1320         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1321         return false;
1322     }
1323     if (IsAsyncRunnerTask()) {
1324         errMessage = "AsyncRunnerTask cannot execute outside.";
1325         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1326         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1327         return false;
1328     }
1329     return true;
1330 }
1331 
CanExecuteDelayed(napi_env env)1332 bool Task::CanExecuteDelayed(napi_env env)
1333 {
1334     std::string errMessage = "";
1335     if (IsGroupCommonTask()) {
1336         errMessage = "taskpool:: groupTask cannot executeDelayed outside";
1337         HILOG_ERROR("%{public}s", errMessage.c_str());
1338         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1339         return false;
1340     }
1341     if (IsSeqRunnerTask()) {
1342         errMessage = "taskpool:: seqRunnerTask cannot executeDelayed outside";
1343         HILOG_ERROR("%{public}s", errMessage.c_str());
1344         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1345         return false;
1346     }
1347     if (IsCommonTask() && HasDependency()) {
1348         errMessage = "taskpool:: executedTask with dependency cannot executeDelayed again";
1349         HILOG_ERROR("%{public}s", errMessage.c_str());
1350         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1351         return false;
1352     }
1353     if (IsExecuted() && IsLongTask()) {
1354         errMessage = "taskpool:: Multiple executions of longTask are not supported in the executeDelayed";
1355         HILOG_ERROR("%{public}s", errMessage.c_str());
1356         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1357         return false;
1358     }
1359     if (IsPeriodicTask()) {
1360         errMessage = "taskpool:: the periodicTask cannot executeDelayed";
1361         HILOG_ERROR("%{public}s", errMessage.c_str());
1362         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1363         return false;
1364     }
1365     if (IsAsyncRunnerTask()) {
1366         errMessage = "AsyncRunnerTask cannot executeDelayed.";
1367         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1368         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1369         return false;
1370     }
1371     return true;
1372 }
1373 
CanExecutePeriodically(napi_env env)1374 bool Task::CanExecutePeriodically(napi_env env)
1375 {
1376     if (IsAsyncRunnerTask()) {
1377         std::string errMessage = "AsyncRunnerTask cannot executePeriodically.";
1378         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1379         return false;
1380     }
1381     if (IsExecuted() || IsPeriodicTask()) {
1382         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_PERIODICALLY);
1383         return false;
1384     }
1385     if (HasDependency()) {
1386         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
1387             "taskpool:: the task with dependency cannot executePeriodically");
1388         return false;
1389     }
1390     return true;
1391 }
1392 
SetHasDependency(bool hasDependency)1393 void Task::SetHasDependency(bool hasDependency)
1394 {
1395     hasDependency_ = hasDependency;
1396 }
1397 
HasDependency() const1398 bool Task::HasDependency() const
1399 {
1400     return hasDependency_;
1401 }
1402 
TryClearHasDependency()1403 void Task::TryClearHasDependency()
1404 {
1405     HILOG_DEBUG("taskpool:: task:%{public}s TryClearHasDependency", std::to_string(taskId_).c_str());
1406     if (IsExecuted()) {
1407         HILOG_DEBUG("taskpool:: task TryClearHasDependency end, task is executed");
1408         return;
1409     }
1410     if ((!TaskManager::GetInstance().IsDependentByTaskId(taskId_)) &&
1411         (!TaskManager::GetInstance().IsDependendByTaskId(taskId_))) {
1412         SetHasDependency(false);
1413     }
1414 }
1415 
ThrowNoDependencyError(napi_env env)1416 void Task::ThrowNoDependencyError(napi_env env)
1417 {
1418     std::string errMessage = "taskpool:: task has no dependency";
1419     HILOG_ERROR("%{public}s", errMessage.c_str());
1420     ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY, errMessage.c_str());
1421 }
1422 
UpdatePeriodicTask()1423 void Task::UpdatePeriodicTask()
1424 {
1425     taskType_ = TaskType::COMMON_TASK;
1426     napi_reference_ref(env_, taskRef_, nullptr);
1427     isPeriodicTask_ = true;
1428 }
1429 
InitHandle(napi_env env)1430 void Task::InitHandle(napi_env env)
1431 {
1432 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1433     if (OHOS::AppExecFwk::EventRunner::IsAppMainThread()) {
1434         isMainThreadTask_ = true;
1435         return;
1436     }
1437 #endif
1438     uv_loop_t* loop = NapiHelper::GetLibUV(env);
1439     ConcurrentHelper::UvHandleInit(loop, onStartCancelSignal_, Task::Cancel);
1440     ConcurrentHelper::UvHandleInit(loop, onStartDiscardSignal_, Task::DiscardTask);
1441     auto engine = reinterpret_cast<NativeEngine*>(env);
1442     isMainThreadTask_ = engine->IsMainThread();
1443 }
1444 
ClearDelayedTimers()1445 void Task::ClearDelayedTimers()
1446 {
1447     HILOG_DEBUG("taskpool:: task ClearDelayedTimers");
1448     std::list<napi_deferred> deferreds {};
1449     {
1450         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1451         TaskMessage* taskMessage = nullptr;
1452         for (auto t: delayedTimers_) {
1453             if (t == nullptr) {
1454                 continue;
1455             }
1456             taskMessage = static_cast<TaskMessage*>(t->data);
1457             deferreds.push_back(taskMessage->deferred);
1458             uv_timer_stop(t);
1459             uv_close(reinterpret_cast<uv_handle_t*>(t), [](uv_handle_t* handle) {
1460                 delete (uv_timer_t*)handle;
1461                 handle = nullptr;
1462             });
1463             delete taskMessage;
1464             taskMessage = nullptr;
1465         }
1466         delayedTimers_.clear();
1467     }
1468     std::string error = "taskpool:: task has been canceled";
1469     TaskManager::GetInstance().BatchRejectDeferred(env_, deferreds, error);
1470 }
1471 
VerifyAndPostResult(Task * task,Priority priority)1472 bool Task::VerifyAndPostResult(Task* task, Priority priority)
1473 {
1474     if (!task->IsMainThreadTask() && !task->IsValid()) {
1475         return false;
1476     }
1477 
1478     auto taskId = task->GetTaskId();
1479     auto onResultTask = [taskId]([[maybe_unused]] void* data) {
1480         Task* hostTask = TaskManager::GetInstance().GetTask(taskId);
1481         if (hostTask == nullptr) { // LCOV_EXCL_BR_LINE
1482             return;
1483         }
1484         TaskPool::HandleTaskResult(hostTask);
1485     };
1486 
1487     auto napiPrio = g_napiPriorityMap.at(priority);
1488     uint64_t handleId = 0;
1489     napi_status status = napi_send_cancelable_event(task->GetEnv(), onResultTask, nullptr, napiPrio,
1490                                                     &handleId, ON_RESULT_STR);
1491     // should nerver access any data of the task when status is napi_ok
1492     if (status != napi_ok) {
1493         HILOG_ERROR("taskpool:: failed to send event for task:%{public}s", std::to_string(taskId).c_str());
1494         return false;
1495     }
1496     return true;
1497 }
1498 
IncreaseTaskLifecycleCount()1499 void Task::IncreaseTaskLifecycleCount()
1500 {
1501     lifecycleCount_++; // when tasks are created or executed, lifecycleCount_ will increment
1502 }
1503 
DecreaseTaskLifecycleCount()1504 void Task::DecreaseTaskLifecycleCount()
1505 {
1506     lifecycleCount_--; // when tasks finished, lifecycleCount_ will decrement
1507 }
1508 
ShouldDeleteTask(bool needUnref)1509 bool Task::ShouldDeleteTask(bool needUnref)
1510 {
1511     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1512     if (!IsValid()) {
1513         HILOG_WARN("taskpool:: task is invalid");
1514         if (IsAsyncRunnerTask()) {
1515             AsyncRunnerManager::GetInstance().DecreaseRunningCount(asyncRunnerId_);
1516         }
1517         TaskManager::GetInstance().RemoveTask(taskId_);
1518         return true;
1519     }
1520     if (needUnref) {
1521         if (IsAsyncRunnerTask()) {
1522             AsyncRunnerManager::GetInstance().DecreaseRunningCount(asyncRunnerId_);
1523         }
1524         DecreaseTaskLifecycleCount();
1525     }
1526     return false;
1527 }
1528 
CheckStartExecution(Priority priority)1529 bool Task::CheckStartExecution(Priority priority)
1530 {
1531 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1532     if (IsMainThreadTask()) {
1533         if (onStartExecutionCallBackInfo_ == nullptr) {
1534             return true;
1535         }
1536         HITRACE_HELPER_METER_NAME("PerformTask: PostTask");
1537         uint32_t taskId = taskId_;
1538         auto onStartExecutionTask = [taskId]() {
1539             Task* task = TaskManager::GetInstance().GetTask(taskId);
1540             if (task == nullptr || task->onStartExecutionCallBackInfo_ == nullptr) {
1541                 return;
1542             }
1543             Task::StartExecutionTask(task->onStartExecutionCallBackInfo_);
1544         };
1545         TaskManager::GetInstance().PostTask(onStartExecutionTask, "TaskPoolOnStartExecutionTask", priority);
1546     } else {
1547         if (onStartExecutionSignal_ == nullptr) {
1548             return true;
1549         }
1550         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1551         if (!IsValid()) {
1552             return false;
1553         }
1554         ConcurrentHelper::UvCheckAndAsyncSend(onStartExecutionSignal_);
1555     }
1556     return true;
1557 #else
1558     if (onStartExecutionSignal_ == nullptr) {
1559         return true;
1560     }
1561     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1562     if (!IsValid()) {
1563         return false;
1564     }
1565     ConcurrentHelper::UvCheckAndAsyncSend(onStartExecutionSignal_);
1566     return true;
1567 #endif
1568 }
1569 
SetValid(bool isValid)1570 void Task::SetValid(bool isValid)
1571 {
1572     isValid_.store(isValid);
1573 }
1574 
IsValid()1575 bool Task::IsValid()
1576 {
1577     return isValid_.load();
1578 }
1579 
CanForAsyncRunner(napi_env env)1580 bool Task::CanForAsyncRunner(napi_env env)
1581 {
1582     std::string errMessage = "";
1583     if (HasDependency()) {
1584         errMessage = "AsyncRunner:: dependent task not allowed.";
1585         HILOG_ERROR("%{public}s", errMessage.c_str());
1586         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ADD_DEPENDENT_TASK_TO_SEQRUNNER, errMessage.c_str());
1587         return false;
1588     }
1589     if (IsPeriodicTask()) {
1590         errMessage = "AsyncRunner cannot execute the periodicTask.";
1591         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1592         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1593         return false;
1594     }
1595     if (IsCommonTask() || IsSeqRunnerTask()) {
1596         errMessage = "AsyncRunner cannot execute seqRunnerTask or executedTask.";
1597         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1598         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1599         return false;
1600     }
1601     if (IsGroupCommonTask()) {
1602         errMessage = "AsyncRunner cannot execute groupTask.";
1603         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1604         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1605         return false;
1606     }
1607     if (IsAsyncRunnerTask()) {
1608         errMessage = "AsyncRunner cannot execute asyncRunnerTask.";
1609         HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str());
1610         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_CANNOT_EXECUTED, errMessage.c_str());
1611         return false;
1612     }
1613     return true;
1614 }
1615 
IsAsyncRunnerTask()1616 bool Task::IsAsyncRunnerTask()
1617 {
1618     return taskType_ == TaskType::ASYNCRUNNER_TASK;
1619 }
1620 
SetTaskId(uint32_t taskId)1621 void Task::SetTaskId(uint32_t taskId)
1622 {
1623     taskId_ = taskId;
1624 }
1625 
TriggerCancel(CancelTaskMessage * message)1626 void Task::TriggerCancel(CancelTaskMessage* message)
1627 {
1628 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1629     if (IsMainThreadTask()) {
1630         HITRACE_HELPER_METER_NAME("TriggerCancel: PostTask");
1631         auto onCancelTask = [message]() {
1632             Task* task = TaskManager::GetInstance().GetTask(message->taskId);
1633             if (task == nullptr) {
1634                 CloseHelp::DeletePointer(message, false);
1635                 return;
1636             }
1637             napi_status status = napi_ok;
1638             HandleScope scope(task->env_, status);
1639             if (status != napi_ok) {
1640                 HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
1641                 CloseHelp::DeletePointer(message, false);
1642                 return;
1643             }
1644             task->CancelInner(message->state);
1645             CloseHelp::DeletePointer(message, false);
1646         };
1647         TaskManager::GetInstance().PostTask(onCancelTask, "TaskOnCancelTask", Priority::DEFAULT);
1648     } else {
1649         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1650         if (!IsValid() || !ConcurrentHelper::IsUvActive(onStartCancelSignal_)) {
1651             return;
1652         }
1653         onStartCancelSignal_->data = message;
1654         uv_async_send(onStartCancelSignal_);
1655     }
1656 #else
1657     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1658     if (!IsValid() || !ConcurrentHelper::IsUvActive(onStartCancelSignal_)) {
1659         CloseHelp::DeletePointer(message, false);
1660         return;
1661     }
1662     onStartCancelSignal_->data = message;
1663     uv_async_send(onStartCancelSignal_);
1664 #endif
1665 }
1666 
CancelInner(ExecuteState state)1667 void Task::CancelInner(ExecuteState state)
1668 {
1669     ClearDelayedTimers();
1670     CancelPendingTask(env_);
1671     if (HasDependency()) {
1672         TaskManager::GetInstance().ClearDependentTask(taskId_);
1673     }
1674     std::list<napi_deferred> deferreds {};
1675     std::string error = "taskpool:: task has been canceled";
1676     {
1677         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1678         if (state == ExecuteState::WAITING && currentTaskInfo_ != nullptr &&
1679             TaskManager::GetInstance().EraseWaitingTaskId(taskId_, currentTaskInfo_->priority)) {
1680             reinterpret_cast<NativeEngine*>(env_)->DecreaseSubEnvCounter();
1681             DecreaseTaskLifecycleCount();
1682             TaskManager::GetInstance().DecreaseSendDataRefCount(env_, taskId_);
1683             deferreds.push_back(currentTaskInfo_->deferred);
1684             napi_reference_unref(env_, taskRef_, nullptr);
1685             delete currentTaskInfo_;
1686             currentTaskInfo_ = nullptr;
1687             isCancelToFinish_ = true;
1688         }
1689         if (IsSeqRunnerTask() && state == ExecuteState::CANCELED) {
1690             if (currentTaskInfo_ != nullptr) {
1691                 deferreds.push_back(currentTaskInfo_->deferred);
1692                 error = "taskpool:: sequenceRunner task has been canceled";
1693             }
1694             DisposeCanceledTask();
1695         }
1696         if (state == ExecuteState::DELAYED) {
1697             isCancelToFinish_ = true;
1698         }
1699     }
1700 
1701     TaskManager::GetInstance().BatchRejectDeferred(env_, deferreds, error);
1702 }
1703 
IsSameEnv(napi_env env)1704 bool Task::IsSameEnv(napi_env env)
1705 {
1706     return env_ == env;
1707 }
1708 
DiscardAsyncRunnerTask(DiscardTaskMessage * message)1709 void Task::DiscardAsyncRunnerTask(DiscardTaskMessage* message)
1710 {
1711     if (message == nullptr || !IsAsyncRunnerTask() || !IsValid()) {
1712         CloseHelp::DeletePointer(message, false);
1713         return;
1714     }
1715 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1716     if (IsMainThreadTask()) {
1717         HITRACE_HELPER_METER_NAME("DiscardAsyncRunnerTask: PostTask");
1718         auto onDiscardTask = [message]() {
1719             Task* task = TaskManager::GetInstance().GetTask(message->taskId);
1720             if (task == nullptr) {
1721                 CloseHelp::DeletePointer(message, false);
1722                 return;
1723             }
1724             napi_status status = napi_ok;
1725             HandleScope scope(task->env_, status);
1726             if (status != napi_ok) {
1727                 CloseHelp::DeletePointer(message, false);
1728                 HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
1729                 return;
1730             }
1731             task->DiscardInner(message);
1732         };
1733         TaskManager::GetInstance().PostTask(onDiscardTask, "TaskOnDiscardTask", Priority::DEFAULT);
1734     } else {
1735         std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1736         if (ConcurrentHelper::IsUvActive(onStartDiscardSignal_)) {
1737             onStartDiscardSignal_->data = message;
1738             uv_async_send(onStartDiscardSignal_);
1739         }
1740     }
1741 #else
1742     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1743     if (ConcurrentHelper::IsUvActive(onStartDiscardSignal_)) {
1744         onStartDiscardSignal_->data = message;
1745         uv_async_send(onStartDiscardSignal_);
1746     }
1747 #endif
1748 }
1749 
DiscardInner(DiscardTaskMessage * message)1750 void Task::DiscardInner(DiscardTaskMessage* message)
1751 {
1752     if (message == nullptr) {
1753         CloseHelp::DeletePointer(message, false);
1754         return;
1755     }
1756     auto task = TaskManager::GetInstance().GetTask(message->taskId);
1757     if (task == nullptr || !task->IsValid() || message->env != task->env_) {
1758         CloseHelp::DeletePointer(message, false);
1759         HILOG_DEBUG("taskpool:: discard task is nullptr.");
1760         return;
1761     }
1762     napi_value error = nullptr;
1763     if (message->errCode == ErrorHelper::ERR_ASYNCRUNNER_TASK_CANCELED) {
1764         error = TaskManager::GetInstance().CancelError(task->env_, message->errCode);
1765     } else {
1766         error = ErrorHelper::NewError(task->env_, message->errCode);
1767     }
1768     napi_reject_deferred(task->env_, task->currentTaskInfo_->deferred, error);
1769     DisposeCanceledTask();
1770     TaskManager::GetInstance().RemoveTask(message->taskId);
1771 
1772     CloseHelp::DeletePointer(message, false);
1773 }
1774 
DiscardTask(const uv_async_t * req)1775 void Task::DiscardTask(const uv_async_t* req)
1776 {
1777     auto message = static_cast<DiscardTaskMessage*>(req->data);
1778     if (message == nullptr) {
1779         return;
1780     }
1781     auto task = TaskManager::GetInstance().GetTask(message->taskId);
1782     if (task == nullptr || task->env_ != message->env) {
1783         CloseHelp::DeletePointer(message, false);
1784         HILOG_DEBUG("taskpool:: task is nullptr.");
1785         return;
1786     }
1787     napi_status status = napi_ok;
1788     HandleScope scope(task->env_, status);
1789     if (status != napi_ok) {
1790         CloseHelp::DeletePointer(message, false);
1791         HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
1792         return;
1793     }
1794 
1795     task->DiscardInner(message);
1796 }
1797 
ReleaseData()1798 void Task::ReleaseData()
1799 {
1800     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1801     if (onStartCancelSignal_ != nullptr) {
1802         if (!ConcurrentHelper::IsUvClosing(onStartCancelSignal_)) {
1803             ConcurrentHelper::UvHandleClose(onStartCancelSignal_);
1804         } else {
1805             delete onStartCancelSignal_;
1806             onStartCancelSignal_ = nullptr;
1807         }
1808     }
1809 
1810     if (onStartDiscardSignal_ != nullptr) {
1811         if (!ConcurrentHelper::IsUvClosing(onStartDiscardSignal_)) {
1812             ConcurrentHelper::UvHandleClose(onStartDiscardSignal_);
1813         } else {
1814             delete onStartDiscardSignal_;
1815             onStartDiscardSignal_ = nullptr;
1816         }
1817     }
1818 
1819     if (currentTaskInfo_ != nullptr) {
1820         delete currentTaskInfo_;
1821         currentTaskInfo_ = nullptr;
1822     }
1823 }
1824 
DisposeCanceledTask()1825 void Task::DisposeCanceledTask()
1826 {
1827     reinterpret_cast<NativeEngine*>(env_)->DecreaseSubEnvCounter();
1828     napi_reference_unref(env_, taskRef_, nullptr);
1829     delete currentTaskInfo_;
1830     currentTaskInfo_ = nullptr;
1831 }
1832 
GetWorker() const1833 Worker* Task::GetWorker() const
1834 {
1835     return static_cast<Worker*>(worker_);
1836 }
1837 
GetEnv() const1838 napi_env Task::GetEnv() const
1839 {
1840     return env_;
1841 }
1842 
GetTaskId() const1843 uint32_t Task::GetTaskId() const
1844 {
1845     return taskId_;
1846 }
1847 
IsRealyCanceled()1848 bool Task::IsRealyCanceled()
1849 {
1850     return taskState_ == ExecuteState::CANCELED && isCancelToFinish_;
1851 }
1852 
UpdateTaskStateToWaiting()1853 bool Task::UpdateTaskStateToWaiting()
1854 {
1855     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1856     if (IsAsyncRunnerTask() || IsSeqRunnerTask()) {
1857         if (taskState_ == ExecuteState::NOT_FOUND) {
1858             taskState_ = ExecuteState::WAITING;
1859             return true;
1860         }
1861         return false;
1862     }
1863     if (IsPeriodicTask()) {
1864         if (taskState_ == ExecuteState::NOT_FOUND || taskState_ == ExecuteState::FINISHED) {
1865             taskState_ = ExecuteState::WAITING;
1866             return true;
1867         }
1868         return false;
1869     }
1870     if (taskState_ == ExecuteState::NOT_FOUND || taskState_ == ExecuteState::FINISHED ||
1871         IsRealyCanceled()) {
1872         taskState_ = ExecuteState::WAITING;
1873         return true;
1874     }
1875     return false;
1876 }
1877 
UpdateTaskStateToRunning()1878 bool Task::UpdateTaskStateToRunning()
1879 {
1880     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1881     if (taskState_ != ExecuteState::CANCELED) {
1882         taskState_ = ExecuteState::RUNNING;
1883         return true;
1884     }
1885     return false;
1886 }
1887 
UpdateTaskStateToCanceled()1888 bool Task::UpdateTaskStateToCanceled()
1889 {
1890     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1891     if (IsPeriodicTask()) {
1892         taskState_ = ExecuteState::CANCELED;
1893         return true;
1894     }
1895     if (taskState_ == ExecuteState::NOT_FOUND || taskState_ == ExecuteState::FINISHED ||
1896         taskState_ == ExecuteState::CANCELED || taskState_ == ExecuteState::ENDING) {
1897         taskState_ = ExecuteState::WAITING;
1898         return false;
1899     }
1900     taskState_ = ExecuteState::CANCELED;
1901     return true;
1902 }
1903 
UpdateTaskStateToFinished()1904 bool Task::UpdateTaskStateToFinished()
1905 {
1906     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1907     if (taskState_ == ExecuteState::ENDING) {
1908         taskState_ = ExecuteState::FINISHED;
1909         return true;
1910     }
1911     return false;
1912 }
1913 
UpdateTaskStateToDelayed()1914 bool Task::UpdateTaskStateToDelayed()
1915 {
1916     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1917     if (!IsExecuted() || IsRealyCanceled() || taskState_ == ExecuteState::FINISHED) {
1918         taskState_ = ExecuteState::DELAYED;
1919         return true;
1920     }
1921     return false;
1922 }
1923 
UpdateTaskStateToEnding()1924 bool Task::UpdateTaskStateToEnding()
1925 {
1926     std::lock_guard<std::recursive_mutex> lock(taskMutex_);
1927     if (taskState_ == ExecuteState::RUNNING ||
1928         (taskState_ == ExecuteState::CANCELED && !IsPeriodicTask())) {
1929         taskState_ = ExecuteState::ENDING;
1930         return true;
1931     }
1932     return false;
1933 }
1934 
GetSerializeParams(napi_env env,napi_value napiTask)1935 std::tuple<napi_value, napi_value, napi_value, napi_value> Task::GetSerializeParams(napi_env env, napi_value napiTask)
1936 {
1937     napi_value func = NapiHelper::GetNameProperty(env, napiTask, FUNCTION_STR);
1938     napi_value args = NapiHelper::GetNameProperty(env, napiTask, ARGUMENTS_STR);
1939     if (func == nullptr || args == nullptr) {
1940         std::string errMessage = "taskpool:: task value is error";
1941         HILOG_ERROR("%{public}s", errMessage.c_str());
1942         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1943         return {nullptr, nullptr, nullptr, nullptr};
1944     }
1945     napi_value transferList = NapiHelper::GetUndefinedValue(env);
1946     if (NapiHelper::HasNameProperty(env, napiTask, TRANSFERLIST_STR)) {
1947         transferList = NapiHelper::GetNameProperty(env, napiTask, TRANSFERLIST_STR);
1948     }
1949     napi_value cloneList = NapiHelper::GetUndefinedValue(env);
1950     if (NapiHelper::HasNameProperty(env, napiTask, CLONE_LIST_STR)) {
1951         cloneList = NapiHelper::GetNameProperty(env, napiTask, CLONE_LIST_STR);
1952     }
1953     return {func, args, transferList, cloneList};
1954 }
1955 
GetSerializeResult(napi_env env,napi_value func,napi_value args,std::tuple<napi_value,napi_value,bool,bool> transferAndCloneParams)1956 std::tuple<void*, void*> Task::GetSerializeResult(napi_env env, napi_value func, napi_value args,
1957                                                   std::tuple<napi_value, napi_value, bool, bool> transferAndCloneParams)
1958 {
1959     auto [transferList, cloneList, defaultTransfer, defaultCloneSendable] = transferAndCloneParams;
1960     napi_value undefined = NapiHelper::GetUndefinedValue(env);
1961     void* serializationFunction = nullptr;
1962     std::string errString = "";
1963     napi_status status = napi_serialize_inner_with_error(env, func, undefined, undefined, defaultTransfer,
1964                                                          defaultCloneSendable, &serializationFunction, errString);
1965     std::string errMessage = "";
1966     if (status != napi_ok || serializationFunction == nullptr) {
1967         errMessage = "taskpool: failed to serialize function.\nSerialize error: " + errString;
1968         HILOG_ERROR("%{public}s", errMessage.c_str());
1969         ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_CONCURRENT_FUNCTION, errMessage.c_str());
1970         return {nullptr, nullptr};
1971     }
1972     void* serializationArguments = nullptr;
1973     errMessage = "";
1974     status = napi_serialize_inner_with_error(env, args, transferList, cloneList, defaultTransfer,
1975                                              defaultCloneSendable, &serializationArguments, errString);
1976     if (status != napi_ok || serializationArguments == nullptr) { // LOCV_EXCL_BR_LINE
1977         errMessage = "taskpool: failed to serialize arguments.\nSerialize error: " + errString;
1978         HILOG_ERROR("%{public}s", errMessage.c_str());
1979         ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1980         return {nullptr, nullptr};
1981     }
1982     return {serializationFunction, serializationArguments};
1983 }
1984 } // namespace Commonlibrary::Concurrent::TaskPoolModule