• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 // [Start napi_call_threadsafe_function_with_priority_cpp]
16 // [Start napi_ark_runtime_cpp]
17 #include <pthread.h>
18 #include "napi/native_api.h"
19 // [StartExclute napi_ark_runtime_cpp]
20 #include <napi/common.h>
21 #include <pthread.h>
22 #include <future>
23 
24 static constexpr int INT_ARG_2 = 2; // 入参索引
25 static constexpr int INT_ARG_12 = 12; // 入参索引
26 static constexpr int INT_ARG_15 = 15; // 入参索引
27 // [EndExclute napi_ark_runtime_cpp]
28 // [StartExclute napi_call_threadsafe_function_with_priority_cpp]
CreateArkRuntimeFunc(void * arg)29 static void *CreateArkRuntimeFunc(void *arg)
30 {
31     // 1. 创建基础运行环境
32     napi_env env;
33     napi_status ret = napi_create_ark_runtime(&env);
34     if (ret != napi_ok) {
35         return nullptr;
36     }
37 
38     // 2. 加载自定义模块
39     napi_value objUtils;
40     ret = napi_load_module_with_info(env, "entry/src/main/ets/pages/ObjectUtils", "com.example.myapplication/entry",
41                                      &objUtils);
42     if (ret != napi_ok) {
43         return nullptr;
44     }
45 
46     // 3. 使用ArkTS中的logger
47     napi_value logger;
48     ret = napi_get_named_property(env, objUtils, "Logger", &logger);
49     if (ret != napi_ok) {
50         return nullptr;
51     }
52     ret = napi_call_function(env, objUtils, logger, 0, nullptr, nullptr);
53 
54     // 4. 销毁ArkTS环境
55     ret = napi_destroy_ark_runtime(&env);
56 
57     return nullptr;
58 }
59 
CreateArkRuntime(napi_env env,napi_callback_info info)60 static napi_value CreateArkRuntime(napi_env env, napi_callback_info info)
61 {
62     pthread_t tid;
63     pthread_create(&tid, nullptr, CreateArkRuntimeFunc, nullptr);
64     pthread_join(tid, nullptr);
65     return nullptr;
66 }
67 // [StartExclute napi_ark_runtime_cpp]
68 // [Start napi_event_loop_cpp]
ResolvedCallback(napi_env env,napi_callback_info info)69 static napi_value ResolvedCallback(napi_env env, napi_callback_info info)
70 {
71     napi_stop_event_loop(env);
72     return nullptr;
73 }
74 
RejectedCallback(napi_env env,napi_callback_info info)75 static napi_value RejectedCallback(napi_env env, napi_callback_info info)
76 {
77     napi_stop_event_loop(env);
78     return nullptr;
79 }
80 
RunEventLoopFunc(void * arg)81 static void *RunEventLoopFunc(void *arg)
82 {
83     // 1. 创建ArkTS实例
84     napi_env env;
85     napi_status ret = napi_create_ark_runtime(&env);
86     if (ret != napi_ok) {
87         return nullptr;
88     }
89 
90     // 2. 加载自定义的模块
91     napi_value objectUtils;
92     // 'com.example.myapplication' 为当前应用的bundleName
93     ret = napi_load_module_with_info(env, "ets/pages/ObjectUtils", "com.example.myapplication/entry", &objectUtils);
94     if (ret != napi_ok) {
95         return nullptr;
96     }
97 
98     // 3. 调用异步SetTimeout接口
99     napi_value setTimeout = nullptr;
100     napi_value promise = nullptr;
101 
102     napi_get_named_property(env, objectUtils, "SetTimeout", &setTimeout);
103     napi_call_function(env, objectUtils, setTimeout, 0, nullptr, &promise);
104 
105     napi_value theFunc = nullptr;
106     if (napi_get_named_property(env, promise, "then", &theFunc) != napi_ok) {
107         return nullptr;
108     }
109 
110     napi_value resolvedCallback = nullptr;
111     napi_value rejectedCallback = nullptr;
112     napi_create_function(env, "resolvedCallback", NAPI_AUTO_LENGTH, ResolvedCallback, nullptr, &resolvedCallback);
113     napi_create_function(env, "rejectedCallback", NAPI_AUTO_LENGTH, RejectedCallback, nullptr, &rejectedCallback);
114     napi_value argv[2] = {resolvedCallback, rejectedCallback};
115     napi_call_function(env, promise, theFunc, INT_ARG_2, argv, nullptr);
116 
117     auto flag = reinterpret_cast<bool *>(arg);
118     if (*flag == true) {
119         napi_run_event_loop(env, napi_event_mode_default);
120     } else {
121         // 非阻塞式的处理任务,有可能队列中还没有任务就已经返回了
122         napi_run_event_loop(env, napi_event_mode_nowait);
123     }
124     return nullptr;
125 }
126 
RunEventLoop(napi_env env,napi_callback_info info)127 static napi_value RunEventLoop(napi_env env, napi_callback_info info)
128 {
129     pthread_t tid;
130     size_t argc = 1;
131     napi_value argv[1] = {nullptr};
132     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
133 
134     bool flag = false;
135     napi_get_value_bool(env, argv[0], &flag);
136     // 创建异步线程
137     pthread_create(&tid, nullptr, RunEventLoopFunc, &flag);
138     pthread_join(tid, nullptr);
139 
140     return nullptr;
141 }
142 // [StartExclute napi_event_loop_cpp]
143 // [EndExclute napi_call_threadsafe_function_with_priority_cpp]
144 struct CallbackData {
145     napi_threadsafe_function tsfn;
146     napi_async_work work;
147 };
148 // ArkTS线程的回调实现
CallJs(napi_env env,napi_value jsCb,void * context,void * data)149 static void CallJs(napi_env env, napi_value jsCb, void *context, void *data)
150 {
151     if (env == nullptr) {
152         return;
153     }
154     napi_value resultNumber = nullptr;
155     napi_value undefined = nullptr;
156     napi_get_undefined(env, &undefined);
157     napi_value number1 = nullptr;
158     napi_create_int32(env, INT_ARG_12, &number1);
159     napi_value number2 = nullptr;
160     napi_create_int32(env, INT_ARG_15, &number2);
161     napi_value argv[2] = {number1, number2};
162     napi_call_function(env, undefined, jsCb, INT_ARG_2, argv, &resultNumber);
163     int32_t res = 0;
164     napi_get_value_int32(env, resultNumber, &res);
165 }
166 
167 // 异步线程中调用该接口向ArkTS线程投递指定优先级和入队方式的任务
ExecuteWork(napi_env env,void * data)168 static void ExecuteWork(napi_env env, void *data)
169 {
170     CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
171     // 执行任务为napi_priority_idle优先级,入队方式为队列尾部入队
172     napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_idle, true);
173     napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_low, true);
174     napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_high, true);
175     napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate, true);
176     // 执行任务为napi_priority_high优先级,入队方式为队列头部入队
177     napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_high, false);
178 }
179 
WorkComplete(napi_env env,napi_status status,void * data)180 static void WorkComplete(napi_env env, napi_status status, void *data)
181 {
182     CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
183     napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
184     napi_delete_async_work(env, callbackData->work);
185     callbackData->work = nullptr;
186     callbackData->tsfn = nullptr;
187 }
188 
CallThreadSafeWithPriority(napi_env env,napi_callback_info info)189 static napi_value CallThreadSafeWithPriority(napi_env env, napi_callback_info info)
190 {
191     size_t argc = 1;
192     napi_value jsCb = nullptr;
193     CallbackData *callbackData = nullptr;
194     napi_get_cb_info(env, info, &argc, &jsCb, nullptr, reinterpret_cast<void **>(&callbackData));
195     napi_value resourceName = nullptr;
196     napi_create_string_utf8(env, "Thread-safe Function Demo", NAPI_AUTO_LENGTH, &resourceName);
197     napi_create_threadsafe_function(env, jsCb, nullptr, resourceName, 0, 1, callbackData, nullptr, callbackData, CallJs,
198                                     &callbackData->tsfn);
199     napi_create_async_work(env, nullptr, resourceName, ExecuteWork, WorkComplete, callbackData, &callbackData->work);
200     napi_queue_async_work(env, callbackData->work);
201     return nullptr;
202 }
203 // [EndExclute napi_event_loop_cpp]
204 // [EndExclute napi_ark_runtime_cpp]
205 EXTERN_C_START
Init(napi_env env,napi_value exports)206 static napi_value Init(napi_env env, napi_value exports)
207 {
208     CallbackData *callbackData = new CallbackData();
209     napi_property_descriptor desc[] = {
210         {"createArkRuntime", nullptr, CreateArkRuntime, nullptr, nullptr, nullptr, napi_static, nullptr},
211         {"runEventLoop", nullptr, RunEventLoop, nullptr, nullptr, nullptr, napi_default, nullptr},
212         {"callThreadSafeWithPriority", nullptr, CallThreadSafeWithPriority, nullptr, nullptr, nullptr,
213             napi_default, callbackData}};
214     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
215     return exports;
216 }
217 EXTERN_C_END
218 
219 static napi_module nativeModule = {
220     .nm_version = 1,
221     .nm_flags = 0,
222     .nm_filename = nullptr,
223     .nm_register_func = Init,
224     .nm_modname = "entry",
225     .nm_priv = nullptr,
226     .reserved = {0},
227 };
228 
RegisterQueueWorkModule()229 extern "C" __attribute__((constructor)) void RegisterQueueWorkModule() { napi_module_register(&nativeModule); }
230 // [End napi_call_threadsafe_function_with_priority_cpp]
231 // [End napi_event_loop_cpp]
232 // [End napi_ark_runtime_cpp]
233