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#ifndef JS_CONCURRENT_MODULE_TASKPOOL_TASK_H 17#define JS_CONCURRENT_MODULE_TASKPOOL_TASK_H 18 19#include <list> 20#include <map> 21#include <mutex> 22#include <set> 23#include <shared_mutex> 24#include <string> 25#include <uv.h> 26 27#include "helper/concurrent_helper.h" 28#include "napi/native_api.h" 29#include "utils.h" 30#include "tools/log.h" 31#if defined(ENABLE_TASKPOOL_EVENTHANDLER) 32#include "event_handler.h" 33#endif 34 35#if defined(ENABLE_TASKPOOL_FFRT) 36#include "c/executor_task.h" 37#include "ffrt_inner.h" 38#endif 39 40namespace Commonlibrary::Concurrent::TaskPoolModule { 41using namespace Commonlibrary::Platform; 42 43enum ExecuteState { NOT_FOUND, WAITING, RUNNING, CANCELED, FINISHED, DELAYED, ENDING}; 44enum TaskType { TASK, FUNCTION_TASK, SEQRUNNER_TASK, COMMON_TASK, GROUP_COMMON_TASK, GROUP_FUNCTION_TASK }; 45 46struct GroupInfo; 47class Worker; 48struct TaskInfo { 49 napi_deferred deferred = nullptr; 50 Priority priority {Priority::DEFAULT}; 51 void* serializationFunction = nullptr; 52 void* serializationArguments = nullptr; 53}; 54 55#if defined(ENABLE_TASKPOOL_FFRT) 56#define RECURSIVE_MUTEX ffrt::recursive_mutex 57#define FFRT_MUTEX ffrt::mutex 58#define SHARED_MUTEX ffrt::shared_mutex 59#else 60#define RECURSIVE_MUTEX std::recursive_mutex 61#define FFRT_MUTEX std::mutex 62#define SHARED_MUTEX std::shared_mutex 63#endif 64 65struct ListenerCallBackInfo { 66 ListenerCallBackInfo(napi_env env, napi_ref callbackRef, napi_value taskError) : env_(env), 67 callbackRef_(callbackRef), taskError_(taskError) {} 68 ~ListenerCallBackInfo() 69 { 70 napi_delete_reference(env_, callbackRef_); 71 } 72 napi_env env_; 73 napi_ref callbackRef_; 74 napi_value taskError_; 75}; 76 77class Task { 78public: 79 Task(napi_env env, TaskType taskType, std::string name); 80 Task() = default; 81 ~Task() = default; 82 83 static napi_value TaskConstructor(napi_env env, napi_callback_info cbinfo); 84 static napi_value LongTaskConstructor(napi_env env, napi_callback_info cbinfo); 85 static napi_value SetTransferList(napi_env env, napi_callback_info cbinfo); 86 static napi_value SetCloneList(napi_env env, napi_callback_info cbinfo); 87 static napi_value IsCanceled(napi_env env, napi_callback_info cbinfo); 88 static napi_value OnReceiveData(napi_env env, napi_callback_info cbinfo); 89 static napi_value SendData(napi_env env, napi_callback_info cbinfo); 90 static napi_value AddDependency(napi_env env, napi_callback_info cbinfo); 91 static napi_value RemoveDependency(napi_env env, napi_callback_info cbinfo); 92 static napi_value OnEnqueued(napi_env env, napi_callback_info cbinfo); 93 static napi_value OnStartExecution(napi_env env, napi_callback_info cbinfo); 94 static napi_value OnExecutionFailed(napi_env env, napi_callback_info cbinfo); 95 static napi_value OnExecutionSucceeded(napi_env env, napi_callback_info cbinfo); 96 static napi_value IsDone(napi_env env, napi_callback_info cbinfo); 97 static napi_value GetTotalDuration(napi_env env, napi_callback_info info); 98 static napi_value GetCPUDuration(napi_env env, napi_callback_info info); 99 static napi_value GetIODuration(napi_env env, napi_callback_info info); 100 static napi_value GetTaskDuration(napi_env env, napi_callback_info& info, std::string durationType); 101 static napi_value GetName(napi_env env, [[maybe_unused]] napi_callback_info info); 102 103 static Task* GenerateTask(napi_env env, napi_value task, napi_value func, 104 napi_value name, napi_value* args, size_t argc); 105 static Task* GenerateFunctionTask(napi_env env, napi_value func, napi_value* args, size_t argc, TaskType type); 106 static TaskInfo* GenerateTaskInfo(napi_env env, napi_value func, napi_value args, 107 napi_value transferList, napi_value cloneList, Priority priority, 108 bool defaultTransfer = true, bool defaultCloneSendable = false); 109 static void TaskDestructor(napi_env env, void* data, void* hint); 110 111 static void ThrowNoDependencyError(napi_env env); 112 static void StartExecutionCallback(const uv_async_t* req); 113 static void StartExecutionTask(ListenerCallBackInfo* listenerCallBackInfo); 114 static void ExecuteListenerCallback(ListenerCallBackInfo* listenerCallBackInfo); 115 static void CleanupHookFunc(void* arg); 116 117 void StoreTaskId(uint64_t taskId); 118 napi_value GetTaskInfoPromise(napi_env env, napi_value task, TaskType taskType = TaskType::COMMON_TASK, 119 Priority priority = Priority::DEFAULT); 120 TaskInfo* GetTaskInfo(napi_env env, napi_value task, Priority priority); 121 void UpdateTaskType(TaskType taskType); 122 void UpdatePeriodicTask(); 123 bool IsRepeatableTask() const; 124 bool IsGroupTask() const; 125 bool IsGroupCommonTask() const; 126 bool IsGroupFunctionTask() const; 127 bool IsCommonTask() const; 128 bool IsSeqRunnerTask() const; 129 bool IsFunctionTask() const; 130 bool IsLongTask() const; 131 bool IsPeriodicTask() const; 132 bool IsMainThreadTask() const; 133 bool IsExecuted() const; 134 void IncreaseRefCount(); 135 void DecreaseRefCount(); 136 bool IsReadyToHandle() const; 137 void NotifyPendingTask(); 138 void CancelPendingTask(napi_env env); 139 bool UpdateTask(uint64_t startTime, void* worker); 140 napi_value DeserializeValue(napi_env env, napi_value* func, napi_value* args); 141 void StoreTaskDuration(); 142 bool CanForSequenceRunner(napi_env env); 143 bool CanForTaskGroup(napi_env env); 144 bool CanExecute(napi_env env); 145 bool CanExecuteDelayed(napi_env env); 146 bool CanExecutePeriodically(napi_env env); 147 void SetHasDependency(bool hasDependency); 148 bool HasDependency() const; 149 void TryClearHasDependency(); 150 void ClearDelayedTimers(); 151 void IncreaseTaskRefCount(); 152 void DecreaseTaskRefCount(); 153 bool ShouldDeleteTask(bool needUnref = true); 154 bool VerifyAndPostResult(Priority priority); 155 bool CheckStartExecution(Priority priority); 156 bool IsValid(); 157 void SetValid(bool isValid); 158 159private: 160 Task(const Task &) = delete; 161 Task& operator=(const Task &) = delete; 162 Task(Task &&) = delete; 163 Task& operator=(Task &&) = delete; 164 165 void InitHandle(napi_env env); 166 167public: 168 napi_env env_ = nullptr; 169 TaskType taskType_ {TaskType::TASK}; 170 std::string name_ {}; 171 uint64_t taskId_ {}; 172 std::atomic<ExecuteState> taskState_ {ExecuteState::NOT_FOUND}; 173 uint64_t groupId_ {}; // 0 for task outside taskgroup 174 uint64_t seqRunnerId_ {}; // 0 for task without seqRunner 175 TaskInfo* currentTaskInfo_ {}; 176 std::list<TaskInfo*> pendingTaskInfos_ {}; // for a common task executes multiple times 177 void* result_ = nullptr; 178 uv_async_t* onResultSignal_ = nullptr; 179 std::atomic<bool> success_ {true}; 180 std::atomic<uint64_t> startTime_ {}; 181 std::atomic<uint64_t> cpuTime_ {}; 182 std::atomic<uint64_t> ioTime_ {}; 183 void* worker_ {nullptr}; 184 napi_ref taskRef_ {}; 185 std::atomic<uint32_t> taskRefCount_ {}; 186 RECURSIVE_MUTEX taskMutex_ {}; 187 bool hasDependency_ {false}; 188 bool isLongTask_ {false}; 189 bool defaultTransfer_ {true}; 190 bool defaultCloneSendable_ {false}; 191 std::atomic<bool> isValid_ {true}; 192 std::atomic<uint32_t> refCount_ {false}; // when refCount_ is 0, the task pointer can be deleted 193 uv_async_t* onStartExecutionSignal_ = nullptr; 194 ListenerCallBackInfo* onEnqueuedCallBackInfo_ = nullptr; 195 ListenerCallBackInfo* onStartExecutionCallBackInfo_ = nullptr; 196 ListenerCallBackInfo* onExecutionFailedCallBackInfo_ = nullptr; 197 ListenerCallBackInfo* onExecutionSucceededCallBackInfo_ = nullptr; 198 199 // for periodic task 200 bool isPeriodicTask_ {false}; 201 // periodic task first Generate TaskInfo 202 std::atomic<bool> isFirstTaskInfo_ {false}; 203 uv_timer_t* timer_ {nullptr}; 204 Priority periodicTaskPriority_ {Priority::DEFAULT}; 205 206 std::set<uv_timer_t*> delayedTimers_ {}; // task delayed timer 207 208 bool isMainThreadTask_ {false}; 209}; 210 211struct CallbackInfo { 212 CallbackInfo(napi_env env, uint32_t count, napi_ref ref, Task* task) 213 : hostEnv(env), refCount(count), callbackRef(ref), task(task), onCallbackSignal(nullptr), worker(nullptr) {} 214 ~CallbackInfo() 215 { 216 napi_delete_reference(hostEnv, callbackRef); 217#if defined(ENABLE_TASKPOOL_EVENTHANDLER) 218 if (task == nullptr) { 219 return; 220 } 221 if (!task->IsMainThreadTask() && onCallbackSignal != nullptr) { 222 Common::Helper::ConcurrentHelper::UvHandleClose(onCallbackSignal); 223 } 224#else 225 if (onCallbackSignal != nullptr) { 226 Common::Helper::ConcurrentHelper::UvHandleClose(onCallbackSignal); 227 } 228#endif 229 } 230 231 napi_env hostEnv; 232 uint32_t refCount; 233 napi_ref callbackRef; 234 Task* task; 235 uv_async_t* onCallbackSignal; 236 Worker* worker; 237}; 238 239struct TaskResultInfo { 240 TaskResultInfo(napi_env env, napi_env curEnv, uint64_t id, void* args) : hostEnv(env), workerEnv(curEnv), 241 taskId(id), serializationArgs(args) {} 242 ~TaskResultInfo() = default; 243 244 napi_env hostEnv; 245 napi_env workerEnv; 246 uint64_t taskId; 247 void* serializationArgs; 248}; 249} // namespace Commonlibrary::Concurrent::TaskPoolModule 250#endif // JS_CONCURRENT_MODULE_TASKPOOL_TASK_H