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