• 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 "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 
TaskDestructor(napi_env env,void * data,void * hint)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     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, args[0], 1);
441     auto task = TaskManager::GetInstance().GetTask(taskId);
442     if (task == nullptr) {
443         HILOG_ERROR("taskpool:: OnReceiveData's task is nullptr");
444         return nullptr;
445     }
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 
GetName(napi_env env,napi_callback_info cbinfo)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     return true;
1122 }
1123 
DeserializeValue(napi_env env,napi_value * func,napi_value * args)1124 napi_value Task::DeserializeValue(napi_env env, napi_value* func, napi_value* args)
1125 {
1126     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1127     if (UNLIKELY(currentTaskInfo_ == nullptr)) {
1128         HILOG_ERROR("taskpool:: the currentTaskInfo is nullptr, the task may have been cancelled");
1129         return nullptr;
1130     }
1131 
1132     napi_status status = napi_ok;
1133     std::string errMessage = "";
1134     status = napi_deserialize(env, currentTaskInfo_->serializationFunction, func);
1135     if (!IsGroupFunctionTask()) {
1136         napi_delete_serialization_data(env, currentTaskInfo_->serializationFunction);
1137     }
1138     if (status != napi_ok || func == nullptr) {
1139         errMessage = "taskpool:: failed to deserialize function.";
1140         HILOG_ERROR("%{public}s", errMessage.c_str());
1141         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1142         success_ = false;
1143         return err;
1144     }
1145 
1146     status = napi_deserialize(env, currentTaskInfo_->serializationArguments, args);
1147     if (!IsGroupFunctionTask()) {
1148         napi_delete_serialization_data(env, currentTaskInfo_->serializationArguments);
1149     }
1150     if (status != napi_ok || args == nullptr) {
1151         errMessage = "taskpool:: failed to deserialize function.";
1152         HILOG_ERROR("%{public}s", errMessage.c_str());
1153         napi_value err = ErrorHelper::NewError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, errMessage.c_str());
1154         success_ = false;
1155         return err;
1156     }
1157     return nullptr;
1158 }
1159 
StoreTaskDuration()1160 void Task::StoreTaskDuration()
1161 {
1162     HILOG_DEBUG("taskpool:: task:%{public}s StoreTaskDuration", std::to_string(taskId_).c_str());
1163     cpuTime_ = ConcurrentHelper::GetMilliseconds();
1164     uint64_t cpuDuration = cpuTime_ - startTime_;
1165     if (ioTime_ != 0) {
1166         uint64_t ioDuration = ioTime_ - startTime_;
1167         TaskManager::GetInstance().StoreTaskDuration(taskId_, std::max(cpuDuration, ioDuration), cpuDuration);
1168     } else {
1169         TaskManager::GetInstance().StoreTaskDuration(taskId_, 0, cpuDuration);
1170     }
1171 }
1172 
CanForSequenceRunner(napi_env env)1173 bool Task::CanForSequenceRunner(napi_env env)
1174 {
1175     std::string errMessage = "";
1176     // task with dependence is not allowed
1177     if (HasDependency()) {
1178         errMessage = "seqRunner:: dependent task not allowed.";
1179         HILOG_ERROR("%{public}s", errMessage.c_str());
1180         ErrorHelper::ThrowError(env, ErrorHelper::ERR_ADD_DEPENDENT_TASK_TO_SEQRUNNER, errMessage.c_str());
1181         return false;
1182     }
1183     if (IsPeriodicTask()) {
1184         errMessage = "taskpool:: SequenceRunner cannot execute the periodicTask";
1185         HILOG_ERROR("%{public}s", errMessage.c_str());
1186         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1187         return false;
1188     }
1189     if (IsCommonTask() || IsSeqRunnerTask()) {
1190         errMessage = "taskpool:: SequenceRunner cannot execute seqRunnerTask or executedTask";
1191         HILOG_ERROR("%{public}s", errMessage.c_str());
1192         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1193         return false;
1194     }
1195     if (IsGroupCommonTask()) {
1196         errMessage = "taskpool:: SequenceRunner cannot execute groupTask";
1197         HILOG_ERROR("%{public}s", errMessage.c_str());
1198         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1199         return false;
1200     }
1201     return true;
1202 }
1203 
CanForTaskGroup(napi_env env)1204 bool Task::CanForTaskGroup(napi_env env)
1205 {
1206     std::string errMessage = "";
1207     if (HasDependency()) {
1208         errMessage = "taskpool:: dependent task not allowed.";
1209         HILOG_ERROR("%{public}s", errMessage.c_str());
1210         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1211         return false;
1212     }
1213     if (IsPeriodicTask()) {
1214         errMessage = "taskpool:: The interface does not support the periodicTask";
1215         HILOG_ERROR("%{public}s", errMessage.c_str());
1216         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1217         return false;
1218     }
1219     if (IsCommonTask() || IsSeqRunnerTask()) {
1220         errMessage = "taskpool:: taskGroup cannot add seqRunnerTask or executedTask";
1221         HILOG_ERROR("%{public}s", errMessage.c_str());
1222         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1223         return false;
1224     }
1225     if (IsGroupCommonTask()) {
1226         errMessage = "taskpool:: taskGroup cannot add groupTask";
1227         HILOG_ERROR("%{public}s", errMessage.c_str());
1228         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1229         return false;
1230     }
1231     if (IsLongTask()) {
1232         errMessage = "taskpool:: The interface does not support the long task";
1233         HILOG_ERROR("%{public}s", errMessage.c_str());
1234         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1235         return false;
1236     }
1237     taskType_ = TaskType::GROUP_COMMON_TASK;
1238     return true;
1239 }
1240 
CanExecute(napi_env env)1241 bool Task::CanExecute(napi_env env)
1242 {
1243     std::string errMessage = "";
1244     if (IsGroupCommonTask()) {
1245         errMessage = "taskpool:: groupTask cannot execute outside";
1246         HILOG_ERROR("%{public}s", errMessage.c_str());
1247         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1248         return false;
1249     }
1250     if (IsSeqRunnerTask()) {
1251         errMessage = "taskpool:: seqRunnerTask cannot execute outside";
1252         HILOG_ERROR("%{public}s", errMessage.c_str());
1253         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1254         return false;
1255     }
1256     if (IsCommonTask() && HasDependency()) {
1257         errMessage = "taskpool:: executedTask with dependency cannot execute again";
1258         HILOG_ERROR("%{public}s", errMessage.c_str());
1259         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1260         return false;
1261     }
1262     if (IsExecuted() && IsLongTask()) {
1263         errMessage = "taskpool:: The long task can only be executed once";
1264         HILOG_ERROR("%{public}s", errMessage.c_str());
1265         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1266         return false;
1267     }
1268     if (IsPeriodicTask()) {
1269         errMessage = "taskpool:: the periodicTask cannot execute again";
1270         HILOG_ERROR("%{public}s", errMessage.c_str());
1271         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1272         return false;
1273     }
1274     return true;
1275 }
1276 
CanExecuteDelayed(napi_env env)1277 bool Task::CanExecuteDelayed(napi_env env)
1278 {
1279     std::string errMessage = "";
1280     if (IsGroupCommonTask()) {
1281         errMessage = "taskpool:: groupTask cannot executeDelayed outside";
1282         HILOG_ERROR("%{public}s", errMessage.c_str());
1283         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1284         return false;
1285     }
1286     if (IsSeqRunnerTask()) {
1287         errMessage = "taskpool:: seqRunnerTask cannot executeDelayed outside";
1288         HILOG_ERROR("%{public}s", errMessage.c_str());
1289         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1290         return false;
1291     }
1292     if (IsCommonTask() && HasDependency()) {
1293         errMessage = "taskpool:: executedTask with dependency cannot executeDelayed again";
1294         HILOG_ERROR("%{public}s", errMessage.c_str());
1295         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1296         return false;
1297     }
1298     if (IsExecuted() && IsLongTask()) {
1299         errMessage = "taskpool:: Multiple executions of longTask are not supported in the executeDelayed";
1300         HILOG_ERROR("%{public}s", errMessage.c_str());
1301         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
1302         return false;
1303     }
1304     if (IsPeriodicTask()) {
1305         errMessage = "taskpool:: the periodicTask cannot executeDelayed";
1306         HILOG_ERROR("%{public}s", errMessage.c_str());
1307         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_AGAIN, errMessage.c_str());
1308         return false;
1309     }
1310     return true;
1311 }
1312 
CanExecutePeriodically(napi_env env)1313 bool Task::CanExecutePeriodically(napi_env env)
1314 {
1315     if (IsExecuted() || IsPeriodicTask()) {
1316         ErrorHelper::ThrowError(env, ErrorHelper::ERR_TASK_EXECUTE_PERIODICALLY);
1317         return false;
1318     }
1319     if (HasDependency()) {
1320         ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
1321             "taskpool:: the task with dependency cannot executePeriodically");
1322         return false;
1323     }
1324     return true;
1325 }
1326 
SetHasDependency(bool hasDependency)1327 void Task::SetHasDependency(bool hasDependency)
1328 {
1329     hasDependency_ = hasDependency;
1330 }
1331 
HasDependency() const1332 bool Task::HasDependency() const
1333 {
1334     return hasDependency_;
1335 }
1336 
TryClearHasDependency()1337 void Task::TryClearHasDependency()
1338 {
1339     HILOG_DEBUG("taskpool:: task:%{public}s TryClearHasDependency", std::to_string(taskId_).c_str());
1340     if (IsExecuted()) {
1341         HILOG_DEBUG("taskpool:: task TryClearHasDependency end, task is executed");
1342         return;
1343     }
1344     if ((!TaskManager::GetInstance().IsDependentByTaskId(taskId_)) &&
1345         (!TaskManager::GetInstance().IsDependendByTaskId(taskId_))) {
1346         SetHasDependency(false);
1347     }
1348 }
1349 
ThrowNoDependencyError(napi_env env)1350 void Task::ThrowNoDependencyError(napi_env env)
1351 {
1352     std::string errMessage = "taskpool:: task has no dependency";
1353     HILOG_ERROR("%{public}s", errMessage.c_str());
1354     ErrorHelper::ThrowError(env, ErrorHelper::ERR_INEXISTENT_DEPENDENCY, errMessage.c_str());
1355 }
1356 
UpdatePeriodicTask()1357 void Task::UpdatePeriodicTask()
1358 {
1359     taskType_ = TaskType::COMMON_TASK;
1360     napi_reference_ref(env_, taskRef_, nullptr);
1361     isPeriodicTask_ = true;
1362 }
1363 
InitHandle(napi_env env)1364 void Task::InitHandle(napi_env env)
1365 {
1366 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1367     if (!OHOS::AppExecFwk::EventRunner::IsAppMainThread()) {
1368         uv_loop_t* loop = NapiHelper::GetLibUV(env);
1369         ConcurrentHelper::UvHandleInit(loop, onResultSignal_, TaskPool::HandleTaskResult, this);
1370     } else {
1371         isMainThreadTask_ = true;
1372         HILOG_DEBUG("taskpool:: eventrunner should be nullptr if the current thread is not the main thread");
1373     }
1374 #else
1375     uv_loop_t* loop = NapiHelper::GetLibUV(env);
1376     ConcurrentHelper::UvHandleInit(loop, onResultSignal_, TaskPool::HandleTaskResult, this);
1377     auto engine = reinterpret_cast<NativeEngine*>(env);
1378     isMainThreadTask_ = engine->IsMainThread();
1379 #endif
1380 }
1381 
ClearDelayedTimers()1382 void Task::ClearDelayedTimers()
1383 {
1384     HILOG_DEBUG("taskpool:: task ClearDelayedTimers");
1385     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1386     TaskMessage *taskMessage = nullptr;
1387     for (auto t: delayedTimers_) {
1388         if (t == nullptr) {
1389             continue;
1390         }
1391         taskMessage = static_cast<TaskMessage *>(t->data);
1392         napi_value error = ErrorHelper::NewError(env_, 0, "taskpool:: task has been canceled");
1393         napi_reject_deferred(env_, taskMessage->deferred, error);
1394         uv_timer_stop(t);
1395         uv_close(reinterpret_cast<uv_handle_t*>(t), [](uv_handle_t* handle) {
1396             delete (uv_timer_t*)handle;
1397             handle = nullptr;
1398         });
1399         delete taskMessage;
1400         taskMessage = nullptr;
1401     }
1402     delayedTimers_.clear();
1403 }
1404 
VerifyAndPostResult(Priority priority)1405 bool Task::VerifyAndPostResult(Priority priority)
1406 {
1407 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1408     if (IsMainThreadTask()) {
1409         HITRACE_HELPER_METER_NAME("VerifyAndPostResult: PostTask");
1410         uint64_t taskId = taskId_;
1411         auto onResultTask = [taskId]() {
1412             Task* task = TaskManager::GetInstance().GetTask(taskId);
1413             if (task == nullptr) {
1414                 return;
1415             }
1416             TaskPool::HandleTaskResultCallback(task);
1417         };
1418         TaskManager::GetInstance().PostTask(onResultTask, "TaskPoolOnResultTask", priority);
1419         return true;
1420     } else {
1421         std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1422         if (!IsValid() || onResultSignal_ == nullptr || uv_is_closing((uv_handle_t*)onResultSignal_)) {
1423             return false;
1424         }
1425         uv_async_send(onResultSignal_);
1426         return true;
1427     }
1428 #else
1429     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1430     if (!IsValid() || onResultSignal_ == nullptr || uv_is_closing((uv_handle_t*)onResultSignal_)) {
1431         return false;
1432     }
1433     uv_async_send(onResultSignal_);
1434     return true;
1435 #endif
1436 }
1437 
IncreaseTaskRefCount()1438 void Task::IncreaseTaskRefCount()
1439 {
1440     refCount_++; // when tasks are created or executed, refCount_ will increment
1441 }
1442 
DecreaseTaskRefCount()1443 void Task::DecreaseTaskRefCount()
1444 {
1445     refCount_--; // when tasks finished, refCount_ will decrement
1446 }
1447 
ShouldDeleteTask(bool needUnref)1448 bool Task::ShouldDeleteTask(bool needUnref)
1449 {
1450     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1451     if (!IsValid()) {
1452         HILOG_WARN("taskpool:: task is invalid");
1453         TaskManager::GetInstance().RemoveTask(taskId_);
1454         return true;
1455     }
1456     if (needUnref) {
1457         DecreaseTaskRefCount();
1458     }
1459     return false;
1460 }
1461 
CheckStartExecution(Priority priority)1462 bool Task::CheckStartExecution(Priority priority)
1463 {
1464 #if defined(ENABLE_TASKPOOL_EVENTHANDLER)
1465     if (IsMainThreadTask()) {
1466         if (onStartExecutionCallBackInfo_ == nullptr) {
1467             return true;
1468         }
1469         HITRACE_HELPER_METER_NAME("PerformTask: PostTask");
1470         uint64_t taskId = taskId_;
1471         auto onStartExecutionTask = [taskId]() {
1472             Task* task = TaskManager::GetInstance().GetTask(taskId);
1473             if (task == nullptr || task->onStartExecutionCallBackInfo_ == nullptr) {
1474                 return;
1475             }
1476             Task::StartExecutionTask(task->onStartExecutionCallBackInfo_);
1477         };
1478         TaskManager::GetInstance().PostTask(onStartExecutionTask, "TaskPoolOnStartExecutionTask", priority);
1479     } else {
1480         if (onStartExecutionSignal_ == nullptr) {
1481             return true;
1482         }
1483         std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1484         if (!IsValid()) {
1485             return false;
1486         }
1487         if (onStartExecutionSignal_ != nullptr && !uv_is_closing((uv_handle_t*)onStartExecutionSignal_)) {
1488             uv_async_send(onStartExecutionSignal_);
1489         }
1490     }
1491     return true;
1492 #else
1493     if (onStartExecutionSignal_ == nullptr) {
1494         return true;
1495     }
1496     std::lock_guard<RECURSIVE_MUTEX> lock(taskMutex_);
1497     if (!IsValid()) {
1498         return false;
1499     }
1500     if (onStartExecutionSignal_ != nullptr && !uv_is_closing((uv_handle_t*)onStartExecutionSignal_)) {
1501         uv_async_send(onStartExecutionSignal_);
1502     }
1503     return true;
1504 #endif
1505 }
1506 
SetValid(bool isValid)1507 void Task::SetValid(bool isValid)
1508 {
1509     isValid_.store(isValid);
1510 }
1511 
IsValid()1512 bool Task::IsValid()
1513 {
1514     return isValid_.load();
1515 }
1516 } // namespace Commonlibrary::Concurrent::TaskPoolModule