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#include "sequence_runner.h" 16 17#include <cinttypes> 18 19#include "helper/error_helper.h" 20#include "helper/napi_helper.h" 21#include "helper/object_helper.h" 22#include "task_manager.h" 23#include "tools/log.h" 24 25namespace Commonlibrary::Concurrent::TaskPoolModule { 26using namespace Commonlibrary::Concurrent::Common::Helper; 27static constexpr char EXECUTE_STR[] = "execute"; 28static constexpr char SEQ_RUNNER_ID_STR[] = "seqRunnerId"; 29 30void SequenceRunner::SeqRunnerConstructorInner(napi_env env, napi_value &thisVar, SequenceRunner *seqRunner) 31{ 32 // update seqRunner.seqRunnerId 33 uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner); 34 napi_value napiSeqRunnerId = NapiHelper::CreateUint64(env, seqRunnerId); 35 TaskGroupManager::GetInstance().StoreSequenceRunner(seqRunnerId, seqRunner); 36 napi_property_descriptor properties[] = { 37 DECLARE_NAPI_PROPERTY(SEQ_RUNNER_ID_STR, napiSeqRunnerId), 38 DECLARE_NAPI_FUNCTION(EXECUTE_STR, Execute), 39 }; 40 napi_define_properties(env, thisVar, sizeof(properties) / sizeof(properties[0]), properties); 41 HILOG_INFO("taskpool:: construct seqRunner name is %{public}s, seqRunnerid %{public}s.", 42 seqRunner->seqName_.c_str(), std::to_string(seqRunnerId).c_str()); 43 44 seqRunner->seqRunnerId_ = seqRunnerId; 45 napi_wrap(env, thisVar, seqRunner, SequenceRunnerDestructor, nullptr, nullptr); 46} 47 48napi_value SequenceRunner::SeqRunnerConstructor(napi_env env, napi_callback_info cbinfo) 49{ 50 // get input args out of env and cbinfo 51 size_t argc = 2; // 2: The maximum number of parameters is 2 52 napi_value args[2]; // 2: The maximum number of parameters is 2 53 napi_value thisVar; 54 napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr); 55 56 uint32_t priority = Priority::DEFAULT; 57 std::string name = ""; 58 if (argc == 2) { // 2: The number of parameters is 2, if the first is seqRunner name, the second must be priority 59 if (NapiHelper::IsString(env, args[0]) && NapiHelper::IsNumber(env, args[1])) { 60 name = NapiHelper::GetString(env, args[0]); 61 priority = NapiHelper::GetUint32Value(env, args[1]); 62 if (priority >= Priority::NUMBER) { 63 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied."); 64 return nullptr; 65 } 66 } else { 67 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 68 "the type of first param must be string and the type of second param must be string."); 69 return nullptr; 70 } 71 } else if (argc == 1) { 72 if (NapiHelper::IsString(env, args[0])) { 73 name = NapiHelper::GetString(env, args[0]); 74 } else if (NapiHelper::IsNumber(env, args[0])) { 75 priority = NapiHelper::GetUint32Value(env, args[0]); 76 if (priority >= Priority::NUMBER) { 77 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied."); 78 return nullptr; 79 } 80 } else { 81 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of first param must be string or number."); 82 return nullptr; 83 } 84 } 85 86 SequenceRunner* seqRunner = nullptr; 87 if (name != "") { 88 seqRunner = SequenceRunnerManager::GetInstance().CreateOrGetGlobalRunner(env, thisVar, argc, name, priority); 89 if (seqRunner == nullptr) { 90 HILOG_ERROR("taskpool:: create or get globalRunner failed"); 91 return nullptr; 92 } 93 } else { 94 seqRunner = new SequenceRunner(); 95 seqRunner->priority_ = static_cast<Priority>(priority); 96 napi_create_reference(env, thisVar, 0, &seqRunner->seqRunnerRef_); 97 } 98 99 SeqRunnerConstructorInner(env, thisVar, seqRunner); 100 return thisVar; 101} 102 103napi_value SequenceRunner::Execute(napi_env env, napi_callback_info cbinfo) 104{ 105 size_t argc = 1; 106 napi_value args[1]; 107 napi_value thisVar; 108 napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr); 109 std::string errMessage = ""; 110 if (argc < 1) { 111 errMessage = "seqRunner:: number of params at least one"; 112 HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str()); 113 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of param at least one."); 114 return nullptr; 115 } 116 if (!NapiHelper::IsObject(env, args[0]) || !NapiHelper::HasNameProperty(env, args[0], TASKID_STR)) { 117 errMessage = "seqRunner:: first param must be task."; 118 HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str()); 119 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be task."); 120 return nullptr; 121 } 122 napi_value napiSeqRunnerId = NapiHelper::GetNameProperty(env, thisVar, SEQ_RUNNER_ID_STR); 123 uint64_t seqRunnerId = NapiHelper::GetUint64Value(env, napiSeqRunnerId); 124 SequenceRunner* seqRunner = TaskGroupManager::GetInstance().GetSeqRunner(seqRunnerId); 125 if (seqRunner == nullptr) { 126 return nullptr; 127 } 128 Task* task = nullptr; 129 napi_unwrap(env, args[0], reinterpret_cast<void**>(&task)); 130 if (task == nullptr) { 131 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of param must be task."); 132 return nullptr; 133 } 134 if (!task->CanForSequenceRunner(env)) { 135 return nullptr; 136 } 137 task->seqRunnerId_ = seqRunnerId; 138 napi_value promise = task->GetTaskInfoPromise(env, args[0], TaskType::SEQRUNNER_TASK, seqRunner->priority_); 139 if (promise == nullptr) { 140 return nullptr; 141 } 142 napi_reference_ref(env, seqRunner->seqRunnerRef_, nullptr); 143 if (seqRunner->currentTaskId_ == 0) { 144 HILOG_INFO("taskpool:: taskId %{public}s in seqRunner %{public}s immediately.", 145 std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str()); 146 seqRunner->currentTaskId_ = task->taskId_; 147 task->IncreaseRefCount(); 148 task->taskState_ = ExecuteState::WAITING; 149 ExecuteTaskImmediately(task->taskId_, seqRunner->priority_); 150 } else { 151 HILOG_INFO("taskpool:: add taskId: %{public}s to seqRunner %{public}s.", 152 std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str()); 153 TaskGroupManager::GetInstance().AddTaskToSeqRunner(seqRunnerId, task); 154 } 155 return promise; 156} 157 158void SequenceRunner::ExecuteTaskImmediately(uint64_t taskId, Priority priority) 159{ 160 TaskManager::GetInstance().EnqueueTaskId(taskId, priority); 161} 162 163void SequenceRunner::SequenceRunnerDestructor(napi_env env, void* data, [[maybe_unused]] void* hint) 164{ 165 SequenceRunner* seqRunner = static_cast<SequenceRunner*>(data); 166 if (seqRunner->isGlobalRunner_) { 167 SequenceRunnerManager::GetInstance().GlobalSequenceRunnerDestructor(env, seqRunner); 168 } else { 169 TaskGroupManager::GetInstance().RemoveSequenceRunner(seqRunner->seqRunnerId_); 170 napi_delete_reference(env, seqRunner->seqRunnerRef_); 171 delete seqRunner; 172 } 173} 174} // namespace Commonlibrary::Concurrent::TaskPoolModule