14d6c458bSopenharmony_ci/* 24d6c458bSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License. 54d6c458bSopenharmony_ci * You may obtain a copy of the License at 64d6c458bSopenharmony_ci * 74d6c458bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84d6c458bSopenharmony_ci * 94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and 134d6c458bSopenharmony_ci * limitations under the License. 144d6c458bSopenharmony_ci */ 154d6c458bSopenharmony_ci#include "sequence_runner.h" 164d6c458bSopenharmony_ci 174d6c458bSopenharmony_ci#include <cinttypes> 184d6c458bSopenharmony_ci 194d6c458bSopenharmony_ci#include "helper/error_helper.h" 204d6c458bSopenharmony_ci#include "helper/napi_helper.h" 214d6c458bSopenharmony_ci#include "helper/object_helper.h" 224d6c458bSopenharmony_ci#include "task_manager.h" 234d6c458bSopenharmony_ci#include "tools/log.h" 244d6c458bSopenharmony_ci 254d6c458bSopenharmony_cinamespace Commonlibrary::Concurrent::TaskPoolModule { 264d6c458bSopenharmony_ciusing namespace Commonlibrary::Concurrent::Common::Helper; 274d6c458bSopenharmony_cistatic constexpr char EXECUTE_STR[] = "execute"; 284d6c458bSopenharmony_cistatic constexpr char SEQ_RUNNER_ID_STR[] = "seqRunnerId"; 294d6c458bSopenharmony_ci 304d6c458bSopenharmony_civoid SequenceRunner::SeqRunnerConstructorInner(napi_env env, napi_value &thisVar, SequenceRunner *seqRunner) 314d6c458bSopenharmony_ci{ 324d6c458bSopenharmony_ci // update seqRunner.seqRunnerId 334d6c458bSopenharmony_ci uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner); 344d6c458bSopenharmony_ci napi_value napiSeqRunnerId = NapiHelper::CreateUint64(env, seqRunnerId); 354d6c458bSopenharmony_ci TaskGroupManager::GetInstance().StoreSequenceRunner(seqRunnerId, seqRunner); 364d6c458bSopenharmony_ci napi_property_descriptor properties[] = { 374d6c458bSopenharmony_ci DECLARE_NAPI_PROPERTY(SEQ_RUNNER_ID_STR, napiSeqRunnerId), 384d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION(EXECUTE_STR, Execute), 394d6c458bSopenharmony_ci }; 404d6c458bSopenharmony_ci napi_define_properties(env, thisVar, sizeof(properties) / sizeof(properties[0]), properties); 414d6c458bSopenharmony_ci HILOG_INFO("taskpool:: construct seqRunner name is %{public}s, seqRunnerid %{public}s.", 424d6c458bSopenharmony_ci seqRunner->seqName_.c_str(), std::to_string(seqRunnerId).c_str()); 434d6c458bSopenharmony_ci 444d6c458bSopenharmony_ci seqRunner->seqRunnerId_ = seqRunnerId; 454d6c458bSopenharmony_ci napi_wrap(env, thisVar, seqRunner, SequenceRunnerDestructor, nullptr, nullptr); 464d6c458bSopenharmony_ci} 474d6c458bSopenharmony_ci 484d6c458bSopenharmony_cinapi_value SequenceRunner::SeqRunnerConstructor(napi_env env, napi_callback_info cbinfo) 494d6c458bSopenharmony_ci{ 504d6c458bSopenharmony_ci // get input args out of env and cbinfo 514d6c458bSopenharmony_ci size_t argc = 2; // 2: The maximum number of parameters is 2 524d6c458bSopenharmony_ci napi_value args[2]; // 2: The maximum number of parameters is 2 534d6c458bSopenharmony_ci napi_value thisVar; 544d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr); 554d6c458bSopenharmony_ci 564d6c458bSopenharmony_ci uint32_t priority = Priority::DEFAULT; 574d6c458bSopenharmony_ci std::string name = ""; 584d6c458bSopenharmony_ci if (argc == 2) { // 2: The number of parameters is 2, if the first is seqRunner name, the second must be priority 594d6c458bSopenharmony_ci if (NapiHelper::IsString(env, args[0]) && NapiHelper::IsNumber(env, args[1])) { 604d6c458bSopenharmony_ci name = NapiHelper::GetString(env, args[0]); 614d6c458bSopenharmony_ci priority = NapiHelper::GetUint32Value(env, args[1]); 624d6c458bSopenharmony_ci if (priority >= Priority::NUMBER) { 634d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied."); 644d6c458bSopenharmony_ci return nullptr; 654d6c458bSopenharmony_ci } 664d6c458bSopenharmony_ci } else { 674d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 684d6c458bSopenharmony_ci "the type of first param must be string and the type of second param must be string."); 694d6c458bSopenharmony_ci return nullptr; 704d6c458bSopenharmony_ci } 714d6c458bSopenharmony_ci } else if (argc == 1) { 724d6c458bSopenharmony_ci if (NapiHelper::IsString(env, args[0])) { 734d6c458bSopenharmony_ci name = NapiHelper::GetString(env, args[0]); 744d6c458bSopenharmony_ci } else if (NapiHelper::IsNumber(env, args[0])) { 754d6c458bSopenharmony_ci priority = NapiHelper::GetUint32Value(env, args[0]); 764d6c458bSopenharmony_ci if (priority >= Priority::NUMBER) { 774d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "priority value unvalied."); 784d6c458bSopenharmony_ci return nullptr; 794d6c458bSopenharmony_ci } 804d6c458bSopenharmony_ci } else { 814d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of first param must be string or number."); 824d6c458bSopenharmony_ci return nullptr; 834d6c458bSopenharmony_ci } 844d6c458bSopenharmony_ci } 854d6c458bSopenharmony_ci 864d6c458bSopenharmony_ci SequenceRunner* seqRunner = nullptr; 874d6c458bSopenharmony_ci if (name != "") { 884d6c458bSopenharmony_ci seqRunner = SequenceRunnerManager::GetInstance().CreateOrGetGlobalRunner(env, thisVar, argc, name, priority); 894d6c458bSopenharmony_ci if (seqRunner == nullptr) { 904d6c458bSopenharmony_ci HILOG_ERROR("taskpool:: create or get globalRunner failed"); 914d6c458bSopenharmony_ci return nullptr; 924d6c458bSopenharmony_ci } 934d6c458bSopenharmony_ci } else { 944d6c458bSopenharmony_ci seqRunner = new SequenceRunner(); 954d6c458bSopenharmony_ci seqRunner->priority_ = static_cast<Priority>(priority); 964d6c458bSopenharmony_ci napi_create_reference(env, thisVar, 0, &seqRunner->seqRunnerRef_); 974d6c458bSopenharmony_ci } 984d6c458bSopenharmony_ci 994d6c458bSopenharmony_ci SeqRunnerConstructorInner(env, thisVar, seqRunner); 1004d6c458bSopenharmony_ci return thisVar; 1014d6c458bSopenharmony_ci} 1024d6c458bSopenharmony_ci 1034d6c458bSopenharmony_cinapi_value SequenceRunner::Execute(napi_env env, napi_callback_info cbinfo) 1044d6c458bSopenharmony_ci{ 1054d6c458bSopenharmony_ci size_t argc = 1; 1064d6c458bSopenharmony_ci napi_value args[1]; 1074d6c458bSopenharmony_ci napi_value thisVar; 1084d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr); 1094d6c458bSopenharmony_ci std::string errMessage = ""; 1104d6c458bSopenharmony_ci if (argc < 1) { 1114d6c458bSopenharmony_ci errMessage = "seqRunner:: number of params at least one"; 1124d6c458bSopenharmony_ci HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str()); 1134d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of param at least one."); 1144d6c458bSopenharmony_ci return nullptr; 1154d6c458bSopenharmony_ci } 1164d6c458bSopenharmony_ci if (!NapiHelper::IsObject(env, args[0]) || !NapiHelper::HasNameProperty(env, args[0], TASKID_STR)) { 1174d6c458bSopenharmony_ci errMessage = "seqRunner:: first param must be task."; 1184d6c458bSopenharmony_ci HILOG_ERROR("taskpool:: %{public}s", errMessage.c_str()); 1194d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of the first param must be task."); 1204d6c458bSopenharmony_ci return nullptr; 1214d6c458bSopenharmony_ci } 1224d6c458bSopenharmony_ci napi_value napiSeqRunnerId = NapiHelper::GetNameProperty(env, thisVar, SEQ_RUNNER_ID_STR); 1234d6c458bSopenharmony_ci uint64_t seqRunnerId = NapiHelper::GetUint64Value(env, napiSeqRunnerId); 1244d6c458bSopenharmony_ci SequenceRunner* seqRunner = TaskGroupManager::GetInstance().GetSeqRunner(seqRunnerId); 1254d6c458bSopenharmony_ci if (seqRunner == nullptr) { 1264d6c458bSopenharmony_ci return nullptr; 1274d6c458bSopenharmony_ci } 1284d6c458bSopenharmony_ci Task* task = nullptr; 1294d6c458bSopenharmony_ci napi_unwrap(env, args[0], reinterpret_cast<void**>(&task)); 1304d6c458bSopenharmony_ci if (task == nullptr) { 1314d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of param must be task."); 1324d6c458bSopenharmony_ci return nullptr; 1334d6c458bSopenharmony_ci } 1344d6c458bSopenharmony_ci if (!task->CanForSequenceRunner(env)) { 1354d6c458bSopenharmony_ci return nullptr; 1364d6c458bSopenharmony_ci } 1374d6c458bSopenharmony_ci task->seqRunnerId_ = seqRunnerId; 1384d6c458bSopenharmony_ci napi_value promise = task->GetTaskInfoPromise(env, args[0], TaskType::SEQRUNNER_TASK, seqRunner->priority_); 1394d6c458bSopenharmony_ci if (promise == nullptr) { 1404d6c458bSopenharmony_ci return nullptr; 1414d6c458bSopenharmony_ci } 1424d6c458bSopenharmony_ci napi_reference_ref(env, seqRunner->seqRunnerRef_, nullptr); 1434d6c458bSopenharmony_ci if (seqRunner->currentTaskId_ == 0) { 1444d6c458bSopenharmony_ci HILOG_INFO("taskpool:: taskId %{public}s in seqRunner %{public}s immediately.", 1454d6c458bSopenharmony_ci std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str()); 1464d6c458bSopenharmony_ci seqRunner->currentTaskId_ = task->taskId_; 1474d6c458bSopenharmony_ci task->IncreaseRefCount(); 1484d6c458bSopenharmony_ci task->taskState_ = ExecuteState::WAITING; 1494d6c458bSopenharmony_ci ExecuteTaskImmediately(task->taskId_, seqRunner->priority_); 1504d6c458bSopenharmony_ci } else { 1514d6c458bSopenharmony_ci HILOG_INFO("taskpool:: add taskId: %{public}s to seqRunner %{public}s.", 1524d6c458bSopenharmony_ci std::to_string(task->taskId_).c_str(), std::to_string(seqRunnerId).c_str()); 1534d6c458bSopenharmony_ci TaskGroupManager::GetInstance().AddTaskToSeqRunner(seqRunnerId, task); 1544d6c458bSopenharmony_ci } 1554d6c458bSopenharmony_ci return promise; 1564d6c458bSopenharmony_ci} 1574d6c458bSopenharmony_ci 1584d6c458bSopenharmony_civoid SequenceRunner::ExecuteTaskImmediately(uint64_t taskId, Priority priority) 1594d6c458bSopenharmony_ci{ 1604d6c458bSopenharmony_ci TaskManager::GetInstance().EnqueueTaskId(taskId, priority); 1614d6c458bSopenharmony_ci} 1624d6c458bSopenharmony_ci 1634d6c458bSopenharmony_civoid SequenceRunner::SequenceRunnerDestructor(napi_env env, void* data, [[maybe_unused]] void* hint) 1644d6c458bSopenharmony_ci{ 1654d6c458bSopenharmony_ci SequenceRunner* seqRunner = static_cast<SequenceRunner*>(data); 1664d6c458bSopenharmony_ci if (seqRunner->isGlobalRunner_) { 1674d6c458bSopenharmony_ci SequenceRunnerManager::GetInstance().GlobalSequenceRunnerDestructor(env, seqRunner); 1684d6c458bSopenharmony_ci } else { 1694d6c458bSopenharmony_ci TaskGroupManager::GetInstance().RemoveSequenceRunner(seqRunner->seqRunnerId_); 1704d6c458bSopenharmony_ci napi_delete_reference(env, seqRunner->seqRunnerRef_); 1714d6c458bSopenharmony_ci delete seqRunner; 1724d6c458bSopenharmony_ci } 1734d6c458bSopenharmony_ci} 1744d6c458bSopenharmony_ci} // namespace Commonlibrary::Concurrent::TaskPoolModule