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 "utils/log.h"
24
25 namespace Commonlibrary::Concurrent::TaskPoolModule {
26 using namespace Commonlibrary::Concurrent::Common::Helper;
27 static constexpr char EXECUTE_STR[] = "execute";
28 static constexpr char SEQ_RUNNER_ID_STR[] = "seqRunnerId";
29
SeqRunnerConstructor(napi_env env,napi_callback_info cbinfo)30 napi_value SequenceRunner::SeqRunnerConstructor(napi_env env, napi_callback_info cbinfo)
31 {
32 // get input args out of env and cbinfo
33 size_t argc = 1;
34 napi_value args[1];
35 napi_value thisVar;
36 napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
37
38 uint32_t priority = Priority::DEFAULT;
39 if (argc > 0) {
40 HILOG_DEBUG("seqRunner:: parse priority params.");
41 if (!NapiHelper::IsNumber(env, args[0])) {
42 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "seqRunner:: first param must be priority.");
43 return nullptr;
44 }
45 priority = NapiHelper::GetUint32Value(env, args[0]);
46 if (priority >= Priority::NUMBER) {
47 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "seqRunner:: priority value unvalied.");
48 return nullptr;
49 }
50 }
51 // update seqRunner.seqRunnerId
52 SequenceRunner* seqRunner = new SequenceRunner();
53 uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
54 napi_value napiSeqRunnerId = NapiHelper::CreateUint64(env, seqRunnerId);
55 TaskGroupManager::GetInstance().StoreSequenceRunner(seqRunnerId, seqRunner);
56 napi_value seqRunnerExecuteFunc;
57 napi_create_function(env, EXECUTE_STR, NAPI_AUTO_LENGTH, Execute, NULL, &seqRunnerExecuteFunc);
58 napi_property_descriptor properties[] = {
59 DECLARE_NAPI_PROPERTY(SEQ_RUNNER_ID_STR, napiSeqRunnerId),
60 DECLARE_NAPI_FUNCTION(EXECUTE_STR, Execute),
61 };
62 napi_define_properties(env, thisVar, sizeof(properties) / sizeof(properties[0]), properties);
63 HILOG_DEBUG("seqRunner:: construct seqRunner %" PRIu64 ".", seqRunnerId);
64
65 seqRunner->priority_ = Priority(priority);
66 seqRunner->seqRunnerId_ = seqRunnerId;
67 TaskGroupManager::GetInstance().StoreSequenceRunner(seqRunnerId, seqRunner);
68 napi_wrap(env, thisVar, seqRunner, SequnceRunnerDestructor, nullptr, nullptr);
69 napi_create_reference(env, thisVar, 0, &seqRunner->seqRunnerRef_);
70 return thisVar;
71 }
72
Execute(napi_env env,napi_callback_info cbinfo)73 napi_value SequenceRunner::Execute(napi_env env, napi_callback_info cbinfo)
74 {
75 size_t argc = 1;
76 napi_value args[1];
77 napi_value thisVar;
78 napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, nullptr);
79 std::string errMessage = "";
80 if (argc < 1) {
81 errMessage = "seqRunner:: number of params at least one";
82 HILOG_ERROR("%{public}s", errMessage.c_str());
83 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
84 return nullptr;
85 }
86 if (!NapiHelper::IsObject(env, args[0]) || !NapiHelper::HasNameProperty(env, args[0], TASKID_STR)) {
87 errMessage = "seqRunner:: first param must be task.";
88 HILOG_ERROR("%{public}s", errMessage.c_str());
89 ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, errMessage.c_str());
90 return nullptr;
91 }
92 napi_value napiSeqRunnerId = NapiHelper::GetNameProperty(env, thisVar, SEQ_RUNNER_ID_STR);
93 uint64_t seqRunnerId = NapiHelper::GetUint64Value(env, napiSeqRunnerId);
94 SequenceRunner* seqRunner = TaskGroupManager::GetInstance().GetSeqRunner(seqRunnerId);
95 if (seqRunner == nullptr) {
96 return nullptr;
97 }
98 napi_reference_ref(env, seqRunner->seqRunnerRef_, nullptr);
99 Task* task = nullptr;
100 napi_unwrap(env, args[0], reinterpret_cast<void**>(&task));
101 if (task == nullptr) {
102 HILOG_ERROR("taskpool:: SeqRunner execute task is nullptr");
103 return nullptr;
104 }
105 if (!task->CanForSequenceRunner(env)) {
106 return nullptr;
107 }
108 task->seqRunnerId_ = seqRunnerId;
109 task->taskState_ = ExecuteState::WAITING;
110 napi_value promise = task->GetTaskInfoPromise(env, args[0], TaskType::SEQRUNNER_TASK, seqRunner->priority_);
111 if (promise == nullptr) {
112 return nullptr;
113 }
114 if (seqRunner->currentTaskId_ == 0) {
115 HILOG_DEBUG("seqRunner:: task %" PRIu64 " in seqRunner %" PRIu64 " immediately.", task->taskId_, seqRunnerId);
116 seqRunner->currentTaskId_ = task->taskId_;
117 task->IncreaseRefCount();
118 ExecuteTaskImmediately(task->taskId_, seqRunner->priority_);
119 } else {
120 HILOG_DEBUG("seqRunner:: add %" PRIu64 " to seqRunner %" PRIu64 ".", task->taskId_, seqRunnerId);
121 TaskGroupManager::GetInstance().AddTaskToSeqRunner(seqRunnerId, task);
122 }
123 return promise;
124 }
125
ExecuteTaskImmediately(uint64_t taskId,Priority priority)126 void SequenceRunner::ExecuteTaskImmediately(uint64_t taskId, Priority priority)
127 {
128 TaskManager::GetInstance().EnqueueTaskId(taskId, priority);
129 TaskManager::GetInstance().TryTriggerExpand();
130 }
131
SequnceRunnerDestructor(napi_env env,void * data,void * hint)132 void SequenceRunner::SequnceRunnerDestructor(napi_env env, void* data, [[maybe_unused]] void* hint)
133 {
134 SequenceRunner* seqRunner = static_cast<SequenceRunner*>(data);
135 TaskGroupManager::GetInstance().RemoveSequenceRunner(seqRunner->seqRunnerId_);
136 delete seqRunner;
137 }
138 }
139