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