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 "helper/error_helper.h"
19 #include "helper/napi_helper.h"
20 #include "helper/object_helper.h"
21 #include "helper/hitrace_helper.h"
22 #include "task_manager.h"
23 #include "taskpool.h"
24 #include "tools/log.h"
25 #include "worker.h"
26 
27 namespace Commonlibrary::Concurrent::TaskPoolModule {
28 static constexpr char ONRECEIVEDATA_STR[] = "onReceiveData";
29 static constexpr char SETTRANSFERLIST_STR[] = "setTransferList";
30 static constexpr char SET_CLONE_LIST_STR[] = "setCloneList";
31 static constexpr char ONENQUEUED_STR[] = "onEnqueued";
32 static constexpr char ONSTARTEXECUTION_STR[] = "onStartExecution";
33 static constexpr char ONEXECUTIONFAILED_STR[] = "onExecutionFailed";
34 static constexpr char ONEXECUTIONSUCCEEDED_STR[] = "onExecutionSucceeded";
35 static constexpr char ISDONE_STR[] = "isDone";
36 
37 using namespace Commonlibrary::Concurrent::Common::Helper;
38 
Task(napi_env env,TaskType taskType,std::string name)39 Task::Task(napi_env env, TaskType taskType, std::string name) : env_(env), taskType_(taskType), name_(name) {}
40 
TaskConstructor(napi_env env,napi_callback_info cbinfo)41 napi_value Task::TaskConstructor(napi_env env, napi_callback_info cbinfo)
42 {
43     // check argv count
44     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
45     std::string errMessage = "";
46     if (argc < 1) {
47         errMessage = "taskpool:: create task need more than one param";
48         HILOG_ERROR("%{public}s", errMessage.c_str());
49         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
50         return nullptr;
51     }
52     napi_value* args = new napi_value[argc];
53     ObjectScope<napi_value> scope(args, true);
54     napi_value thisVar = nullptr;
55     napi_value func = nullptr;
56     napi_value name = nullptr;
57     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
58     // if the first is task name, the second might be func
59     if (argc > 1 && NapiHelper::IsString(env, args[0])) {
60         name = args[0];
61         func = args[1];
62         args += 2; // 2: name and func
63         argc -= 2; // 2: name and func
64     } else {
65         func = args[0];
66         args += 1; // 1: func
67         argc -= 1; // 1: func
68     }
69     if (!NapiHelper::IsFunction(env, func)) {
70         errMessage = "taskpool:: the first or second param of task must be function";
71         HILOG_ERROR("%{public}s", errMessage.c_str());
72         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
73             "the type of the first or second param of task must be function.");
74         return nullptr;
75     }
76 
77     Task* task = GenerateTask(env, thisVar, func, name, args, argc);
78     napi_status status = napi_wrap(env, thisVar, task, TaskDestructor, nullptr, nullptr);
79     if (status != napi_ok) {
80         HILOG_ERROR("taskpool::TaskConstructor napi_wrap return value is %{public}d", status);
81         delete task;
82         task = nullptr;
83         return nullptr;
84     }
85     TaskManager::GetInstance().StoreTask(task->taskId_, task);
86     napi_create_reference(env, thisVar, 0, &task->taskRef_);
87     if (!task->IsMainThreadTask()) {
88         napi_add_env_cleanup_hook(env, Task::CleanupHookFunc, task);
89     }
90     return thisVar;
91 }
92 
LongTaskConstructor(napi_env env,napi_callback_info cbinfo)93 napi_value Task::LongTaskConstructor(napi_env env, napi_callback_info cbinfo)
94 {
95     auto thisVar = TaskConstructor(env, cbinfo);
96     if (thisVar == nullptr) {
97         return nullptr;
98     }
99     Task* task;
100     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
101     task->isLongTask_ = true;
102     return thisVar;
103 }
104 
105 void Task::TaskDestructor(napi_env env, void* data, [[maybe_unused]] void* hint)
106 {
107     Task* task = static_cast<Task*>(data);
108     HILOG_INFO("taskpool:: taskId:%{public}s TaskDestructor", std::to_string(task->taskId_).c_str());
109     if (!task->IsMainThreadTask()) {
110         napi_remove_env_cleanup_hook(env, Task::CleanupHookFunc, task);
111     }
112     // for performance, do not lock first
113     if (task->IsMainThreadTask() || task->refCount_ == 0) {
114         TaskManager::GetInstance().ReleaseTaskData(env, task);
115         napi_delete_reference(env, task->taskRef_);
116         delete task;
117         return;
118     }
119     bool shouldDelete = false;
120     {
121         std::lock_guard<RECURSIVE_MUTEX> lock(task->taskMutex_);
122         task->SetValid(false);
123         if (task->refCount_ == 0) {
124             shouldDelete = true;
125         }
126         TaskManager::GetInstance().ReleaseTaskData(env, task, shouldDelete);
127         napi_delete_reference(env, task->taskRef_);
128     }
129     if (shouldDelete) {
130         delete task;
131     }
132 }
133 
CleanupHookFunc(void * arg)134 void Task::CleanupHookFunc(void* arg)
135 {
136     if (arg == nullptr) {
137         HILOG_ERROR("taskpool:: cleanupHook arg is nullptr");
138         return;
139     }
140     Task* task = static_cast<Task*>(arg);
141     std::lock_guard<RECURSIVE_MUTEX> lock(task->taskMutex_);
142     if (task->onResultSignal_ != nullptr) {
143         uv_close(reinterpret_cast<uv_handle_t*>(task->onResultSignal_), nullptr);
144     }
145     if (task->onStartExecutionSignal_ != nullptr) {
146         uv_close(reinterpret_cast<uv_handle_t*>(task->onStartExecutionSignal_), nullptr);
147     }
148     if (task->IsFunctionTask()) {
149         task->SetValid(false);
150     }
151 }
152 
GenerateTask(napi_env env,napi_value napiTask,napi_value func,napi_value name,napi_value * args,size_t argc)153 Task* Task::GenerateTask(napi_env env, napi_value napiTask, napi_value func,
154                          napi_value name, napi_value* args, size_t argc)
155 {
156     HILOG_DEBUG("taskpool:: task GenerateTask");
157     napi_value argsArray = NapiHelper::CreateArrayWithLength(env, argc);
158     for (size_t i = 0; i < argc; i++) {
159         napi_set_element(env, argsArray, i, args[i]);
160     }
161     if (name == nullptr) {
162         name = NapiHelper::GetNameProperty(env, func, NAME);
163     }
164     char* nameStr = NapiHelper::GetChars(env, name);
165     Task* task = new Task(env, TaskType::TASK, nameStr);
166     delete[] nameStr;
167     task->taskId_ = reinterpret_cast<uint64_t>(task);
168     task->InitHandle(env);
169 
170     napi_value taskId = NapiHelper::CreateUint64(env, task->taskId_);
171     napi_value napiTrue = NapiHelper::CreateBooleanValue(env, true);
172     napi_value napiFalse = NapiHelper::CreateBooleanValue(env, false);
173     napi_set_named_property(env, napiTask, FUNCTION_STR, func);
174     napi_set_named_property(env, napiTask, TASKID_STR, taskId);
175     napi_set_named_property(env, napiTask, ARGUMENTS_STR, argsArray);
176     napi_set_named_property(env, napiTask, DEFAULT_TRANSFER_STR, napiTrue);
177     napi_set_named_property(env, napiTask, DEFAULT_CLONE_SENDABLE_STR, napiFalse);
178     napi_property_descriptor properties[] = {
179         DECLARE_NAPI_FUNCTION(SETTRANSFERLIST_STR, SetTransferList),
180         DECLARE_NAPI_FUNCTION(SET_CLONE_LIST_STR, SetCloneList),
181         DECLARE_NAPI_FUNCTION(ONRECEIVEDATA_STR, OnReceiveData),
182         DECLARE_NAPI_FUNCTION(ADD_DEPENDENCY_STR, AddDependency),
183         DECLARE_NAPI_FUNCTION(REMOVE_DEPENDENCY_STR, RemoveDependency),
184         DECLARE_NAPI_FUNCTION(ONENQUEUED_STR, OnEnqueued),
185         DECLARE_NAPI_FUNCTION(ONSTARTEXECUTION_STR, OnStartExecution),
186         DECLARE_NAPI_FUNCTION(ONEXECUTIONFAILED_STR, OnExecutionFailed),
187         DECLARE_NAPI_FUNCTION(ONEXECUTIONSUCCEEDED_STR, OnExecutionSucceeded),
188         DECLARE_NAPI_FUNCTION(ISDONE_STR, IsDone),
189         DECLARE_NAPI_GETTER(TASK_TOTAL_TIME, GetTotalDuration),
190         DECLARE_NAPI_GETTER(TASK_CPU_TIME, GetCPUDuration),
191         DECLARE_NAPI_GETTER(TASK_IO_TIME, GetIODuration),
192         DECLARE_NAPI_GETTER(NAME, GetName)
193     };
194     napi_define_properties(env, napiTask, sizeof(properties) / sizeof(properties[0]), properties);
195     return task;
196 }
197 
GenerateFunctionTask(napi_env env,napi_value func,napi_value * args,size_t argc,TaskType type)198 Task* Task::GenerateFunctionTask(napi_env env, napi_value func, napi_value* args, size_t argc, TaskType type)
199 {
200     HILOG_DEBUG("taskpool:: task GenerateFunctionTask");
201     napi_value argsArray;
202     napi_create_array_with_length(env, argc, &argsArray);
203     for (size_t i = 0; i < argc; i++) {
204         napi_set_element(env, argsArray, i, args[i]);
205     }
206     napi_value undefined = NapiHelper::GetUndefinedValue(env);
207     TaskInfo* taskInfo = GenerateTaskInfo(env, func, argsArray, undefined, undefined, Priority::DEFAULT);
208     if (taskInfo == nullptr) {
209         HILOG_ERROR("taskpool:: task GenerateFunctionTask end, taskInfo is nullptr");
210         return nullptr;
211     }
212     napi_value napiFuncName = NapiHelper::GetNameProperty(env, func, NAME);
213     char* nameStr = NapiHelper::GetChars(env, napiFuncName);
214     Task* task = new Task(env, type, nameStr);
215     delete[] nameStr;
216     task->taskId_ = reinterpret_cast<uint64_t>(task);
217     task->currentTaskInfo_ = taskInfo;
218     task->InitHandle(env);
219     if (!task->IsMainThreadTask()) {
220         napi_add_env_cleanup_hook(env, CleanupHookFunc, task);
221     }
222     return task;
223 }
224 
GetTaskInfoPromise(napi_env env,napi_value task,TaskType taskType,Priority priority)225 napi_value Task::GetTaskInfoPromise(napi_env env, napi_value task, TaskType taskType, Priority priority)
226 {
227     TaskInfo* taskInfo = GetTaskInfo(env, task, priority);
228     if (taskInfo == nullptr) {
229         return nullptr;
230     }
231     UpdateTaskType(taskType);
232     return NapiHelper::CreatePromise(env, &taskInfo->deferred);
233 }
234 
GetTaskInfo(napi_env env,napi_value task,Priority priority)235 TaskInfo* Task::GetTaskInfo(napi_env env, napi_value task, Priority priority)
236 {
237     napi_value func = NapiHelper::GetNameProperty(env, task, FUNCTION_STR);
238     napi_value args = NapiHelper::GetNameProperty(env, task, ARGUMENTS_STR);
239     napi_value taskName = NapiHelper::GetNameProperty(env, task, NAME);
240     napi_value napiDefaultTransfer = NapiHelper::GetNameProperty(env, task, DEFAULT_TRANSFER_STR);
241     napi_value napiDefaultClone = NapiHelper::GetNameProperty(env, task, DEFAULT_CLONE_SENDABLE_STR);
242     if (func == nullptr || args == nullptr || napiDefaultTransfer == nullptr || napiDefaultClone == nullptr) {
243         std::string errMessage = "taskpool:: task value is error";
244         HILOG_ERROR("%{public}s", errMessage.c_str());
245         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
246         return nullptr;
247     }
248     napi_value transferList = NapiHelper::GetUndefinedValue(env);
249     if (NapiHelper::HasNameProperty(env, task, TRANSFERLIST_STR)) {
250         transferList = NapiHelper::GetNameProperty(env, task, TRANSFERLIST_STR);
251     }
252     napi_value cloneList = NapiHelper::GetUndefinedValue(env);
253     if (NapiHelper::HasNameProperty(env, task, CLONE_LIST_STR)) {
254         cloneList = NapiHelper::GetNameProperty(env, task, CLONE_LIST_STR);
255     }
256     bool defaultTransfer = NapiHelper::GetBooleanValue(env, napiDefaultTransfer);
257     bool defaultCloneSendable = NapiHelper::GetBooleanValue(env, napiDefaultClone);
258     TaskInfo* pendingInfo = GenerateTaskInfo(env, func, args, transferList, cloneList, priority,
259                                              defaultTransfer, defaultCloneSendable);
260     if (pendingInfo == nullptr) {
261         return nullptr;
262     }
263     {
264         std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
265         if (currentTaskInfo_ == nullptr) {
266             currentTaskInfo_ = pendingInfo;
267         } else {
268             pendingTaskInfos_.push_back(pendingInfo);
269         }
270     }
271     char* name = NapiHelper::GetChars(env, taskName);
272     if (strlen(name) == 0) {
273         napi_value funcName = NapiHelper::GetNameProperty(env, func, NAME);
274         name = NapiHelper::GetChars(env, funcName);
275     }
276     name_ = std::string(name);
277     delete[] name;
278     return pendingInfo;
279 }
280 
SetTransferList(napi_env env,napi_callback_info cbinfo)281 napi_value Task::SetTransferList(napi_env env, napi_callback_info cbinfo)
282 {
283     size_t argc = 1;
284     napi_value args[1];
285     napi_value thisVar;
286     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
287     // Check whether clone list has been set
288     if (NapiHelper::HasNameProperty(env, thisVar, CLONE_LIST_STR)) {
289         ErrorHelper::ThrowError(env, ErrorHelper::ERR_IN_BOTH_CLONE_AND_TRANSFER);
290         return nullptr;
291     }
292     if (argc > 1) {
293         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
294             "the number of setTransferList parma must be less than 2.");
295         return nullptr;
296     }
297     Task* task = nullptr;
298     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
299     if (task == nullptr) {
300         HILOG_ERROR("taskpool:: task is nullptr");
301         return nullptr;
302     }
303     napi_value undefined = NapiHelper::GetUndefinedValue(env);
304     napi_value falseVal = NapiHelper::CreateBooleanValue(env, false);
305     if (argc == 0) {
306         HILOG_DEBUG("taskpool:: set task params not transfer");
307         napi_set_named_property(env, thisVar, TRANSFERLIST_STR, undefined);
308         // set task.defaultTransfer false
309         napi_set_named_property(env, thisVar, DEFAULT_TRANSFER_STR, falseVal);
310         return nullptr;
311     }
312     if (!NapiHelper::IsArray(env, args[0])) {
313         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
314             "the type of setTransferList first param must be array.");
315         return nullptr;
316     }
317     // set task.defaultTransfer false
318     napi_set_named_property(env, thisVar, DEFAULT_TRANSFER_STR, falseVal);
319     uint32_t arrayLength = NapiHelper::GetArrayLength(env, args[0]);
320     if (arrayLength == 0) {
321         HILOG_DEBUG("taskpool:: set task params not transfer");
322         napi_set_named_property(env, thisVar, TRANSFERLIST_STR, undefined);
323         return nullptr;
324     }
325     for (size_t i = 0; i < arrayLength; i++) {
326         napi_value transferVal = NapiHelper::GetElement(env, args[0], i);
327         if (!NapiHelper::IsArrayBuffer(env, transferVal)) {
328             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
329                 "the type of the element in array must be arraybuffer.");
330             return nullptr;
331         }
332     }
333     HILOG_DEBUG("taskpool:: check setTransferList param success");
334     napi_set_named_property(env, thisVar, TRANSFERLIST_STR, args[0]);
335     return nullptr;
336 }
337 
SetCloneList(napi_env env,napi_callback_info cbinfo)338 napi_value Task::SetCloneList(napi_env env, napi_callback_info cbinfo)
339 {
340     size_t argc = 1;
341     napi_value args[1];
342     napi_value thisVar;
343     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
344     // Check whether transfer list has been set
345     if (NapiHelper::HasNameProperty(env, thisVar, TRANSFERLIST_STR)) {
346         ErrorHelper::ThrowError(env, ErrorHelper::ERR_IN_BOTH_CLONE_AND_TRANSFER);
347         return nullptr;
348     }
349     if (argc != 1) {
350         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
351             "the number of setCloneList parma must be 1.");
352         return nullptr;
353     }
354     if (!NapiHelper::IsArray(env, args[0])) {
355         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
356             "the type of setCloneList first param must be array.");
357         return nullptr;
358     }
359     Task* task = nullptr;
360     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
361     if (task == nullptr) {
362         HILOG_ERROR("taskpool:: task is nullptr");
363         return nullptr;
364     }
365     napi_value undefined = NapiHelper::GetUndefinedValue(env);
366     uint32_t arrayLength = NapiHelper::GetArrayLength(env, args[0]);
367     if (arrayLength == 0) {
368         HILOG_DEBUG("taskpool:: clone list is empty");
369         napi_set_named_property(env, thisVar, CLONE_LIST_STR, undefined);
370         return nullptr;
371     }
372     for (size_t i = 0; i < arrayLength; i++) {
373         napi_value cloneVal = NapiHelper::GetElement(env, args[0], i);
374         if (NapiHelper::IsBitVector(env, cloneVal)) {
375             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "BitVector not support setCloneList.");
376             return nullptr;
377         }
378         if (!NapiHelper::IsArrayBuffer(env, cloneVal) && !NapiHelper::IsSendable(env, cloneVal)) {
379             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
380                 "the type of setCloneList elements in array must be arraybuffer or sendable.");
381             return nullptr;
382         }
383     }
384     napi_set_named_property(env, thisVar, CLONE_LIST_STR, args[0]);
385     return nullptr;
386 }
387 
IsCanceled(napi_env env,napi_callback_info cbinfo)388 napi_value Task::IsCanceled(napi_env env, napi_callback_info cbinfo)
389 {
390     bool isCanceled = false;
391     auto engine = reinterpret_cast<NativeEngine*>(env);
392     if (!engine->IsTaskPoolThread()) {
393         HILOG_ERROR("taskpool:: call isCanceled not in taskpool thread");
394         return NapiHelper::CreateBooleanValue(env, isCanceled);
395     }
396     // Get task and query task cancel state
397     void* data = engine->GetCurrentTaskInfo();
398     if (data == nullptr) {
399         HILOG_ERROR("taskpool:: call isCanceled not in Concurrent function");
400     } else {
401         Task* task = static_cast<Task*>(data);
402         isCanceled = task->taskState_ == ExecuteState::CANCELED ? true : false;
403     }
404     return NapiHelper::CreateBooleanValue(env, isCanceled);
405 }
406 
OnReceiveData(napi_env env,napi_callback_info cbinfo)407 napi_value Task::OnReceiveData(napi_env env, napi_callback_info cbinfo)
408 {
409     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
410     if (argc >= 2) { // 2: the number of parmas
411         HILOG_ERROR("taskpool:: the number of OnReceiveData parma must be less than 2");
412         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
413             "the number of OnReceiveData parma must be less than 2.");
414         return nullptr;
415     }
416 
417     napi_value thisVar;
418     if (argc == 0) {
419         HILOG_INFO("taskpool:: Set taskpool.Task.onReceiveData to undefined");
420         napi_get_cb_info(env, cbinfo, &argc, nullptr, &thisVar, nullptr);
421         napi_value id = NapiHelper::GetNameProperty(env, thisVar, "taskId");
422         uint64_t taskId = NapiHelper::GetUint64Value(env, id);
423         TaskManager::GetInstance().RegisterCallback(env, taskId, nullptr);
424         return nullptr;
425     }
426 
427     napi_value args[1];
428     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
429     napi_valuetype type;
430     NAPI_CALL(env, napi_typeof(env, args[0], &type));
431     if (type != napi_function) {
432         HILOG_ERROR("taskpool:: OnReceiveData's parameter should be function");
433         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
434             "the type of onReceiveData's parameter must be function.");
435         return nullptr;
436     }
437     // store callbackInfo
438     napi_value napiTaskId = NapiHelper::GetNameProperty(env, thisVar, "taskId");
439     uint64_t taskId = NapiHelper::GetUint64Value(env, napiTaskId);
440     auto task = TaskManager::GetInstance().GetTask(taskId);
441     if (task == nullptr) {
442         HILOG_ERROR("taskpool:: OnReceiveData's task is nullptr");
443         return nullptr;
444     }
445     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
446     std::shared_ptr<CallbackInfo> callbackInfo = std::make_shared<CallbackInfo>(env, 1, callbackRef, task);
447 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
448     if (!task->IsMainThreadTask()) {
449         auto loop = NapiHelper::GetLibUV(env);
450         ConcurrentHelper::UvHandleInit(loop, callbackInfo->onCallbackSignal, TaskPool::ExecuteCallback);
451     }
452 #else
453     auto loop = NapiHelper::GetLibUV(env);
454     ConcurrentHelper::UvHandleInit(loop, callbackInfo->onCallbackSignal, TaskPool::ExecuteCallback);
455 #endif
456     TaskManager::GetInstance().RegisterCallback(env, taskId, callbackInfo);
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     Task* task = nullptr;
479     void* data = engine->GetCurrentTaskInfo();
480     if (data == nullptr) {
481         HILOG_ERROR("taskpool:: SendData is not called in the concurrent function");
482         ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_IN_CONCURRENT_FUNCTION);
483         return nullptr;
484     } else {
485         task = static_cast<Task*>(data);
486     }
487 
488     napi_value undefined = NapiHelper::GetUndefinedValue(env);
489     void* serializationArgs = nullptr;
490     bool defaultClone = false;
491     bool defaultTransfer = true;
492     napi_status status = napi_serialize_inner(env, argsArray, undefined, undefined,
493                                               defaultTransfer, defaultClone, &serializationArgs);
494     if (status != napi_ok || serializationArgs == nullptr) {
495         std::string errMessage = "taskpool:: failed to serialize function";
496         HILOG_ERROR("%{public}s in SendData", errMessage.c_str());
497         ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
498         return nullptr;
499     }
500 
501     TaskResultInfo* resultInfo = new TaskResultInfo(task->env_, env, task->taskId_, serializationArgs);
502     return TaskManager::GetInstance().NotifyCallbackExecute(env, resultInfo, task);
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->IsGroupCommonTask()) {
539         errMessage = "taskpool:: groupTask cannot addDependency";
540         HILOG_ERROR("%{public}s", errMessage.c_str());
541         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
542         return nullptr;
543     }
544     task->SetHasDependency(true);
545     std::set<uint64_t> idSet;
546     for (size_t i = 0; i < argc; i++) {
547         if (!NapiHelper::HasNameProperty(env, args[i], TASKID_STR)) {
548             errMessage = "taskpool:: addDependency param is not task";
549             HILOG_ERROR("%{public}s", errMessage.c_str());
550             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
551                 "the type of the addDependency param must be task.");
552             return nullptr;
553         } else {
554             Task* dependentTask = nullptr;
555             napi_unwrap(env, args[i], reinterpret_cast<void**>(&dependentTask));
556             if (dependentTask == nullptr) {
557                 HILOG_ERROR("taskpool:: dependentTask is nullptr");
558                 return nullptr;
559             }
560             if (dependentTask->taskId_ == task->taskId_) {
561                 HILOG_ERROR("taskpool:: there is a circular dependency");
562                 ErrorHelper::ThrowError(env, ErrorHelper::ERR_CIRCULAR_DEPENDENCY);
563                 return nullptr;
564             }
565             if (dependentTask->IsPeriodicTask()) {
566                 HILOG_ERROR("taskpool:: the periodic task cannot have a dependency");
567                 ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
568                 return nullptr;
569             }
570             if (dependentTask->IsCommonTask() || dependentTask->IsSeqRunnerTask()) {
571                 errMessage = "taskpool:: seqRunnerTask or executedTask cannot be relied on";
572                 HILOG_ERROR("%{public}s", errMessage.c_str());
573                 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
574                 return nullptr;
575             }
576             if (dependentTask->IsGroupCommonTask()) {
577                 errMessage = "taskpool:: groupTask cannot be relied on";
578                 HILOG_ERROR("%{public}s", errMessage.c_str());
579                 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
580                 return nullptr;
581             }
582             idSet.emplace(dependentTask->taskId_);
583             dependentTask->SetHasDependency(true);
584         }
585     }
586     if (!TaskManager::GetInstance().StoreTaskDependency(task->taskId_, idSet)) {
587         HILOG_ERROR("taskpool:: there is a circular dependency");
588         ErrorHelper::ThrowError(env, ErrorHelper::ERR_CIRCULAR_DEPENDENCY);
589     }
590     std::string strTrace = "Task::AddDependency: ";
591     HITRACE_HELPER_METER_NAME(strTrace + TaskManager::GetInstance().GetTaskDependInfoToString(task->taskId_));
592     return nullptr;
593 }
594 
RemoveDependency(napi_env env,napi_callback_info cbinfo)595 napi_value Task::RemoveDependency(napi_env env, napi_callback_info cbinfo)
596 {
597     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
598     if (argc == 0) {
599         std::string errMessage = "taskpool:: removeDependency has no params";
600         HILOG_ERROR("%{public}s", errMessage.c_str());
601         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "removeDependency has no params.");
602         return nullptr;
603     }
604     napi_status status = napi_ok;
605     HandleScope scope(env, status);
606     napi_value args[argc];
607     napi_value napiTask;
608     napi_get_cb_info(env, cbinfo, &argc, args, &napiTask, nullptr);
609     Task* task = nullptr;
610     napi_unwrap(env, napiTask, reinterpret_cast<void**>(&task));
611     if (task == nullptr) {
612         HILOG_ERROR("taskpool:: the task is nullptr");
613         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the task is nullptr");
614         return nullptr;
615     }
616     if (!task->HasDependency()) {
617         ThrowNoDependencyError(env);
618         return nullptr;
619     }
620     if (task->IsPeriodicTask()) {
621         HILOG_ERROR("taskpool:: the periodic task cannot call removeDependency");
622         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
623         return nullptr;
624     }
625     if (task->IsCommonTask()) {
626         std::string errMessage = "taskpool:: executedTask cannot removeDependency";
627         HILOG_ERROR("%{public}s", errMessage.c_str());
628         ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY, errMessage.c_str());
629         return nullptr;
630     }
631     for (size_t i = 0; i < argc; i++) {
632         if (!NapiHelper::HasNameProperty(env, args[i], TASKID_STR)) {
633             std::string errMessage = "taskpool:: removeDependency param is not task";
634             HILOG_ERROR("%{public}s", errMessage.c_str());
635             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
636                 "the type of removeDependency param must be task.");
637             return nullptr;
638         }
639         Task* dependentTask = nullptr;
640         napi_unwrap(env, args[i], reinterpret_cast<void**>(&dependentTask));
641         if (dependentTask == nullptr) {
642             HILOG_ERROR("taskpool:: the dependent task is nullptr");
643             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the dependent task is nullptr");
644             return nullptr;
645         }
646         if (!dependentTask->HasDependency()) {
647             ThrowNoDependencyError(env);
648             return nullptr;
649         }
650         if (dependentTask->IsPeriodicTask()) {
651             HILOG_ERROR("taskpool:: the periodic task cannot call removeDependency");
652             ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_HAVE_DEPENDENCY);
653             return nullptr;
654         }
655         if (dependentTask->IsCommonTask()) {
656             std::string errMessage = "taskpool:: cannot removeDependency on a dependent and executed task";
657             HILOG_ERROR("%{public}s", errMessage.c_str());
658             ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
659             return nullptr;
660         }
661         if (!TaskManager::GetInstance().RemoveTaskDependency(task->taskId_, dependentTask->taskId_)) {
662             HILOG_ERROR("taskpool:: the dependency does not exist");
663             ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY);
664             return nullptr;
665         }
666         dependentTask->TryClearHasDependency();
667     }
668     task->TryClearHasDependency();
669     std::string strTrace = "Task::RemoveDependency: ";
670     HITRACE_HELPER_METER_NAME(strTrace + TaskManager::GetInstance().GetTaskDependInfoToString(task->taskId_));
671     return nullptr;
672 }
673 
StartExecutionCallback(const uv_async_t * req)674 void Task::StartExecutionCallback(const uv_async_t* req)
675 {
676     HILOG_DEBUG("taskpool:: task StartExecutionCallback");
677     auto listenerCallBackInfo = static_cast<ListenerCallBackInfo*>(req->data);
678     if (listenerCallBackInfo == nullptr) { // LCOV_EXCL_BR_LINE
679         HILOG_FATAL("taskpool:: StartExecutionCallBackInfo is null");
680         return;
681     }
682     StartExecutionTask(listenerCallBackInfo);
683 }
684 
StartExecutionTask(ListenerCallBackInfo * listenerCallBackInfo)685 void Task::StartExecutionTask(ListenerCallBackInfo* listenerCallBackInfo)
686 {
687     auto env = listenerCallBackInfo->env_;
688     napi_status status = napi_ok;
689     HandleScope scope(env, status);
690     if (status != napi_ok) {
691         HILOG_ERROR("taskpool:: napi_open_handle_scope failed");
692         return;
693     }
694     auto func = NapiHelper::GetReferenceValue(env, listenerCallBackInfo->callbackRef_);
695     if (func == nullptr) {
696         HILOG_INFO("taskpool:: StartExecutionCallback func is null");
697         return;
698     }
699 
700     napi_value result;
701     napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 0, nullptr, &result);
702     if (NapiHelper::IsExceptionPending(env)) {
703         napi_value exception = nullptr;
704         napi_get_and_clear_last_exception(env, &exception);
705         std::string funcStr = NapiHelper::GetPrintString(env, func);
706         HILOG_ERROR("taskpool:: an exception has occurred napi_call_function, func is %{public}s", funcStr.c_str());
707     }
708 }
709 
ExecuteListenerCallback(ListenerCallBackInfo * listenerCallBackInfo)710 void Task::ExecuteListenerCallback(ListenerCallBackInfo* listenerCallBackInfo)
711 {
712     HILOG_DEBUG("taskpool:: task ExecuteListenerCallback");
713     if (listenerCallBackInfo == nullptr) { // LCOV_EXCL_BR_LINE
714         HILOG_FATAL("taskpool:: listenerCallBackInfo is null");
715         return;
716     }
717 
718     napi_env env = listenerCallBackInfo->env_;
719     napi_value func = NapiHelper::GetReferenceValue(env, listenerCallBackInfo->callbackRef_);
720     if (func == nullptr) {
721         HILOG_INFO("taskpool:: ExecuteListenerCallback func is null");
722         return;
723     }
724 
725     napi_value result;
726     napi_value args = listenerCallBackInfo->taskError_;
727     if (args != nullptr) {
728         napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 1, &args, &result);
729     } else {
730         napi_call_function(env, NapiHelper::GetGlobalObject(env), func, 0, nullptr, &result);
731     }
732 
733     if (NapiHelper::IsExceptionPending(env)) {
734         napi_value exception = nullptr;
735         napi_get_and_clear_last_exception(env, &exception);
736         std::string funcStr = NapiHelper::GetPrintString(env, func);
737         HILOG_ERROR("taskpool:: an exception has occurred napi_call_function, func is %{public}s", funcStr.c_str());
738     }
739 }
740 
OnEnqueued(napi_env env,napi_callback_info cbinfo)741 napi_value Task::OnEnqueued(napi_env env, napi_callback_info cbinfo)
742 {
743     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
744     napi_value thisVar;
745     if (argc == 0) {
746         HILOG_INFO("taskpool:: the number of the params must be one");
747         return nullptr;
748     }
749 
750     napi_value args[1];
751     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
752     napi_valuetype type;
753     NAPI_CALL(env, napi_typeof(env, args[0], &type));
754     if (type != napi_function) {
755         HILOG_ERROR("taskpool:: OnEnqueued's parameter should be function");
756         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
757             "the type of OnEnqueued's parameter must be function.");
758         return nullptr;
759     }
760 
761     Task* task = nullptr;
762     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
763     if (task == nullptr) {
764         HILOG_ERROR("taskpool:: task is nullptr");
765         return nullptr;
766     }
767 
768     if (task->taskState_ != ExecuteState::NOT_FOUND) {
769         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
770         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
771         return nullptr;
772     }
773 
774     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
775     task->onEnqueuedCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
776     return nullptr;
777 }
778 
OnStartExecution(napi_env env,napi_callback_info cbinfo)779 napi_value Task::OnStartExecution(napi_env env, napi_callback_info cbinfo)
780 {
781     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
782     napi_value thisVar;
783     if (argc == 0) {
784         HILOG_INFO("taskpool:: the number of the params must be one");
785         return nullptr;
786     }
787 
788     napi_value args[1];
789     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
790     napi_valuetype type;
791     NAPI_CALL(env, napi_typeof(env, args[0], &type));
792     if (type != napi_function) {
793         HILOG_ERROR("taskpool:: OnStartExecution's parameter should be function");
794         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
795             "the type of OnStartExecution's parameter must be function.");
796         return nullptr;
797     }
798 
799     Task* task = nullptr;
800     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
801     if (task == nullptr) {
802         HILOG_ERROR("taskpool:: task is nullptr");
803         return nullptr;
804     }
805 
806     if (task->taskState_ != ExecuteState::NOT_FOUND) {
807         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
808         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
809         return nullptr;
810     }
811 
812     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
813     task->onStartExecutionCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
814 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
815     if (!task->IsMainThreadTask()) {
816         auto loop = NapiHelper::GetLibUV(env);
817         ConcurrentHelper::UvHandleInit(loop, task->onStartExecutionSignal_,
818             Task::StartExecutionCallback, task->onStartExecutionCallBackInfo_);
819     }
820 #else
821     auto loop = NapiHelper::GetLibUV(env);
822     ConcurrentHelper::UvHandleInit(loop, task->onStartExecutionSignal_,
823         Task::StartExecutionCallback, task->onStartExecutionCallBackInfo_);
824 #endif
825 
826     return nullptr;
827 }
828 
OnExecutionFailed(napi_env env,napi_callback_info cbinfo)829 napi_value Task::OnExecutionFailed(napi_env env, napi_callback_info cbinfo)
830 {
831     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
832     napi_value thisVar;
833     if (argc == 0) {
834         HILOG_INFO("taskpool:: the number of the params must be one");
835         return nullptr;
836     }
837 
838     napi_value args[1];
839     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
840     napi_valuetype type;
841     NAPI_CALL(env, napi_typeof(env, args[0], &type));
842     if (type != napi_function) {
843         HILOG_ERROR("taskpool:: OnExecutionFailed's parameter should be function");
844         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
845             "the type of OnExecutionFailed's parameter must be function.");
846         return nullptr;
847     }
848 
849     Task* task = nullptr;
850     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
851     if (task == nullptr) {
852         HILOG_ERROR("taskpool:: task is nullptr");
853         return nullptr;
854     }
855 
856     if (task->taskState_ != ExecuteState::NOT_FOUND) {
857         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
858         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
859         return nullptr;
860     }
861 
862     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
863     task->onExecutionFailedCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
864     return nullptr;
865 }
866 
OnExecutionSucceeded(napi_env env,napi_callback_info cbinfo)867 napi_value Task::OnExecutionSucceeded(napi_env env, napi_callback_info cbinfo)
868 {
869     size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
870     napi_value thisVar;
871     if (argc == 0) {
872         HILOG_INFO("taskpool:: the number of the params must be one");
873         return nullptr;
874     }
875 
876     napi_value args[1];
877     napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
878     napi_valuetype type;
879     NAPI_CALL(env, napi_typeof(env, args[0], &type));
880     if (type != napi_function) {
881         HILOG_ERROR("taskpool:: OnExecutionSucceeded's parameter should be function");
882         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
883             "the type of OnExecutionSucceeded's parameter must be function");
884         return nullptr;
885     }
886 
887     Task* task = nullptr;
888     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
889     if (task == nullptr) {
890         HILOG_ERROR("taskpool:: task is nullptr");
891         return nullptr;
892     }
893 
894     if (task->taskState_ != ExecuteState::NOT_FOUND) {
895         HILOG_ERROR("taskpool:: The executed task does not support the registration of listeners.");
896         ErrorHelper::ThrowError(env, ErrorHelper::ERR_REGISTRATION_OF_LISTENERS);
897         return nullptr;
898     }
899 
900     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
901     task->onExecutionSucceededCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
902     return nullptr;
903 }
904 
IsDone(napi_env env,napi_callback_info cbinfo)905 napi_value Task::IsDone(napi_env env, napi_callback_info cbinfo)
906 {
907     napi_value thisVar = nullptr;
908     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
909     Task* task = nullptr;
910     napi_unwrap(env, thisVar, reinterpret_cast<void**>(&task));
911     if (task == nullptr) {
912         HILOG_ERROR("taskpool:: task is nullptr");
913         return NapiHelper::CreateBooleanValue(env, false);
914     }
915 
916     if (task->taskState_ == ExecuteState::FINISHED || task->taskState_ == ExecuteState::ENDING) {
917         return NapiHelper::CreateBooleanValue(env, true);
918     }
919     return NapiHelper::CreateBooleanValue(env, false);
920 }
921 
GetTaskDuration(napi_env env,napi_callback_info & cbinfo,std::string durationType)922 napi_value Task::GetTaskDuration(napi_env env, napi_callback_info& cbinfo, std::string durationType)
923 {
924     napi_value thisVar = nullptr;
925     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
926     napi_value napiTaskId = NapiHelper::GetNameProperty(env, thisVar, TASKID_STR);
927     uint64_t taskId = NapiHelper::GetUint64Value(env, napiTaskId);
928     uint64_t totalDuration = TaskManager::GetInstance().GetTaskDuration(taskId, durationType);
929     return NapiHelper::CreateUint32(env, totalDuration);
930 }
931 
GetTotalDuration(napi_env env,napi_callback_info cbinfo)932 napi_value Task::GetTotalDuration(napi_env env, napi_callback_info cbinfo)
933 {
934     return GetTaskDuration(env, cbinfo, TASK_TOTAL_TIME);
935 }
936 
GetCPUDuration(napi_env env,napi_callback_info cbinfo)937 napi_value Task::GetCPUDuration(napi_env env, napi_callback_info cbinfo)
938 {
939     return GetTaskDuration(env, cbinfo, TASK_CPU_TIME);
940 }
941 
GetIODuration(napi_env env,napi_callback_info cbinfo)942 napi_value Task::GetIODuration(napi_env env, napi_callback_info cbinfo)
943 {
944     return GetTaskDuration(env, cbinfo, TASK_IO_TIME);
945 }
946 
947 napi_value Task::GetName(napi_env env, [[maybe_unused]] napi_callback_info cbinfo)
948 {
949     napi_value thisVar = nullptr;
950     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
951     napi_value napiTaskId = NapiHelper::GetNameProperty(env, thisVar, TASKID_STR);
952     uint64_t taskId = NapiHelper::GetUint64Value(env, napiTaskId);
953     napi_value name = nullptr;
954     std::string taskName = TaskManager::GetInstance().GetTaskName(taskId);
955     napi_create_string_utf8(env, taskName.c_str(), NAPI_AUTO_LENGTH, &name);
956     return name;
957 }
958 
UpdateTaskType(TaskType taskType)959 void Task::UpdateTaskType(TaskType taskType)
960 {
961     taskType_ = taskType;
962     napi_reference_ref(env_, taskRef_, nullptr);
963 }
964 
IsRepeatableTask() const965 bool Task::IsRepeatableTask() const
966 {
967     return IsCommonTask() || IsGroupCommonTask() || IsGroupFunctionTask();
968 }
969 
IsGroupTask() const970 bool Task::IsGroupTask() const
971 {
972     return IsGroupCommonTask() || IsGroupFunctionTask();
973 }
974 
IsGroupCommonTask() const975 bool Task::IsGroupCommonTask() const
976 {
977     return taskType_ == TaskType::GROUP_COMMON_TASK;
978 }
979 
IsGroupFunctionTask() const980 bool Task::IsGroupFunctionTask() const
981 {
982     return taskType_ == TaskType::GROUP_FUNCTION_TASK;
983 }
984 
IsCommonTask() const985 bool Task::IsCommonTask() const
986 {
987     return taskType_ == TaskType::COMMON_TASK;
988 }
989 
IsSeqRunnerTask() const990 bool Task::IsSeqRunnerTask() const
991 {
992     return taskType_ == TaskType::SEQRUNNER_TASK;
993 }
994 
IsFunctionTask() const995 bool Task::IsFunctionTask() const
996 {
997     return taskType_ == TaskType::FUNCTION_TASK;
998 }
999 
IsLongTask() const1000 bool Task::IsLongTask() const
1001 {
1002     return isLongTask_;
1003 }
1004 
IsPeriodicTask() const1005 bool Task::IsPeriodicTask() const
1006 {
1007     return isPeriodicTask_;
1008 }
1009 
IsMainThreadTask() const1010 bool Task::IsMainThreadTask() const
1011 {
1012     return isMainThreadTask_;
1013 }
1014 
1015 // The uninitialized state is Task, and then taskType_ will be updated based on the task type.
IsExecuted() const1016 bool Task::IsExecuted() const
1017 {
1018     return taskType_ != TaskType::TASK;
1019 }
1020 
GenerateTaskInfo(napi_env env,napi_value func,napi_value args,napi_value transferList,napi_value cloneList,Priority priority,bool defaultTransfer,bool defaultCloneSendable)1021 TaskInfo* Task::GenerateTaskInfo(napi_env env, napi_value func, napi_value args,
1022                                  napi_value transferList, napi_value cloneList, Priority priority,
1023                                  bool defaultTransfer, bool defaultCloneSendable)
1024 {
1025     HILOG_DEBUG("taskpool:: task GenerateTaskInfo");
1026     napi_value undefined = NapiHelper::GetUndefinedValue(env);
1027     void* serializationFunction = nullptr;
1028     napi_status status = napi_serialize_inner(env, func, undefined, undefined,
1029                                               defaultTransfer, defaultCloneSendable, &serializationFunction);
1030     std::string errMessage = "";
1031     if (status != napi_ok || serializationFunction == nullptr) {
1032         errMessage = "taskpool: failed to serialize function.";
1033         HILOG_ERROR("%{public}s", errMessage.c_str());
1034         ErrorHelper::ThrowError(env, ErrorHelper::ERR_NOT_CONCURRENT_FUNCTION, errMessage.c_str());
1035         return nullptr;
1036     }
1037     void* serializationArguments = nullptr;
1038     status = napi_serialize_inner(env, args, transferList, cloneList,
1039                                   defaultTransfer, defaultCloneSendable, &serializationArguments);
1040     if (status != napi_ok || serializationArguments == nullptr) {
1041         errMessage = "taskpool: failed to serialize arguments.";
1042         HILOG_ERROR("%{public}s", errMessage.c_str());
1043         ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1044         return nullptr;
1045     }
1046 
1047     TaskInfo* taskInfo = new TaskInfo();
1048     taskInfo->serializationFunction = serializationFunction;
1049     taskInfo->serializationArguments = serializationArguments;
1050     taskInfo->priority = priority;
1051     reinterpret_cast<NativeEngine*>(env)->IncreaseSubEnvCounter();
1052     return taskInfo;
1053 }
1054 
IncreaseRefCount()1055 void Task::IncreaseRefCount()
1056 {
1057     taskRefCount_.fetch_add(2); // 2 : for PerformTask and TaskResultCallback
1058 }
1059 
DecreaseRefCount()1060 void Task::DecreaseRefCount()
1061 {
1062     taskRefCount_.fetch_sub(1);
1063 }
1064 
IsReadyToHandle() const1065 bool Task::IsReadyToHandle() const
1066 {
1067     return (taskRefCount_ & 1) == 0;
1068 }
1069 
NotifyPendingTask()1070 void Task::NotifyPendingTask()
1071 {
1072     HILOG_DEBUG("taskpool:: task:%{public}s NotifyPendingTask", std::to_string(taskId_).c_str());
1073     TaskManager::GetInstance().NotifyDependencyTaskInfo(taskId_);
1074     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1075     delete currentTaskInfo_;
1076     if (pendingTaskInfos_.empty()) {
1077         currentTaskInfo_ = nullptr;
1078         HILOG_DEBUG("taskpool:: task:%{public}s NotifyPendingTask end, currentTaskInfo_ nullptr",
1079                     std::to_string(taskId_).c_str());
1080         return;
1081     }
1082     currentTaskInfo_ = pendingTaskInfos_.front();
1083     pendingTaskInfos_.pop_front();
1084     taskState_ = ExecuteState::WAITING;
1085     TaskManager::GetInstance().EnqueueTaskId(taskId_, currentTaskInfo_->priority);
1086 }
1087 
CancelPendingTask(napi_env env)1088 void Task::CancelPendingTask(napi_env env)
1089 {
1090     HILOG_DEBUG("taskpool:: task:%{public}s CancelPendingTask", std::to_string(taskId_).c_str());
1091     if (pendingTaskInfos_.empty()) {
1092         HILOG_DEBUG("taskpool:: task CancelPendingTask end, pendingTaskInfos_ nullptr");
1093         return;
1094     }
1095     napi_value error = nullptr;
1096     if (!IsPeriodicTask()) {
1097         error = ErrorHelper::NewError(env, 0, "taskpool:: task has been canceled");
1098     }
1099     auto engine = reinterpret_cast<NativeEngine*>(env);
1100     for (const auto& info : pendingTaskInfos_) {
1101         engine->DecreaseSubEnvCounter();
1102         if (!IsPeriodicTask()) {
1103             napi_reject_deferred(env, info->deferred, error);
1104         }
1105         napi_reference_unref(env, taskRef_, nullptr);
1106         delete info;
1107     }
1108     pendingTaskInfos_.clear();
1109 }
1110 
UpdateTask(uint64_t startTime,void * worker)1111 bool Task::UpdateTask(uint64_t startTime, void* worker)
1112 {
1113     HILOG_DEBUG("taskpool:: task:%{public}s UpdateTask", std::to_string(taskId_).c_str());
1114     if (taskState_ == ExecuteState::CANCELED) { // task may have been canceled
1115         HILOG_INFO("taskpool:: task has been canceled, taskId %{public}s", std::to_string(taskId_).c_str());
1116         return false;
1117     }
1118     taskState_ = ExecuteState::RUNNING;
1119     startTime_ = startTime;
1120     worker_ = worker;
1121     isRunning_ = true;
1122     return true;
1123 }
1124 
DeserializeValue(napi_env env,napi_value * func,napi_value * args)1125 napi_value Task::DeserializeValue(napi_env env, napi_value* func, napi_value* args)
1126 {
1127     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1128     if (UNLIKELY(currentTaskInfo_ == nullptr)) {
1129         HILOG_ERROR("taskpool:: the currentTaskInfo is nullptr, the task may have been cancelled");
1130         return nullptr;
1131     }
1132 
1133     napi_status status = napi_ok;
1134     std::string errMessage = "";
1135     status = napi_deserialize(env, currentTaskInfo_->serializationFunction, func);
1136     if (!IsGroupFunctionTask()) {
1137         napi_delete_serialization_data(env, currentTaskInfo_->serializationFunction);
1138     }
1139     if (status != napi_ok || func == nullptr) {
1140         errMessage = "taskpool:: failed to deserialize function.";
1141         HILOG_ERROR("%{public}s", errMessage.c_str());
1142         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1143         success_ = false;
1144         return err;
1145     }
1146 
1147     status = napi_deserialize(env, currentTaskInfo_->serializationArguments, args);
1148     if (!IsGroupFunctionTask()) {
1149         napi_delete_serialization_data(env, currentTaskInfo_->serializationArguments);
1150     }
1151     if (status != napi_ok || args == nullptr) {
1152         errMessage = "taskpool:: failed to deserialize function.";
1153         HILOG_ERROR("%{public}s", errMessage.c_str());
1154         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1155         success_ = false;
1156         return err;
1157     }
1158     return nullptr;
1159 }
1160 
StoreTaskDuration()1161 void Task::StoreTaskDuration()
1162 {
1163     HILOG_DEBUG("taskpool:: task:%{public}s StoreTaskDuration", std::to_string(taskId_).c_str());
1164     cpuTime_ = ConcurrentHelper::GetMilliseconds();
1165     uint64_t cpuDuration = cpuTime_ - startTime_;
1166     if (ioTime_ != 0) {
1167         uint64_t ioDuration = ioTime_ - startTime_;
1168         TaskManager::GetInstance().StoreTaskDuration(taskId_, std::max(cpuDuration, ioDuration), cpuDuration);
1169     } else {
1170         TaskManager::GetInstance().StoreTaskDuration(taskId_, 0, cpuDuration);
1171     }
1172 }
1173 
CanForSequenceRunner(napi_env env)1174 bool Task::CanForSequenceRunner(napi_env env)
1175 {
1176     std::string errMessage = "";
1177     // task with dependence is not allowed
1178     if (HasDependency()) {
1179         errMessage = "seqRunner:: dependent task not allowed.";
1180         HILOG_ERROR("%{public}s", errMessage.c_str());
1181         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ADD_DEPENDENT_TASK_TO_SEQRUNNER, errMessage.c_str());
1182         return false;
1183     }
1184     if (IsPeriodicTask()) {
1185         errMessage = "taskpool:: SequenceRunner cannot execute the periodicTask";
1186         HILOG_ERROR("%{public}s", errMessage.c_str());
1187         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1188         return false;
1189     }
1190     if (IsCommonTask() || IsSeqRunnerTask()) {
1191         errMessage = "taskpool:: SequenceRunner cannot execute seqRunnerTask or executedTask";
1192         HILOG_ERROR("%{public}s", errMessage.c_str());
1193         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1194         return false;
1195     }
1196     if (IsGroupCommonTask()) {
1197         errMessage = "taskpool:: SequenceRunner cannot execute groupTask";
1198         HILOG_ERROR("%{public}s", errMessage.c_str());
1199         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1200         return false;
1201     }
1202     return true;
1203 }
1204 
CanForTaskGroup(napi_env env)1205 bool Task::CanForTaskGroup(napi_env env)
1206 {
1207     std::string errMessage = "";
1208     if (HasDependency()) {
1209         errMessage = "taskpool:: dependent task not allowed.";
1210         HILOG_ERROR("%{public}s", errMessage.c_str());
1211         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1212         return false;
1213     }
1214     if (IsPeriodicTask()) {
1215         errMessage = "taskpool:: The interface does not support the periodicTask";
1216         HILOG_ERROR("%{public}s", errMessage.c_str());
1217         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1218         return false;
1219     }
1220     if (IsCommonTask() || IsSeqRunnerTask()) {
1221         errMessage = "taskpool:: taskGroup cannot add seqRunnerTask or executedTask";
1222         HILOG_ERROR("%{public}s", errMessage.c_str());
1223         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1224         return false;
1225     }
1226     if (IsGroupCommonTask()) {
1227         errMessage = "taskpool:: taskGroup cannot add groupTask";
1228         HILOG_ERROR("%{public}s", errMessage.c_str());
1229         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1230         return false;
1231     }
1232     if (IsLongTask()) {
1233         errMessage = "taskpool:: The interface does not support the long task";
1234         HILOG_ERROR("%{public}s", errMessage.c_str());
1235         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1236         return false;
1237     }
1238     taskType_ = TaskType::GROUP_COMMON_TASK;
1239     return true;
1240 }
1241 
CanExecute(napi_env env)1242 bool Task::CanExecute(napi_env env)
1243 {
1244     std::string errMessage = "";
1245     if (IsGroupCommonTask()) {
1246         errMessage = "taskpool:: groupTask cannot execute outside";
1247         HILOG_ERROR("%{public}s", errMessage.c_str());
1248         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1249         return false;
1250     }
1251     if (IsSeqRunnerTask()) {
1252         errMessage = "taskpool:: seqRunnerTask cannot execute outside";
1253         HILOG_ERROR("%{public}s", errMessage.c_str());
1254         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1255         return false;
1256     }
1257     if (IsCommonTask() && HasDependency()) {
1258         errMessage = "taskpool:: executedTask with dependency cannot execute again";
1259         HILOG_ERROR("%{public}s", errMessage.c_str());
1260         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1261         return false;
1262     }
1263     if (IsExecuted() && IsLongTask()) {
1264         errMessage = "taskpool:: The long task can only be executed once";
1265         HILOG_ERROR("%{public}s", errMessage.c_str());
1266         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1267         return false;
1268     }
1269     if (IsPeriodicTask()) {
1270         errMessage = "taskpool:: the periodicTask cannot execute again";
1271         HILOG_ERROR("%{public}s", errMessage.c_str());
1272         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1273         return false;
1274     }
1275     return true;
1276 }
1277 
CanExecuteDelayed(napi_env env)1278 bool Task::CanExecuteDelayed(napi_env env)
1279 {
1280     std::string errMessage = "";
1281     if (IsGroupCommonTask()) {
1282         errMessage = "taskpool:: groupTask cannot executeDelayed outside";
1283         HILOG_ERROR("%{public}s", errMessage.c_str());
1284         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1285         return false;
1286     }
1287     if (IsSeqRunnerTask()) {
1288         errMessage = "taskpool:: seqRunnerTask cannot executeDelayed outside";
1289         HILOG_ERROR("%{public}s", errMessage.c_str());
1290         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1291         return false;
1292     }
1293     if (IsCommonTask() && HasDependency()) {
1294         errMessage = "taskpool:: executedTask with dependency cannot executeDelayed again";
1295         HILOG_ERROR("%{public}s", errMessage.c_str());
1296         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1297         return false;
1298     }
1299     if (IsExecuted() && IsLongTask()) {
1300         errMessage = "taskpool:: Multiple executions of longTask are not supported in the executeDelayed";
1301         HILOG_ERROR("%{public}s", errMessage.c_str());
1302         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1303         return false;
1304     }
1305     if (IsPeriodicTask()) {
1306         errMessage = "taskpool:: the periodicTask cannot executeDelayed";
1307         HILOG_ERROR("%{public}s", errMessage.c_str());
1308         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1309         return false;
1310     }
1311     return true;
1312 }
1313 
CanExecutePeriodically(napi_env env)1314 bool Task::CanExecutePeriodically(napi_env env)
1315 {
1316     if (IsExecuted() || IsPeriodicTask()) {
1317         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_PERIODICALLY);
1318         return false;
1319     }
1320     if (HasDependency()) {
1321         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
1322             "taskpool:: the task with dependency cannot executePeriodically");
1323         return false;
1324     }
1325     return true;
1326 }
1327 
SetHasDependency(bool hasDependency)1328 void Task::SetHasDependency(bool hasDependency)
1329 {
1330     hasDependency_ = hasDependency;
1331 }
1332 
HasDependency() const1333 bool Task::HasDependency() const
1334 {
1335     return hasDependency_;
1336 }
1337 
TryClearHasDependency()1338 void Task::TryClearHasDependency()
1339 {
1340     HILOG_DEBUG("taskpool:: task:%{public}s TryClearHasDependency", std::to_string(taskId_).c_str());
1341     if (IsExecuted()) {
1342         HILOG_DEBUG("taskpool:: task TryClearHasDependency end, task is executed");
1343         return;
1344     }
1345     if ((!TaskManager::GetInstance().IsDependentByTaskId(taskId_)) &&
1346         (!TaskManager::GetInstance().IsDependendByTaskId(taskId_))) {
1347         SetHasDependency(false);
1348     }
1349 }
1350 
ThrowNoDependencyError(napi_env env)1351 void Task::ThrowNoDependencyError(napi_env env)
1352 {
1353     std::string errMessage = "taskpool:: task has no dependency";
1354     HILOG_ERROR("%{public}s", errMessage.c_str());
1355     ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY, errMessage.c_str());
1356 }
1357 
UpdatePeriodicTask()1358 void Task::UpdatePeriodicTask()
1359 {
1360     taskType_ = TaskType::COMMON_TASK;
1361     napi_reference_ref(env_, taskRef_, nullptr);
1362     isPeriodicTask_ = true;
1363 }
1364 
InitHandle(napi_env env)1365 void Task::InitHandle(napi_env env)
1366 {
1367 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1368     if (!OHOS::AppExecFwk::EventRunner::IsAppMainThread()) {
1369         uv_loop_t* loop = NapiHelper::GetLibUV(env);
1370         ConcurrentHelper::UvHandleInit(loop, onResultSignal_, TaskPool::HandleTaskResult, this);
1371     } else {
1372         isMainThreadTask_ = true;
1373         HILOG_DEBUG("taskpool:: eventrunner should be nullptr if the current thread is not the main thread");
1374     }
1375 #else
1376     uv_loop_t* loop = NapiHelper::GetLibUV(env);
1377     ConcurrentHelper::UvHandleInit(loop, onResultSignal_, TaskPool::HandleTaskResult, this);
1378     auto engine = reinterpret_cast<NativeEngine*>(env);
1379     isMainThreadTask_ = engine->IsMainThread();
1380 #endif
1381 }
1382 
ClearDelayedTimers()1383 void Task::ClearDelayedTimers()
1384 {
1385     HILOG_DEBUG("taskpool:: task ClearDelayedTimers");
1386     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1387     TaskMessage *taskMessage = nullptr;
1388     for (auto t: delayedTimers_) {
1389         if (t == nullptr) {
1390             continue;
1391         }
1392         taskMessage = static_cast<TaskMessage *>(t->data);
1393         napi_value error = ErrorHelper::NewError(env_, 0, "taskpool:: task has been canceled");
1394         napi_reject_deferred(env_, taskMessage->deferred, error);
1395         uv_timer_stop(t);
1396         uv_close(reinterpret_cast<uv_handle_t*>(t), [](uv_handle_t* handle) {
1397             delete (uv_timer_t*)handle;
1398             handle = nullptr;
1399         });
1400         delete taskMessage;
1401         taskMessage = nullptr;
1402     }
1403     delayedTimers_.clear();
1404 }
1405 
VerifyAndPostResult(Priority priority)1406 bool Task::VerifyAndPostResult(Priority priority)
1407 {
1408 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1409     if (IsMainThreadTask()) {
1410         HITRACE_HELPER_METER_NAME("VerifyAndPostResult: PostTask");
1411         uint64_t taskId = taskId_;
1412         auto onResultTask = [taskId]() {
1413             Task* task = TaskManager::GetInstance().GetTask(taskId);
1414             if (task == nullptr) {
1415                 return;
1416             }
1417             TaskPool::HandleTaskResultCallback(task);
1418         };
1419         TaskManager::GetInstance().PostTask(onResultTask, "TaskPoolOnResultTask", priority);
1420         return true;
1421     } else {
1422         std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1423         if (!IsValid() || onResultSignal_ == nullptr || uv_is_closing((uv_handle_t*)onResultSignal_)) {
1424             return false;
1425         }
1426         uv_async_send(onResultSignal_);
1427         return true;
1428     }
1429 #else
1430     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1431     if (!IsValid() || onResultSignal_ == nullptr || uv_is_closing((uv_handle_t*)onResultSignal_)) {
1432         return false;
1433     }
1434     uv_async_send(onResultSignal_);
1435     return true;
1436 #endif
1437 }
1438 
IncreaseTaskRefCount()1439 void Task::IncreaseTaskRefCount()
1440 {
1441     refCount_++; // when tasks are created or executed, refCount_ will increment
1442 }
1443 
DecreaseTaskRefCount()1444 void Task::DecreaseTaskRefCount()
1445 {
1446     refCount_--; // when tasks finished, refCount_ will decrement
1447 }
1448 
ShouldDeleteTask(bool needUnref)1449 bool Task::ShouldDeleteTask(bool needUnref)
1450 {
1451     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1452     if (!IsValid()) {
1453         HILOG_WARN("taskpool:: task is invalid");
1454         TaskManager::GetInstance().RemoveTask(taskId_);
1455         return true;
1456     }
1457     if (needUnref) {
1458         DecreaseTaskRefCount();
1459     }
1460     return false;
1461 }
1462 
CheckStartExecution(Priority priority)1463 bool Task::CheckStartExecution(Priority priority)
1464 {
1465 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1466     if (IsMainThreadTask()) {
1467         if (onStartExecutionCallBackInfo_ == nullptr) {
1468             return true;
1469         }
1470         HITRACE_HELPER_METER_NAME("PerformTask: PostTask");
1471         uint64_t taskId = taskId_;
1472         auto onStartExecutionTask = [taskId]() {
1473             Task* task = TaskManager::GetInstance().GetTask(taskId);
1474             if (task == nullptr || task->onStartExecutionCallBackInfo_ == nullptr) {
1475                 return;
1476             }
1477             Task::StartExecutionTask(task->onStartExecutionCallBackInfo_);
1478         };
1479         TaskManager::GetInstance().PostTask(onStartExecutionTask, "TaskPoolOnStartExecutionTask", priority);
1480     } else {
1481         if (onStartExecutionSignal_ == nullptr) {
1482             return true;
1483         }
1484         std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1485         if (!IsValid()) {
1486             return false;
1487         }
1488         if (onStartExecutionSignal_ != nullptr && !uv_is_closing((uv_handle_t*)onStartExecutionSignal_)) {
1489             uv_async_send(onStartExecutionSignal_);
1490         }
1491     }
1492     return true;
1493 #else
1494     if (onStartExecutionSignal_ == nullptr) {
1495         return true;
1496     }
1497     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1498     if (!IsValid()) {
1499         return false;
1500     }
1501     if (onStartExecutionSignal_ != nullptr && !uv_is_closing((uv_handle_t*)onStartExecutionSignal_)) {
1502         uv_async_send(onStartExecutionSignal_);
1503     }
1504     return true;
1505 #endif
1506 }
1507 
SetValid(bool isValid)1508 void Task::SetValid(bool isValid)
1509 {
1510     isValid_.store(isValid);
1511 }
1512 
IsValid()1513 bool Task::IsValid()
1514 {
1515     return isValid_.load();
1516 }
1517 } // namespace Commonlibrary::Concurrent::TaskPoolModule