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