1e41f4b71Sopenharmony_ci# libuv 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Introduction 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci[libuv](http://libuv.org/) is a cross-platform library that implements asynchronous I/O based on event loops. It applies to network programming and file system operations. It is one of the core libraries of Node.js and has been widely used by other software projects. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci## Supported Capabilities 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci- Event-driven asynchronous I/O across platforms. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci- Support for standard library interfaces. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci## Available APIs 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ciFor details, see [API documentation](http://docs.libuv.org/en/v1.x/api.html). 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci## Background of Introducing libuv to OpenHarmony 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ciOpenHarmony introduced Node-API of Node.js in its earlier versions to facilitate Node.js developers to extend their JavaScript APIs with OpenHarmony. It also introduced libuv of Node.js to implement event loops. 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci### Evolution Trend 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ciTo address the scheduling issues caused when the application main thread has an event loop that contains **uvloop**, we plan to normalize the event loops in the application model to allow only one task queue in the application main loop with task priorities controlled. 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ciAvoid using the NDK of libuv to perform operations on the application main loop obtained by **napi_get_uv_event_loop** (deprecated in API version 12). This may cause various problems and large amount of workload to address compatibility issues. 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ciIf you want to implement interaction with the main thread cyclically, for example, inserting a task, use [APIs provided by Node-API](../../napi/napi-data-types-interfaces.md). 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ciOpenHarmony will continue to provide capabilities of interacting with the main thread and extending JS APIs through Node-API for a long period of time, but shields the event loops used in the implementation layer. Although **napi_get_uv_event_loop** is deprecated in API version 12, the main functional APIs of Node-API will be maintained for a long time and provide the same native behavior of Node-API, so that the developers who are familiar with the node.js extension mechanism can easily expand their code to OpenHarmony. 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ciIf you are familiar with libuv and can handle memory management and multithreading problems, you can use libuv to develop your services on OpenHarmony. Unless otherwise required, you do not need to import the libuv library to your application project. 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci### Current Problems and Solutions 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ciAccording to the existing mechanism, only one event loop can exist in a thread. To ensure proper running of the main event loop of the system application, the main event loop listens for the FD events in the JS environment and executes `uv_run` only when an FD event is reported. As a result, certain functions that depend on **uvloop** cannot take effect. 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ciCommon scenarios and solutions are as follows: 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci#### Scenario 1: The JS main thread throws an async task to a worker thread for execution, and executes the result returned by the JS code. 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci**Example (incorrect)** 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ciCall **napi_get_uv_event_loop()** to obtain the system loop, and use libuv NDK APIs to implement related functions. 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci```cpp 47e41f4b71Sopenharmony_ci#include "napi/native_api.h" 48e41f4b71Sopenharmony_ci#include "uv.h" 49e41f4b71Sopenharmony_ci#define LOG_DOMAIN 0X0202 50e41f4b71Sopenharmony_ci#define LOG_TAG "MyTag" 51e41f4b71Sopenharmony_ci#include <hilog/log.h> 52e41f4b71Sopenharmony_ci#include <thread> 53e41f4b71Sopenharmony_ci#include <sys/eventfd.h> 54e41f4b71Sopenharmony_ci#include <unistd.h> 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_cistatic void execute(uv_work_t *work) { 57e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos in execute"); 58e41f4b71Sopenharmony_ci} 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_cistatic void complete(uv_work_t *work, int status) { 61e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos in complete"); 62e41f4b71Sopenharmony_ci delete work; 63e41f4b71Sopenharmony_ci} 64e41f4b71Sopenharmony_cistatic napi_value Add(napi_env env, napi_callback_info info) 65e41f4b71Sopenharmony_ci{ 66e41f4b71Sopenharmony_ci napi_value work_name; 67e41f4b71Sopenharmony_ci uv_loop_s *loop = nullptr; 68e41f4b71Sopenharmony_ci /* Obtain the uv_loop of the application JS main thread. */ 69e41f4b71Sopenharmony_ci napi_get_uv_event_loop(env, &loop); 70e41f4b71Sopenharmony_ci uv_work_t *work = new uv_work_t; 71e41f4b71Sopenharmony_ci int ret = uv_queue_work(loop, work, execute, complete); 72e41f4b71Sopenharmony_ci if (ret != 0) { 73e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "delete work"); 74e41f4b71Sopenharmony_ci delete work; 75e41f4b71Sopenharmony_ci } 76e41f4b71Sopenharmony_ci return 0; 77e41f4b71Sopenharmony_ci} 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ciEXTERN_C_START 80e41f4b71Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports){ 81e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}}; 82e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 83e41f4b71Sopenharmony_ci return exports; 84e41f4b71Sopenharmony_ciEXTERN_C_END 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_cistatic napi_module demoModule = { 87e41f4b71Sopenharmony_ci .nm_version = 1, 88e41f4b71Sopenharmony_ci .nm_flags = 0, 89e41f4b71Sopenharmony_ci .nm_filename = nullptr, 90e41f4b71Sopenharmony_ci .nm_register_func = Init, 91e41f4b71Sopenharmony_ci .nm_modname = "entry", 92e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 93e41f4b71Sopenharmony_ci .reserved = {0}, 94e41f4b71Sopenharmony_ci}; 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterEntryModule(void){ 97e41f4b71Sopenharmony_ci napi_module_register(&demoModule); 98e41f4b71Sopenharmony_ci} 99e41f4b71Sopenharmony_ci``` 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci**Example (correct)**: 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ciUse **napi_create_async_work** and **napi_queue_async_work** together. 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci```cpp 106e41f4b71Sopenharmony_ci#include "napi/native_api.h" 107e41f4b71Sopenharmony_ci#include "uv.h" 108e41f4b71Sopenharmony_ci#define LOG_DOMAIN 0X0202 109e41f4b71Sopenharmony_ci#define LOG_TAG "MyTag" 110e41f4b71Sopenharmony_ci#include <hilog/log.h> 111e41f4b71Sopenharmony_ci#include <thread> 112e41f4b71Sopenharmony_ci#include <sys/eventfd.h> 113e41f4b71Sopenharmony_ci#include <unistd.h> 114e41f4b71Sopenharmony_ciuv_loop_t *loop; 115e41f4b71Sopenharmony_cinapi_value jsCb; 116e41f4b71Sopenharmony_ciint fd = -1; 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_cistatic napi_value Add(napi_env env, napi_callback_info info) 119e41f4b71Sopenharmony_ci{ 120e41f4b71Sopenharmony_ci napi_value work_name; 121e41f4b71Sopenharmony_ci napi_async_work work; 122e41f4b71Sopenharmony_ci napi_create_string_utf8(env, "ohos", NAPI_AUTO_LENGTH, &work_name); 123e41f4b71Sopenharmony_ci /* The fourth parameter specifies the work task of the asynchronous thread, and the fifth parameter is the callback of the main thread. */ 124e41f4b71Sopenharmony_ci napi_create_async_work(env, nullptr, work_name, [](napi_env env, void* data){ 125e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos in execute"); 126e41f4b71Sopenharmony_ci }, [](napi_env env, napi_status status, void *data){ 127e41f4b71Sopenharmony_ci /* The specific implementation is skipped. */ 128e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos in complete"); 129e41f4b71Sopenharmony_ci napi_delete_async_work(env, (napi_async_work)data); 130e41f4b71Sopenharmony_ci }, nullptr, &work); 131e41f4b71Sopenharmony_ci /* Call napi_queue_async_work to trigger an async task. */ 132e41f4b71Sopenharmony_ci napi_queue_async_work(env, work); 133e41f4b71Sopenharmony_ci return 0; 134e41f4b71Sopenharmony_ci} 135e41f4b71Sopenharmony_ci 136e41f4b71Sopenharmony_ciEXTERN_C_START 137e41f4b71Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports){ 138e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}}; 139e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 140e41f4b71Sopenharmony_ci return exports; 141e41f4b71Sopenharmony_ciEXTERN_C_END 142e41f4b71Sopenharmony_ci 143e41f4b71Sopenharmony_cistatic napi_module demoModule = { 144e41f4b71Sopenharmony_ci .nm_version = 1, 145e41f4b71Sopenharmony_ci .nm_flags = 0, 146e41f4b71Sopenharmony_ci .nm_filename = nullptr, 147e41f4b71Sopenharmony_ci .nm_register_func = Init, 148e41f4b71Sopenharmony_ci .nm_modname = "entry", 149e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 150e41f4b71Sopenharmony_ci .reserved = {0}, 151e41f4b71Sopenharmony_ci}; 152e41f4b71Sopenharmony_ci 153e41f4b71Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterEntryModule(void){ 154e41f4b71Sopenharmony_ci napi_module_register(&demoModule); 155e41f4b71Sopenharmony_ci} 156e41f4b71Sopenharmony_ci``` 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci#### Scenario 2: The API does not work when the native side throws an FD event to the main loop of the application. 159e41f4b71Sopenharmony_ci 160e41f4b71Sopenharmony_ciThe main loop of the application receives only FD events, and executes **uv_run** only after **backend_fd** in **uvloop** is triggered. That means **uv_run** will never be executed if no FD event is triggered when **uv** APIs are called in the main loop of the application. As a result, calling libuv APIs does not take effect. 161e41f4b71Sopenharmony_ci 162e41f4b71Sopenharmony_ci**Example (incorrect)** 163e41f4b71Sopenharmony_ci 164e41f4b71Sopenharmony_ciIn the following example, calling **uv_poll_start** in OpenHarmony in the same way as in native libuv does not take effect. 165e41f4b71Sopenharmony_ci 166e41f4b71Sopenharmony_ci```cpp 167e41f4b71Sopenharmony_ci#include "napi/native_api.h" 168e41f4b71Sopenharmony_ci#include "uv.h" 169e41f4b71Sopenharmony_ci#define LOG_DOMAIN 0X0202 170e41f4b71Sopenharmony_ci#define LOG_TAG "MyTag" 171e41f4b71Sopenharmony_ci#include <hilog/log.h> 172e41f4b71Sopenharmony_ci#include <thread> 173e41f4b71Sopenharmony_ci#include <sys/eventfd.h> 174e41f4b71Sopenharmony_ci#include <unistd.h> 175e41f4b71Sopenharmony_ciuv_loop_t *loop; 176e41f4b71Sopenharmony_cinapi_value jsCb; 177e41f4b71Sopenharmony_ciint fd = -1; 178e41f4b71Sopenharmony_civoid poll_handler(uv_poll_t* handle,int status, int events){ 179e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos poll print"); 180e41f4b71Sopenharmony_ci} 181e41f4b71Sopenharmony_cistatic napi_value TestClose(napi_env env, napi_callback_info info){ 182e41f4b71Sopenharmony_ci std::thread::id this_id = std::this_thread::get_id(); 183e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos thread id : %{public}ld\n", this_id); 184e41f4b71Sopenharmony_ci size_t argc = 1; 185e41f4b71Sopenharmony_ci napi_value workBname; 186e41f4b71Sopenharmony_ci 187e41f4b71Sopenharmony_ci napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &workBname); 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, &jsCb, nullptr, nullptr); 190e41f4b71Sopenharmony_ci // Obtain the event loop. 191e41f4b71Sopenharmony_ci napi_get_uv_event_loop(env, &loop); 192e41f4b71Sopenharmony_ci // Create an eventfd. 193e41f4b71Sopenharmony_ci fd = eventfd(0, 0); 194e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "fd is %{public}d\n",fd); 195e41f4b71Sopenharmony_ci uv_poll_t* poll_handle = new uv_poll_t; 196e41f4b71Sopenharmony_ci // Initialize a poll handle and associate it with eventfd. 197e41f4b71Sopenharmony_ci uv_poll_init(loop, poll_handle, fd); 198e41f4b71Sopenharmony_ci // Start to listen for the poll event. 199e41f4b71Sopenharmony_ci uv_poll_start(poll_handle, UV_READABLE, poll_handler); 200e41f4b71Sopenharmony_ci // Create a new thread and write data to eventfd. 201e41f4b71Sopenharmony_ci std::thread mythread([](){ 202e41f4b71Sopenharmony_ci for (int i = 0; i < 8; i++){ 203e41f4b71Sopenharmony_ci int value = 10; 204e41f4b71Sopenharmony_ci int ret = eventfd_write(fd, value); 205e41f4b71Sopenharmony_ci if (ret == -1){ 206e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "write failed!\n"); 207e41f4b71Sopenharmony_ci continue; 208e41f4b71Sopenharmony_ci } 209e41f4b71Sopenharmony_ci } 210e41f4b71Sopenharmony_ci }); 211e41f4b71Sopenharmony_ci mythread.detach(); 212e41f4b71Sopenharmony_ci return 0; 213e41f4b71Sopenharmony_ci} 214e41f4b71Sopenharmony_ciEXTERN_C_START 215e41f4b71Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports){ 216e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = {{"testClose", nullptr, TestClose, nullptr, nullptr, nullptr, napi_default, nullptr}}; 217e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 218e41f4b71Sopenharmony_ci return exports; 219e41f4b71Sopenharmony_ci} 220e41f4b71Sopenharmony_ciEXTERN_C_END 221e41f4b71Sopenharmony_ci 222e41f4b71Sopenharmony_cistatic napi_module demoModule = { 223e41f4b71Sopenharmony_ci .nm_version = 1, 224e41f4b71Sopenharmony_ci .nm_flags = 0, 225e41f4b71Sopenharmony_ci .nm_filename = nullptr, 226e41f4b71Sopenharmony_ci .nm_register_func = Init, 227e41f4b71Sopenharmony_ci .nm_modname = "entry", 228e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 229e41f4b71Sopenharmony_ci .reserved = {0}, 230e41f4b71Sopenharmony_ci}; 231e41f4b71Sopenharmony_ci 232e41f4b71Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterEntryModule(void){ 233e41f4b71Sopenharmony_ci napi_module_register(&demoModule); 234e41f4b71Sopenharmony_ci} 235e41f4b71Sopenharmony_ci``` 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ciThe process is as follows: 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci1. Use **napi_get_uv_event_loop** to obtain **uvloop** of the application main thread. 240e41f4b71Sopenharmony_ci2. Create an **eventfd** instance. 241e41f4b71Sopenharmony_ci3. Initialize **uv_poll_t**, and start the handle for it to take effect. Trigger the callback **poll_handler** when the **eventfd** instance is readable. 242e41f4b71Sopenharmony_ci4. Create a thread and write data to **eventfd**. 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ciAfter the preceding code is executed, data cannot be properly printed for **poll_handler**. This is because the main thread of the application executes **uv_run** based on the FD rather than in UV_RUN_DEFAULT mode. Although **event_handler** listens for **backend_fd** in **uvloop**, the FD is not added to **backend_fd** through **epoll_ctl** when **uv_poll_start** is executed. The **epoll_ctl** function is executed only when **uv__io_poll** in **uv_run** is executed the next time. Therefore, if no **backend_fd** event is triggered in the application process, the libuv APIs may not work as expected. 245e41f4b71Sopenharmony_ci 246e41f4b71Sopenharmony_ci**Workaround** 247e41f4b71Sopenharmony_ci 248e41f4b71Sopenharmony_ciIn the current system version, avoid using **napi_get_uv_event_loop** directly to obtain **uvloop** of the application main thread to develop service logic. If libuv must be used to implement service functions, after **uv_xxx_start** is called, use **uv_async_send** to trigger the main thread of the application to execute **uv_run**. In this way, **uv_xxx_start** can be properly executed. 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ciModify the code as follows: 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci```cpp 253e41f4b71Sopenharmony_ci#include "napi/native_api.h" 254e41f4b71Sopenharmony_ci#include "uv.h" 255e41f4b71Sopenharmony_ci#define LOG_DOMAIN 0x0202 256e41f4b71Sopenharmony_ci#define LOG_TAG "MyTag" 257e41f4b71Sopenharmony_ci#include <hilog/log.h> 258e41f4b71Sopenharmony_ci#include <thread> 259e41f4b71Sopenharmony_ci#include <sys/eventfd.h> 260e41f4b71Sopenharmony_ci#include <unistd.h> 261e41f4b71Sopenharmony_ciuv_loop_t *loop; 262e41f4b71Sopenharmony_cinapi_value jsCb; 263e41f4b71Sopenharmony_ciint fd = -1; 264e41f4b71Sopenharmony_civoid poll_handler(uv_poll_t* handle,int status, int events){ 265e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos poll print"); 266e41f4b71Sopenharmony_ci} 267e41f4b71Sopenharmony_cistatic napi_value TestClose(napi_env env, napi_callback_info info){ 268e41f4b71Sopenharmony_ci std::thread::id this_id = std::this_thread::get_id(); 269e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "ohos thread id : %{public}ld\n", this_id); 270e41f4b71Sopenharmony_ci size_t argc = 1; 271e41f4b71Sopenharmony_ci napi_value workBName; 272e41f4b71Sopenharmony_ci 273e41f4b71Sopenharmony_ci napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &workBName); 274e41f4b71Sopenharmony_ci 275e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, &jsCb, nullptr, nullptr); 276e41f4b71Sopenharmony_ci 277e41f4b71Sopenharmony_ci napi_get_uv_event_loop(env, &loop); 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci fd = eventfd(0, 0); 280e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "fd is %{public}d\n",fd); 281e41f4b71Sopenharmony_ci uv_poll_t* poll_handle = new uv_poll_t; 282e41f4b71Sopenharmony_ci uv_poll_init(loop, poll_handle, fd); 283e41f4b71Sopenharmony_ci uv_poll_start(poll_handle, UV_READABLE, poll_handler); 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci // Trigger an FD event to enable the main thread to execute uv_run. 286e41f4b71Sopenharmony_ci uv_async_send(&loop->wq_async); 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci std::thread mythread([](){ 289e41f4b71Sopenharmony_ci for (int i = 0; i < 8; i++){ 290e41f4b71Sopenharmony_ci int value = 10; 291e41f4b71Sopenharmony_ci int ret = eventfd_write(fd, value); 292e41f4b71Sopenharmony_ci if (ret == -1){ 293e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "write failed!\n"); 294e41f4b71Sopenharmony_ci continue; 295e41f4b71Sopenharmony_ci } 296e41f4b71Sopenharmony_ci } 297e41f4b71Sopenharmony_ci }); 298e41f4b71Sopenharmony_ci mythread.detach(); 299e41f4b71Sopenharmony_ci return 0; 300e41f4b71Sopenharmony_ci} 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ciEXTERN_C_START 303e41f4b71Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports){ 304e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = {{"testClose", nullptr, TestClose, nullptr, nullptr, nullptr, napi_default, nullptr}}; 305e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 306e41f4b71Sopenharmony_ci return exports; 307e41f4b71Sopenharmony_ci} 308e41f4b71Sopenharmony_ciEXTERN_C_END 309e41f4b71Sopenharmony_ci 310e41f4b71Sopenharmony_cistatic napi_module demoModule = { 311e41f4b71Sopenharmony_ci .nm_version = 1, 312e41f4b71Sopenharmony_ci .nm_flags = 0, 313e41f4b71Sopenharmony_ci .nm_filename = nullptr, 314e41f4b71Sopenharmony_ci .nm_register_func = Init, 315e41f4b71Sopenharmony_ci .nm_modname = "entry", 316e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 317e41f4b71Sopenharmony_ci .reserved = {0}, 318e41f4b71Sopenharmony_ci}; 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterEntryModule(void){ 321e41f4b71Sopenharmony_ci napi_module_register(&demoModule); 322e41f4b71Sopenharmony_ci} 323e41f4b71Sopenharmony_ci``` 324e41f4b71Sopenharmony_ci 325e41f4b71Sopenharmony_ci## Using libuv 326e41f4b71Sopenharmony_ci 327e41f4b71Sopenharmony_ciAll the APIs that depend on **uv_run** in the libuv NDK do not work as expected in the application main loop of the current system, and may cause freezing or loss of frames. You are advised not to directly use libuv NDK APIs in the JS main thread. You can use Node-API to implement async task execution and communication with the main thread using thread-safe functions. 328e41f4b71Sopenharmony_ci 329e41f4b71Sopenharmony_ci### Mappings Between libuv APIs and Node-API APIs 330e41f4b71Sopenharmony_ci 331e41f4b71Sopenharmony_ciInstead of using libuv APIs, you can use the equivalent Node-API provided by OpenHarmony, which includes async work APIs and thread-safe APIs. 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci#### Asynchronous Work APIs 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_cilibuv provides the **uv_queue_work** API to perform a time-consuming operation in an async thread and return the result to the main thread for processing through a callback. 336e41f4b71Sopenharmony_ci 337e41f4b71Sopenharmony_ciYou can use [napi_async_work](../../napi/use-napi-asynchronous-task.md) APIs of Node-API to implement async operations. 338e41f4b71Sopenharmony_ci 339e41f4b71Sopenharmony_ciThe related APIs are as follows: 340e41f4b71Sopenharmony_ci 341e41f4b71Sopenharmony_ci```cpp 342e41f4b71Sopenharmony_ci// Create a work object that executes logic asynchronously. 343e41f4b71Sopenharmony_ci// env: pointer to the current execution environment. 344e41f4b71Sopenharmony_ci// async_resource: (optional) resource object used to trace async operations. 345e41f4b71Sopenharmony_ci// async_resource_name: (optional) name of the resource object. The value is a string. 346e41f4b71Sopenharmony_ci// execute: callback invoked to perform an async operation in another thread. 347e41f4b71Sopenharmony_ci// complete: callback to be invoked when the async operation is complete. 348e41f4b71Sopenharmony_ci// data: pointer to the customized data to be passed to the execute and complete callbacks. 349e41f4b71Sopenharmony_ci// result: pointer to the async work object created. 350e41f4b71Sopenharmony_cinapi_status napi_create_async_work(napi_env env, 351e41f4b71Sopenharmony_ci napi_value async_resource, 352e41f4b71Sopenharmony_ci napi_value async_resource_name, 353e41f4b71Sopenharmony_ci napi_async_execute_callback execute, 354e41f4b71Sopenharmony_ci napi_async_complete_callback complete, 355e41f4b71Sopenharmony_ci void* data, 356e41f4b71Sopenharmony_ci napi_async_work* result); 357e41f4b71Sopenharmony_ci 358e41f4b71Sopenharmony_ci// Add an async work object to the queue so that it can be scheduled for execution. 359e41f4b71Sopenharmony_ci// env: pointer to the current execution environment. 360e41f4b71Sopenharmony_ci// work: pointer to the async work object to add. 361e41f4b71Sopenharmony_cinapi_status napi_queue_async_work(napi_env env, napi_async_work work); 362e41f4b71Sopenharmony_ci 363e41f4b71Sopenharmony_ci// Delete an async work object. 364e41f4b71Sopenharmony_ci// env: pointer to the current execution environment. 365e41f4b71Sopenharmony_ci// work: pointer to the async work object to delete. 366e41f4b71Sopenharmony_cinapi_status napi_delete_async_work(napi_env env, napi_async_work work); 367e41f4b71Sopenharmony_ci``` 368e41f4b71Sopenharmony_ci 369e41f4b71Sopenharmony_ci#### Thread-safe APIs for Cross-Thread Sharing and Invocation 370e41f4b71Sopenharmony_ci 371e41f4b71Sopenharmony_ciWhen you want to pass a callback to the application main thread, you can use the libuv **uv_async_t** handle, which is used for inter-thread communication, and the following functions: 372e41f4b71Sopenharmony_ci 373e41f4b71Sopenharmony_ci- uv_async_init() 374e41f4b71Sopenharmony_ci- uv_async_send() 375e41f4b71Sopenharmony_ci 376e41f4b71Sopenharmony_ciThe equivalent Node-API APIs are [napi_threadsafe_function](../../napi/use-napi-thread-safety.md) APIs. 377e41f4b71Sopenharmony_ci 378e41f4b71Sopenharmony_ci 379e41f4b71Sopenharmony_ci 380e41f4b71Sopenharmony_ci```cpp 381e41f4b71Sopenharmony_ci// Create a thread-safe function. 382e41f4b71Sopenharmony_ci// env: pointer to the current execution environment. 383e41f4b71Sopenharmony_ci// func: pointer to the JavaScript function to create. 384e41f4b71Sopenharmony_ci// resource_name: pointer to the resource name. 385e41f4b71Sopenharmony_ci// max_queue_size: maximum size of the queue. 386e41f4b71Sopenharmony_ci// initial_thread_count: number of initial threads. 387e41f4b71Sopenharmony_ci// callback: callback. 388e41f4b71Sopenharmony_ci// result: pointer to the operation result. 389e41f4b71Sopenharmony_cinapi_status napi_create_threadsafe_function(napi_env env, 390e41f4b71Sopenharmony_ci napi_value func, 391e41f4b71Sopenharmony_ci const char* resource_name, 392e41f4b71Sopenharmony_ci size_t max_queue_size, 393e41f4b71Sopenharmony_ci size_t initial_thread_count, 394e41f4b71Sopenharmony_ci void* context, 395e41f4b71Sopenharmony_ci napi_threadsafe_function_call_js call_js_func, 396e41f4b71Sopenharmony_ci napi_threadsafe_function_finalize finalize, 397e41f4b71Sopenharmony_ci napi_threadsafe_function* result); 398e41f4b71Sopenharmony_ci 399e41f4b71Sopenharmony_ci// Acquire a thread-safe function. 400e41f4b71Sopenharmony_ci// function: pointer to the thread-safe function to acquire. 401e41f4b71Sopenharmony_cinapi_status napi_acquire_threadsafe_function(napi_threadsafe_function function); 402e41f4b71Sopenharmony_ci 403e41f4b71Sopenharmony_ci// Call a thread-safe function. 404e41f4b71Sopenharmony_ci// function: pointer to the thread-safe function to call. 405e41f4b71Sopenharmony_ci// data: pointer to the user data. 406e41f4b71Sopenharmony_cinapi_status napi_call_threadsafe_function(napi_threadsafe_function function, void* data); 407e41f4b71Sopenharmony_ci 408e41f4b71Sopenharmony_ci// Release a thread-safe function. 409e41f4b71Sopenharmony_ci// function: pointer to the thread-safe function to release. 410e41f4b71Sopenharmony_cinapi_status napi_release_threadsafe_function(napi_threadsafe_function function); 411e41f4b71Sopenharmony_ci 412e41f4b71Sopenharmony_ci``` 413e41f4b71Sopenharmony_ci 414e41f4b71Sopenharmony_ciIf you need to use other libuv APIs to implement service functions, read on to discover basic libuv concepts and common APIs to be used in OpenHarmony, which are helpful to prevent application crashes when using libuv APIs. You can also learn about the APIs that can be used in the application main thread and those cannot. 415e41f4b71Sopenharmony_ci 416e41f4b71Sopenharmony_ci### Available APIs 417e41f4b71Sopenharmony_ci 418e41f4b71Sopenharmony_ci| API Type | API | 419e41f4b71Sopenharmony_ci| ---- | ---- | 420e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_loop_init | 421e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_loop_close | 422e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_default_loop | 423e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_run | 424e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_loop_alive | 425e41f4b71Sopenharmony_ci| [Loop](#event-loops-in-libuv) | uv_stop | 426e41f4b71Sopenharmony_ci| [Handle](#handles-and-requests-in-libuv) | uv_poll\_\* | 427e41f4b71Sopenharmony_ci| [Handle](#handles-and-requests-in-libuv) | uv_timer\_\* | 428e41f4b71Sopenharmony_ci| [Handle](#handles-and-requests-in-libuv) | uv_async\_\* | 429e41f4b71Sopenharmony_ci| [Handle](#handles-and-requests-in-libuv) | uv_signal\_\* | 430e41f4b71Sopenharmony_ci| [Handle](#handles-and-requests-in-libuv) | uv_fs\_\* | 431e41f4b71Sopenharmony_ci| [Request](#handles-and-requests-in-libuv) | uv_random | 432e41f4b71Sopenharmony_ci| [Request](#handles-and-requests-in-libuv) | uv_getaddrinfo | 433e41f4b71Sopenharmony_ci| [Request](#handles-and-requests-in-libuv) | uv_getnameinfo | 434e41f4b71Sopenharmony_ci| [Request](#handles-and-requests-in-libuv) | uv_queue_work | 435e41f4b71Sopenharmony_ci| [Inter-Thread communication](#inter-thread-communication) | uv_async_init | 436e41f4b71Sopenharmony_ci| [Inter-Thread communication](#inter-thread-communication) | uv_async_send | 437e41f4b71Sopenharmony_ci| [Thread pool](#thread-pool) | uv_queue_work | 438e41f4b71Sopenharmony_ci 439e41f4b71Sopenharmony_ci### Thread-Safe Functions 440e41f4b71Sopenharmony_ci 441e41f4b71Sopenharmony_ciA large number of async works are involved in libuv. Improper use of libuv APIs may cause multithreading issues. The following lists the common thread-safe and non-thread-safe functions in libuv. If a non-thread-safe function is called in multithreading programming, you need to add a lock or ensure correct execution timing of the code. Otherwise, the application may crash. 442e41f4b71Sopenharmony_ci 443e41f4b71Sopenharmony_ciThread-safe functions include the following: 444e41f4b71Sopenharmony_ci 445e41f4b71Sopenharmony_ci- **uv_async_init()**: initializes an async handle, which is used to wake up the main event loop thread from another thread and trigger a callback. 446e41f4b71Sopenharmony_ci- **uv_async_send()**: sends a signal to an async handle. This API can be called in any thread. 447e41f4b71Sopenharmony_ci- **uv_thread_create()**: creates a thread and executes the specified function. This API can be called in any thread. 448e41f4b71Sopenharmony_ci- **uv_fs\_\*()**: performs file system operations (*\** indicates the specific function name.) 449e41f4b71Sopenharmony_ci- **uv_poll\_\*()**: performs operations on polling events (*\** indicates the specific function name.) 450e41f4b71Sopenharmony_ci- Lock-related APIs, such as **uv\_mutex\_lock()** and **uv\_mutex\_unlock()**. 451e41f4b71Sopenharmony_ci 452e41f4b71Sopenharmony_ci> **NOTE** 453e41f4b71Sopenharmony_ci> 454e41f4b71Sopenharmony_ci> - Even if the function like **uv_xxx_init** is implemented in a thread-safe manner, avoid calling it by multiple threads at the same time. Otherwise, resource contention may occur. The best way is to call the function in an event loop thread. 455e41f4b71Sopenharmony_ci> - The callback invoked after **uv_async_send()** is triggered asynchronously. If **uv_async_send()** is called multiple times, libuv ensures that at least one callback is executed. As a result, if **uv_async_send()** is called for the same handle for multiple times, the callback processing may be different from your expectations. 456e41f4b71Sopenharmony_ci 457e41f4b71Sopenharmony_ci 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ciNon-thread-safe functions include the following: 460e41f4b71Sopenharmony_ci 461e41f4b71Sopenharmony_ci- **uv\_os\_unsetenv()**: deletes an environment variable. 462e41f4b71Sopenharmony_ci- **uv\_os\_setenv()**: sets an environment variable. 463e41f4b71Sopenharmony_ci- **uv\_os\_getenv()**: obtains an environment variable. 464e41f4b71Sopenharmony_ci- **uv\_os\_environ(**): retrieves all environment variables. 465e41f4b71Sopenharmony_ci- **uv\_os\_tmpdir()**: obtains the temporary directory. 466e41f4b71Sopenharmony_ci- **uv\_os\_homedir()**: obtains the home directory. 467e41f4b71Sopenharmony_ci 468e41f4b71Sopenharmony_ci### Event Loops in libuv 469e41f4b71Sopenharmony_ci 470e41f4b71Sopenharmony_ciAs a core concept in libuv, an event loop manages all resources of the entire event loop and runs through the lifecycle of the entire event loop. Generally, the thread where **uv_run** is located is the main thread of the event loop. 471e41f4b71Sopenharmony_ci 472e41f4b71Sopenharmony_ci#### Event Loop Running Modes 473e41f4b71Sopenharmony_ci 474e41f4b71Sopenharmony_ci- **UV_RUN_DEFAULT**: runs the event loop until there are no active handles or requests. This is the default mode. 475e41f4b71Sopenharmony_ci- **UV_RUN_ONCE**: polls for I/O once. If there is a callback in **pending_queue**, execute the callback and then skip **uv__io_poll**. In this mode, there is an event to occur in the loop by default. 476e41f4b71Sopenharmony_ci 477e41f4b71Sopenharmony_ci- **UV_RUN_NOWAIT**: polls for I/O once but do not block if there are no pending callbacks. In this mode, **uv__io_poll** is executed once and **pending_queue** is not executed. 478e41f4b71Sopenharmony_ci 479e41f4b71Sopenharmony_ci#### Common APIs 480e41f4b71Sopenharmony_ci 481e41f4b71Sopenharmony_ci```cpp 482e41f4b71Sopenharmony_ciint uv_loop_init(uv_loop_t* loop); 483e41f4b71Sopenharmony_ci``` 484e41f4b71Sopenharmony_ci 485e41f4b71Sopenharmony_ci Initializes a loop. 486e41f4b71Sopenharmony_ci 487e41f4b71Sopenharmony_ci```cpp 488e41f4b71Sopenharmony_ciint uv_loop_close(uv_loop_t* loop); 489e41f4b71Sopenharmony_ci``` 490e41f4b71Sopenharmony_ci 491e41f4b71Sopenharmony_ci Closes a loop. The operation is successful only after all handles and requests in the loop are closed. Otherwise, **UV_EBUSY** is returned. 492e41f4b71Sopenharmony_ci 493e41f4b71Sopenharmony_ci```cpp 494e41f4b71Sopenharmony_ciuv_loop_t* uv_default_loop(void); 495e41f4b71Sopenharmony_ci``` 496e41f4b71Sopenharmony_ci 497e41f4b71Sopenharmony_ci Creates a process-level loop. In OpenHarmony, libuv loops still exist in the application main loop and other JS worker threads. You are not advised to use this API to create loops and implement service functions. When the loop mechanism normalization is complete, you can use this API to create loops. 498e41f4b71Sopenharmony_ci 499e41f4b71Sopenharmony_ci```cpp 500e41f4b71Sopenharmony_ciint uv_run(uv_loop_t* loop, uv_run_mode mode); 501e41f4b71Sopenharmony_ci``` 502e41f4b71Sopenharmony_ci 503e41f4b71Sopenharmony_ci Runs an event loop. For details about the running mode, see [Event Loop Running Modes](#event-loop-running-modes). 504e41f4b71Sopenharmony_ci 505e41f4b71Sopenharmony_ci```cpp 506e41f4b71Sopenharmony_ciint uv_loop_alive(uv_loop_t loop); 507e41f4b71Sopenharmony_ci``` 508e41f4b71Sopenharmony_ci 509e41f4b71Sopenharmony_ci Checks whether a loop is active. 510e41f4b71Sopenharmony_ci 511e41f4b71Sopenharmony_ci```cpp 512e41f4b71Sopenharmony_civoid uv_stop(uv_loop_t* loop); 513e41f4b71Sopenharmony_ci``` 514e41f4b71Sopenharmony_ci 515e41f4b71Sopenharmony_ci Stops an event loop. The event loop stops only in the next iteration of the loop. If this API is called before an I/O operation, **uv__io_poll** will be skipped instead of being blocked. 516e41f4b71Sopenharmony_ci 517e41f4b71Sopenharmony_ci> **Tips** 518e41f4b71Sopenharmony_ci> 519e41f4b71Sopenharmony_ci> Pay special attention to the use of **uv_stop**. Before **uv_stop** is called, ensure that the handles of all threads related to the loop are closed. 520e41f4b71Sopenharmony_ci 521e41f4b71Sopenharmony_ciThe sample code is as follows: 522e41f4b71Sopenharmony_ci 523e41f4b71Sopenharmony_ci```cpp 524e41f4b71Sopenharmony_ciint stop_loop(uv_loop_t* loop) 525e41f4b71Sopenharmony_ci{ 526e41f4b71Sopenharmony_ci uv_stop(loop); 527e41f4b71Sopenharmony_ci auto const ensure_close = [](uv_handle_t* handle, void*) { 528e41f4b71Sopenharmony_ci if (uv_is_closing(handle)) { 529e41f4b71Sopenharmony_ci return; 530e41f4b71Sopenharmony_ci } else { 531e41f4b71Sopenharmony_ci uv_close(handle, nullptr); 532e41f4b71Sopenharmony_ci } 533e41f4b71Sopenharmony_ci }; 534e41f4b71Sopenharmony_ci // Traverse all handles. Call ensure_close to close the active handle. 535e41f4b71Sopenharmony_ci uv_walk(loop, ensure_close, nullptr); 536e41f4b71Sopenharmony_ci 537e41f4b71Sopenharmony_ci // Continue to run uv_run until there is no active handle or request in the loop. 538e41f4b71Sopenharmony_ci while(true) { 539e41f4b71Sopenharmony_ci if (uv_run(loop, UV_RUN_DEFAULT) == 0) { 540e41f4b71Sopenharmony_ci break; 541e41f4b71Sopenharmony_ci } 542e41f4b71Sopenharmony_ci } 543e41f4b71Sopenharmony_ci 544e41f4b71Sopenharmony_ci // Check the loop status. 545e41f4b71Sopenharmony_ci if (uv_loop_alive(loop) != 0) { 546e41f4b71Sopenharmony_ci return -1; 547e41f4b71Sopenharmony_ci } 548e41f4b71Sopenharmony_ci return 0; 549e41f4b71Sopenharmony_ci} 550e41f4b71Sopenharmony_ci``` 551e41f4b71Sopenharmony_ci 552e41f4b71Sopenharmony_ci### Handles and Requests in libuv 553e41f4b71Sopenharmony_ci 554e41f4b71Sopenharmony_ciA handle indicates a persistent object, which is usually mounted to the corresponding **handle_queue** in a loop. If a handle is active, **uv_run** will process the callback in the handle each time. 555e41f4b71Sopenharmony_ci 556e41f4b71Sopenharmony_ciA request indicates a temporary request. A request triggers only one callback. 557e41f4b71Sopenharmony_ci 558e41f4b71Sopenharmony_ciThe commonly used handles and requests in OpenHarmony include the following: 559e41f4b71Sopenharmony_ci 560e41f4b71Sopenharmony_ci```cpp 561e41f4b71Sopenharmony_ci/* Handle types. */ 562e41f4b71Sopenharmony_citypedef struct uv_handle_s uv_handle_t; 563e41f4b71Sopenharmony_citypedef struct uv_timer_s uv_timer_t; 564e41f4b71Sopenharmony_citypedef struct uv_async_s uv_async_t; 565e41f4b71Sopenharmony_citypedef struct uv_signal_s uv_signal_t; 566e41f4b71Sopenharmony_ci 567e41f4b71Sopenharmony_ci/* Request types. */ 568e41f4b71Sopenharmony_citypedef struct uv_req_s uv_req_t; 569e41f4b71Sopenharmony_citypedef struct uv_work_s uv_work_t; 570e41f4b71Sopenharmony_citypedef struct uv_fs_s uv_fs_t; 571e41f4b71Sopenharmony_ci``` 572e41f4b71Sopenharmony_ci 573e41f4b71Sopenharmony_ci> **NOTE** 574e41f4b71Sopenharmony_ci> 575e41f4b71Sopenharmony_ci> In handles, **uv_xxx_t** inherits from **uv_handle_t**. In requests, **uv_work_t** inherits from **uv_req_t**. 576e41f4b71Sopenharmony_ci 577e41f4b71Sopenharmony_ciIt is critical to understand the handles in libuv and manage its lifecycle. Observe the following when using a handle: 578e41f4b71Sopenharmony_ci 579e41f4b71Sopenharmony_ci1. Perform the handle initialization in the event loop thread. 580e41f4b71Sopenharmony_ci2. If the handle needs to be initialized in a worker thread due to service requirements, use an atomic variable to check whether the initialization is complete before the handle is used. 581e41f4b71Sopenharmony_ci3. For the handle that is no longer used, call **uv_close** to remove it from the loop. 582e41f4b71Sopenharmony_ci 583e41f4b71Sopenharmony_ciNote that **uv_close** is used to close a handle asynchronously. Its prototype is as follows: 584e41f4b71Sopenharmony_ci 585e41f4b71Sopenharmony_ci```cpp 586e41f4b71Sopenharmony_civoid uv_close(uv_handle_t* handle, uv_close_cb close_cb) 587e41f4b71Sopenharmony_ci``` 588e41f4b71Sopenharmony_ci 589e41f4b71Sopenharmony_ci **handle**: pointer to the handle to close. 590e41f4b71Sopenharmony_ci 591e41f4b71Sopenharmony_ci **close_cb**: function used to process the handle. This function is used to perform operations such as memory management. 592e41f4b71Sopenharmony_ci 593e41f4b71Sopenharmony_ciAfter **uv_close** is called, the handle to be closed is added to the **closing_handles** queue in the loop, and waits for the loop thread to run **uv__run_closing_handles**. Finally, the **close_cb** callback is executed in the next iteration of the loop. Therefore, operations such as memory release should be performed in **close_cb**. Improper use of the **close** API that is executed asynchronously may cause multithreading issues. You need to ensure correct timing of **uv_close** and ensure that all the handles are closed before **close_cb** is executed. 594e41f4b71Sopenharmony_ci 595e41f4b71Sopenharmony_ci> **Tips** 596e41f4b71Sopenharmony_ci> 597e41f4b71Sopenharmony_ci> The following rule of thumb in the official libuv documentation (http://libuv.org/) needs to be observed: 598e41f4b71Sopenharmony_ci> 599e41f4b71Sopenharmony_ci> If a handle of type **uv_foo_t** has a **uv_foo_start()** function, then it's active from the moment that function is called. Likewise, **uv_foo_stop()** deactivates the handle again. 600e41f4b71Sopenharmony_ci 601e41f4b71Sopenharmony_ciFor the libuv request that is dynamically requested, release it in the callback of the loop thread. The following uses **uv_work_t** as an example. 602e41f4b71Sopenharmony_ci 603e41f4b71Sopenharmony_ci```cpp 604e41f4b71Sopenharmony_ciuv_work_t* work = new uv_work_t; 605e41f4b71Sopenharmony_ciuv_queue_work(loop, work, [](uv_work_t* req) { 606e41f4b71Sopenharmony_ci // Asynchronous operation 607e41f4b71Sopenharmony_ci}, [](uv_work_t* req, int status) { 608e41f4b71Sopenharmony_ci // Callback 609e41f4b71Sopenharmony_ci delete req; 610e41f4b71Sopenharmony_ci}); 611e41f4b71Sopenharmony_ci``` 612e41f4b71Sopenharmony_ci 613e41f4b71Sopenharmony_ci### Inter-Thread Communication 614e41f4b71Sopenharmony_ci 615e41f4b71Sopenharmony_ciSo far, you have learn about the basic concepts of libuv. Now let's dive into the inter-thread communication in libuv. 616e41f4b71Sopenharmony_ci 617e41f4b71Sopenharmony_ciThe inter-thread communication of libuv is implemented based on the **uv_async_t** handle. The related APIs are as follows: 618e41f4b71Sopenharmony_ci 619e41f4b71Sopenharmony_ci```cpp 620e41f4b71Sopenharmony_ciint uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) 621e41f4b71Sopenharmony_ci``` 622e41f4b71Sopenharmony_ci 623e41f4b71Sopenharmony_ciInitializes a handle. 624e41f4b71Sopenharmony_ci 625e41f4b71Sopenharmony_ci- **loop**: pointer to the event loop. 626e41f4b71Sopenharmony_ci- **handle**: pointer to the handle for inter-thread communication. 627e41f4b71Sopenharmony_ci- **async_cb**: callback to be invoked. 628e41f4b71Sopenharmony_ci 629e41f4b71Sopenharmony_ci The API returns **0** if the operation is successful; returns an error code if the operation fails. 630e41f4b71Sopenharmony_ci 631e41f4b71Sopenharmony_ci```cpp 632e41f4b71Sopenharmony_ciint uv_async_send(uv_async_t* handle) 633e41f4b71Sopenharmony_ci``` 634e41f4b71Sopenharmony_ci 635e41f4b71Sopenharmony_ci Wakes up the event loop and calls the async handle's callback. 636e41f4b71Sopenharmony_ci 637e41f4b71Sopenharmony_ci **handle**: pointer to the handle for inter-thread communication. 638e41f4b71Sopenharmony_ci 639e41f4b71Sopenharmony_ci The API returns **0** if the operation is successful; returns an error code if the operation fails. 640e41f4b71Sopenharmony_ci 641e41f4b71Sopenharmony_ci> **NOTE** 642e41f4b71Sopenharmony_ci> 643e41f4b71Sopenharmony_ci> **uv_async_t** remains active after **uv_async_init** is called till it is closed by **uv_close**. 644e41f4b71Sopenharmony_ci> **uv_async_t** is executed in the sequence defined by **uv_async_init** instead of **uv_async_send**. Therefore, it is necessary to manage the timing according to the initialization sequence. 645e41f4b71Sopenharmony_ci 646e41f4b71Sopenharmony_ci 647e41f4b71Sopenharmony_ci 648e41f4b71Sopenharmony_ci 649e41f4b71Sopenharmony_ci 650e41f4b71Sopenharmony_ciExample: 651e41f4b71Sopenharmony_ci 652e41f4b71Sopenharmony_ci```cpp 653e41f4b71Sopenharmony_ci#include <bits/stdc++.h> 654e41f4b71Sopenharmony_ci#include "uv.h" 655e41f4b71Sopenharmony_ci 656e41f4b71Sopenharmony_ciuv_loop_t* loop = nullptr; 657e41f4b71Sopenharmony_ciuv_async_t* async = nullptr; 658e41f4b71Sopenharmony_civoid async_handler(uv_async_t* handle) 659e41f4b71Sopenharmony_ci{ 660e41f4b71Sopenharmony_ci printf("ohos async print\n"); 661e41f4b71Sopenharmony_ci} 662e41f4b71Sopenharmony_ci 663e41f4b71Sopenharmony_ciint main() 664e41f4b71Sopenharmony_ci{ 665e41f4b71Sopenharmony_ci loop = uv_default_loop(); 666e41f4b71Sopenharmony_ci async = new uv_async_t; 667e41f4b71Sopenharmony_ci uv_async_init(loop, async, async_handler); 668e41f4b71Sopenharmony_ci std::thread subThread([]() { 669e41f4b71Sopenharmony_ci for (int i = 0; i < 10; i++) { 670e41f4b71Sopenharmony_ci usleep(100); 671e41f4b71Sopenharmony_ci printf("%dth: subThread triggered\n", i); 672e41f4b71Sopenharmony_ci uv_async_send(async); 673e41f4b71Sopenharmony_ci } 674e41f4b71Sopenharmony_ci // Call uv_close to close the async handle and release the memory in the main loop. 675e41f4b71Sopenharmony_ci uv_close((uv_handle_t*)async, [](uv_handle_t* handle) { 676e41f4b71Sopenharmony_ci printf("delete async\n"); 677e41f4b71Sopenharmony_ci delete (uv_async_t*)handle; 678e41f4b71Sopenharmony_ci }); 679e41f4b71Sopenharmony_ci uv_stop(loop); 680e41f4b71Sopenharmony_ci }); 681e41f4b71Sopenharmony_ci subThread.detach(); 682e41f4b71Sopenharmony_ci return uv_run(loop, UV_RUN_DEFAULT); 683e41f4b71Sopenharmony_ci} 684e41f4b71Sopenharmony_ci``` 685e41f4b71Sopenharmony_ci 686e41f4b71Sopenharmony_ciThe sample code describes only a simple scenario. The procedure is as follows: 687e41f4b71Sopenharmony_ci 688e41f4b71Sopenharmony_ci1. Initialize the async handle in the main thread. 689e41f4b71Sopenharmony_ci2. Create a worker thread and trigger **uv_async_send** every 100 milliseconds. After **uv_async_send** is called 10 times, call **uv_close** to close the async handle. 690e41f4b71Sopenharmony_ci3. Run the event loop on the main thread. 691e41f4b71Sopenharmony_ci 692e41f4b71Sopenharmony_ciAs indicated by the following information, each time **uv_async_send** is called, the main thread executes the callback. 693e41f4b71Sopenharmony_ci 694e41f4b71Sopenharmony_ci``` 695e41f4b71Sopenharmony_ci0th:subThread triggered 696e41f4b71Sopenharmony_ciohos async print 697e41f4b71Sopenharmony_ci1th:subThread triggered 698e41f4b71Sopenharmony_ciohos async print 699e41f4b71Sopenharmony_ci2th:subThread triggered 700e41f4b71Sopenharmony_ciohos async print 701e41f4b71Sopenharmony_ci3th:subThread triggered 702e41f4b71Sopenharmony_ciohos async print 703e41f4b71Sopenharmony_ci4th:subThread triggered 704e41f4b71Sopenharmony_ciohos async print 705e41f4b71Sopenharmony_ci5th:subThread triggered 706e41f4b71Sopenharmony_ciohos async print 707e41f4b71Sopenharmony_ci6th:subThread triggered 708e41f4b71Sopenharmony_ciohos async print 709e41f4b71Sopenharmony_ci7th:subThread triggered 710e41f4b71Sopenharmony_ciohos async print 711e41f4b71Sopenharmony_ci8th:subThread triggered 712e41f4b71Sopenharmony_ciohos async print 713e41f4b71Sopenharmony_ci9th:subThread triggered 714e41f4b71Sopenharmony_cidelete async 715e41f4b71Sopenharmony_ci``` 716e41f4b71Sopenharmony_ci 717e41f4b71Sopenharmony_ci### Thread Pool 718e41f4b71Sopenharmony_ci 719e41f4b71Sopenharmony_ciThe thread pool in libuv uses the member variable **wq_async** in **uv_loop_t** to control the communication between the main thread and worker threads. The core API is as follows: 720e41f4b71Sopenharmony_ci 721e41f4b71Sopenharmony_ci```cpp 722e41f4b71Sopenharmony_ciint uv_queue_work(uv_loop_t* loop, 723e41f4b71Sopenharmony_ci uv_work_t* req, 724e41f4b71Sopenharmony_ci uv_work_cb work_cb, 725e41f4b71Sopenharmony_ci uv_after_work_cb after_work_cb) 726e41f4b71Sopenharmony_ci``` 727e41f4b71Sopenharmony_ci 728e41f4b71Sopenharmony_ciInitializes a work request which will run the given **work_cb** in a thread from the thread pool. 729e41f4b71Sopenharmony_ci 730e41f4b71Sopenharmony_ci**work_cb**: task submitted to the worker thread. 731e41f4b71Sopenharmony_ci 732e41f4b71Sopenharmony_ci**after_work_cb**: callback to be executed by the loop thread. 733e41f4b71Sopenharmony_ci 734e41f4b71Sopenharmony_ci> **NOTE** 735e41f4b71Sopenharmony_ci> 736e41f4b71Sopenharmony_ci> **after work_cb** is called after **work_cb** is complete. It is triggered by an FD event triggered by **uv_async_send(loop->wq_async)** and executed in the next iteration of the loop thread. The **uv_work_t** lifecycle ends only when **after_work_cb** is executed. 737e41f4b71Sopenharmony_ci 738e41f4b71Sopenharmony_ciThe following figure illustrates a simplified workflow of the libuv thread pool. The default pending flag of the handle is 1. The number of worker threads is an example only. 739e41f4b71Sopenharmony_ci 740e41f4b71Sopenharmony_ci 741e41f4b71Sopenharmony_ci 742e41f4b71Sopenharmony_ci### Use of libuv in OpenHarmony 743e41f4b71Sopenharmony_ci 744e41f4b71Sopenharmony_ciCurrently, libuv threads are used in the main thread, JS Worker thread, TaskWorker thread in the Taskpool, and IPC thread of OpenHarmony. Except the main thread, which uses **eventhandler** as the main loop, other threads use the **UV_RUN_DEFAULT** mode in libuv as the event main loop of the calling thread to execute tasks. In the main thread, **eventhandler** triggers task execution by an FD event. **eventhandler** listens for **backend_fd** in **uv_loop**. Once an FD event is triggered in the loop, **eventhandler** calls **uv_run** to execute tasks in libuv. 745e41f4b71Sopenharmony_ci 746e41f4b71Sopenharmony_ciAs a result, all the uv APIs that are not triggered by an FD event in the main thread are not responded in a timely manner. The uv APIs on the JS worker threads work as expected. 747e41f4b71Sopenharmony_ci 748e41f4b71Sopenharmony_ciIn addition, in the application main thread, all async tasks are eventually executed through libuv. However, in the current system, [the libuv thread pool has been incorporated to the FFRT](https://gitee.com/openharmony/third_party_libuv/wikis/06-Wiki-%E6%8A%80%E6%9C%AF%E8%B5%84%E6%BA%90/%20libuv%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E6%8E%A5%E5%85%A5FFRT%E6%96%B9%E6%A1%88%E5%88%86%E6%9E%90). Any async task thrown to the libuv thread will be scheduled by the FFRT thread. The callbacks of the application main thread are also inserted into the **eventhandler** queue by **PostTask()**. This means that after the async task in an FFRT thread is complete, the callback of the main thread is not triggered by **uv_async_send**. 749e41f4b71Sopenharmony_ci 750e41f4b71Sopenharmony_ciThe following figure shows the process. 751e41f4b71Sopenharmony_ci 752e41f4b71Sopenharmony_ci 753e41f4b71Sopenharmony_ci 754e41f4b71Sopenharmony_ciThe following types of requests can be processed as expected in the application main loop: 755e41f4b71Sopenharmony_ci 756e41f4b71Sopenharmony_ci- uv_random_t 757e41f4b71Sopenharmony_ci 758e41f4b71Sopenharmony_ci Function prototype: 759e41f4b71Sopenharmony_ci 760e41f4b71Sopenharmony_ci ```cpp 761e41f4b71Sopenharmony_ci /** 762e41f4b71Sopenharmony_ci * Add a work request to an event loop queue. 763e41f4b71Sopenharmony_ci * 764e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 765e41f4b71Sopenharmony_ci * @param req indicates the pointer to the request. 766e41f4b71Sopenharmony_ci * @param buf indicates the buffer for storing the random number. 767e41f4b71Sopenharmony_ci * @param buflen indicates the length of the buffer. 768e41f4b71Sopenharmony_ci * @param flags indicates the options for generating the random number. 769e41f4b71Sopenharmony_ci * @param cb indicates the callback used to return the random number generated. 770e41f4b71Sopenharmony_ci * 771e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns an error code otherwise. 772e41f4b71Sopenharmony_ci */ 773e41f4b71Sopenharmony_ci int uv_random(uv_loop_t* loop, 774e41f4b71Sopenharmony_ci uv_random_t* req, 775e41f4b71Sopenharmony_ci void* buf, 776e41f4b71Sopenharmony_ci size_t buflen, 777e41f4b71Sopenharmony_ci unsigned flags, 778e41f4b71Sopenharmony_ci uv_random_cb cb); 779e41f4b71Sopenharmony_ci ``` 780e41f4b71Sopenharmony_ci 781e41f4b71Sopenharmony_ci- uv_work_t 782e41f4b71Sopenharmony_ci 783e41f4b71Sopenharmony_ci Function prototype: 784e41f4b71Sopenharmony_ci 785e41f4b71Sopenharmony_ci ```cpp 786e41f4b71Sopenharmony_ci /** 787e41f4b71Sopenharmony_ci * Add a work request to an event loop queue. 788e41f4b71Sopenharmony_ci * 789e41f4b71Sopenharmony_ci * work_cb will be called by a new thread in the next iteration of the event loop. 790e41f4b71Sopenharmony_ci * When work_cb is complete, after_work_cb will be called on the event loop thread. 791e41f4b71Sopenharmony_ci * 792e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 793e41f4b71Sopenharmony_ci * @param req indicates the pointer to the work request. 794e41f4b71Sopenharmony_ci * @param work_cb indicates the callback to be executed on a new thread. 795e41f4b71Sopenharmony_ci * @param after_work_cb indicates the callback to be invoked on the event loop thread. 796e41f4b71Sopenharmony_ci * 797e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 798e41f4b71Sopenharmony_ci */ 799e41f4b71Sopenharmony_ci int uv_queue_work(uv_loop_t* loop, 800e41f4b71Sopenharmony_ci uv_work_t* req, 801e41f4b71Sopenharmony_ci uv_work_cb work_cb, 802e41f4b71Sopenharmony_ci uv_after_work_cb after_work_cb); 803e41f4b71Sopenharmony_ci ``` 804e41f4b71Sopenharmony_ci 805e41f4b71Sopenharmony_ci- uv_fs_t 806e41f4b71Sopenharmony_ci 807e41f4b71Sopenharmony_ci All async APIs provided by the file class can work as expected in the application main thread. Common APIs include the following: 808e41f4b71Sopenharmony_ci 809e41f4b71Sopenharmony_ci ```cpp 810e41f4b71Sopenharmony_ci /** 811e41f4b71Sopenharmony_ci * Read a file asynchronously. 812e41f4b71Sopenharmony_ci * 813e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 814e41f4b71Sopenharmony_ci * @param req indicates the pointer to the file operation request. 815e41f4b71Sopenharmony_ci * @param file indicates the file descriptor. 816e41f4b71Sopenharmony_ci * @param bufs indicates an array of buffers for storing the data read. 817e41f4b71Sopenharmony_ci * @param nbufs indicates the number of buffers. 818e41f4b71Sopenharmony_ci * @param off indicates the offset in the file from which data is read. 819e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the read operation is complete. 820e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 821e41f4b71Sopenharmony_ci */ 822e41f4b71Sopenharmony_ci int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, 823e41f4b71Sopenharmony_ci uv_file file, 824e41f4b71Sopenharmony_ci const uv_buf_t bufs[], 825e41f4b71Sopenharmony_ci unsigned int nbufs, 826e41f4b71Sopenharmony_ci int64_t off, 827e41f4b71Sopenharmony_ci uv_fs_cb cb); 828e41f4b71Sopenharmony_ci 829e41f4b71Sopenharmony_ci /** 830e41f4b71Sopenharmony_ci * Open a file asynchronously. 831e41f4b71Sopenharmony_ci * 832e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 833e41f4b71Sopenharmony_ci * @param req indicates the pointer to the file operation request. 834e41f4b71Sopenharmony_ci * * @param path indicates the pointer to the path of the file to open. 835e41f4b71Sopenharmony_ci * @param flags indicates the modes for opening the file. 836e41f4b71Sopenharmony_ci * * @param mode indicates the permission on the file. 837e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the file is opened. 838e41f4b71Sopenharmony_ci * 839e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 840e41f4b71Sopenharmony_ci */ 841e41f4b71Sopenharmony_ci int uv_fs_open(uv_loop_t* loop, 842e41f4b71Sopenharmony_ci uv_fs_t* req, 843e41f4b71Sopenharmony_ci const char* path, 844e41f4b71Sopenharmony_ci int flags, 845e41f4b71Sopenharmony_ci int mode, 846e41f4b71Sopenharmony_ci uv_fs_cb cb); 847e41f4b71Sopenharmony_ci 848e41f4b71Sopenharmony_ci /** 849e41f4b71Sopenharmony_ci * Sends data from a file to another asynchronously. 850e41f4b71Sopenharmony_ci * 851e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 852e41f4b71Sopenharmony_ci * @param req indicates the pointer to the file operation request. 853e41f4b71Sopenharmony_ci * @param out_fd indicates the file descriptor of the destination file. 854e41f4b71Sopenharmony_ci * @param in_fd indicates the file descriptor of the source file. 855e41f4b71Sopenharmony_ci * @param off indicates the offset in the source file from which data is sent. 856e41f4b71Sopenharmony_ci * @param len indicates the length of the data to be sent. 857e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the data is sent. 858e41f4b71Sopenharmony_ci * 859e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 860e41f4b71Sopenharmony_ci */ 861e41f4b71Sopenharmony_ci int uv_fs_sendfile(uv_loop_t* loop, 862e41f4b71Sopenharmony_ci uv_fs_t* req, 863e41f4b71Sopenharmony_ci uv_file out_fd, 864e41f4b71Sopenharmony_ci uv_file in_fd, 865e41f4b71Sopenharmony_ci int64_t off, 866e41f4b71Sopenharmony_ci size_t len, 867e41f4b71Sopenharmony_ci uv_fs_cb cb); 868e41f4b71Sopenharmony_ci 869e41f4b71Sopenharmony_ci /** 870e41f4b71Sopenharmony_ci * Write data to a file asynchronously. 871e41f4b71Sopenharmony_ci * 872e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 873e41f4b71Sopenharmony_ci * @param req indicates the pointer to the file operation request. 874e41f4b71Sopenharmony_ci * @param file indicates the file descriptor. 875e41f4b71Sopenharmony_ci * * @param data indicates an array of buffers for storing the data to be written. 876e41f4b71Sopenharmony_ci * @param nbufs indicates the number of buffers. 877e41f4b71Sopenharmony_ci * @param off indicates the offset in the file from which data is written. 878e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the write operation is complete. 879e41f4b71Sopenharmony_ci * 880e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 881e41f4b71Sopenharmony_ci */ 882e41f4b71Sopenharmony_ci int uv_fs_write(uv_loop_t* loop, 883e41f4b71Sopenharmony_ci uv_fs_t* req, 884e41f4b71Sopenharmony_ci uv_file file, 885e41f4b71Sopenharmony_ci const uv_buf_t bufs[], 886e41f4b71Sopenharmony_ci unsigned int nbufs, 887e41f4b71Sopenharmony_ci int64_t off, 888e41f4b71Sopenharmony_ci uv_fs_cb cb); 889e41f4b71Sopenharmony_ci 890e41f4b71Sopenharmony_ci /** 891e41f4b71Sopenharmony_ci * Copy a file asynchronously. 892e41f4b71Sopenharmony_ci * 893e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 894e41f4b71Sopenharmony_ci * @param req indicates the pointer to the file operation request. 895e41f4b71Sopenharmony_ci * @param path indicates the pointer to the path of the file to copy. 896e41f4b71Sopenharmony_ci * @param new_path indicates the pointer to the destination path. 897e41f4b71Sopenharmony_ci * @param flags indicates the options for the copy operation. 898e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the copy operation is complete. 899e41f4b71Sopenharmony_ci * 900e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 901e41f4b71Sopenharmony_ci */ 902e41f4b71Sopenharmony_ci int uv_fs_copyfile(uv_loop_t* loop, 903e41f4b71Sopenharmony_ci uv_fs_t* req, 904e41f4b71Sopenharmony_ci const char* path, 905e41f4b71Sopenharmony_ci const char* new_path 906e41f4b71Sopenharmony_ci int flags, 907e41f4b71Sopenharmony_ci uv_fs_cb cb); 908e41f4b71Sopenharmony_ci ``` 909e41f4b71Sopenharmony_ci 910e41f4b71Sopenharmony_ci- uv_getaddrinfo_t 911e41f4b71Sopenharmony_ci 912e41f4b71Sopenharmony_ci Function prototype: 913e41f4b71Sopenharmony_ci 914e41f4b71Sopenharmony_ci ```cpp 915e41f4b71Sopenharmony_ci /** 916e41f4b71Sopenharmony_ci * Obtain address information asynchronously. 917e41f4b71Sopenharmony_ci * 918e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 919e41f4b71Sopenharmony_ci * @param req indicates the pointer to the request for obtaining address information. 920e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the address information is obtained. 921e41f4b71Sopenharmony_ci * @param hostname indicates the pointer to the host name to resolve. 922e41f4b71Sopenharmony_ci * @param service indicates the pointer to the service name. 923e41f4b71Sopenharmony_ci * @param hints indicates the pointer to the address information with additional address type constraints. 924e41f4b71Sopenharmony_ci * 925e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 926e41f4b71Sopenharmony_ci */ 927e41f4b71Sopenharmony_ci int uv_getaddrinfo(uv_loop_t* loop, 928e41f4b71Sopenharmony_ci uv_getaddrinfo_t* req, 929e41f4b71Sopenharmony_ci uv_getaddrinfo_cb cb, 930e41f4b71Sopenharmony_ci const char* hostname, 931e41f4b71Sopenharmony_ci const char* service, 932e41f4b71Sopenharmony_ci const struct addrinfo* hints); 933e41f4b71Sopenharmony_ci ``` 934e41f4b71Sopenharmony_ci 935e41f4b71Sopenharmony_ci- uv_getnameinfo_t 936e41f4b71Sopenharmony_ci 937e41f4b71Sopenharmony_ci Function prototype: 938e41f4b71Sopenharmony_ci 939e41f4b71Sopenharmony_ci ```cpp 940e41f4b71Sopenharmony_ci /** 941e41f4b71Sopenharmony_ci * Obtain name information asynchronously. 942e41f4b71Sopenharmony_ci * 943e41f4b71Sopenharmony_ci * @param loop indicates the pointer to the event loop. 944e41f4b71Sopenharmony_ci * @param req indicates the pointer to the request. 945e41f4b71Sopenharmony_ci * @param cb indicates the callback to be invoked when the name information is obtained. 946e41f4b71Sopenharmony_ci * @param addr indicates the pointer to the address information to resolve. 947e41f4b71Sopenharmony_ci * @param flags indicates the flags for controlling the behavior of the lookup. 948e41f4b71Sopenharmony_ci * 949e41f4b71Sopenharmony_ci * @return Returns 0 if the operation is successful; returns -1 otherwise. 950e41f4b71Sopenharmony_ci */ 951e41f4b71Sopenharmony_ci int uv_getnameinfo(uv_loop_t* loop, 952e41f4b71Sopenharmony_ci uv_getnameinfo_t* req, 953e41f4b71Sopenharmony_ci uv_getnameinfo_cb getnameinfo_cb, 954e41f4b71Sopenharmony_ci const struct sockaddr* addr, 955e41f4b71Sopenharmony_ci int flags); 956e41f4b71Sopenharmony_ci ``` 957e41f4b71Sopenharmony_ci 958e41f4b71Sopenharmony_ciThe following APIs do not work as expected in the application main thread: 959e41f4b71Sopenharmony_ci 960e41f4b71Sopenharmony_ci- **Idle** handle 961e41f4b71Sopenharmony_ci- **prepare** handle 962e41f4b71Sopenharmony_ci- **check** handle 963e41f4b71Sopenharmony_ci- signal-related functions 964e41f4b71Sopenharmony_ci- Functions related to TCP and UDP 965e41f4b71Sopenharmony_ci 966e41f4b71Sopenharmony_ci## Case Study 967e41f4b71Sopenharmony_ci 968e41f4b71Sopenharmony_ci[Cause of Incorrect Triggering Time of the Timer Callback in the Main Thread of libuv](https://gitee.com/openharmony/third_party_libuv/wikis/06-Wiki-%E6%8A%80%E6%9C%AF%E8%B5%84%E6%BA%90/libuv%E4%B8%AD%E4%B8%BB%E7%BA%BF%E7%A8%8Btimer%E5%9B%9E%E8%B0%83%E4%BA%8B%E4%BB%B6%E8%A7%A6%E5%8F%91%E6%97%B6%E9%97%B4%E4%B8%8D%E6%AD%A3%E7%A1%AE%E5%8E%9F%E5%9B%A0) 969e41f4b71Sopenharmony_ci 970e41f4b71Sopenharmony_ci[Incorporating libuv Worker Threads to the FFRT](https://gitee.com/openharmony/third_party_libuv/wikis/06-Wiki-%E6%8A%80%E6%9C%AF%E8%B5%84%E6%BA%90/%20libuv%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E6%8E%A5%E5%85%A5FFRT%E6%96%B9%E6%A1%88%E5%88%86%E6%9E%90) 971e41f4b71Sopenharmony_ci 972e41f4b71Sopenharmony_ci[FAQs for QoS-Aware libuv and Node-API Async API Improvements](https://gitee.com/openharmony/third_party_libuv/wikis/06-Wiki-%E6%8A%80%E6%9C%AF%E8%B5%84%E6%BA%90/QoS%E6%84%9F%E7%9F%A5%E7%9A%84libuv%E3%80%81napi%E5%BC%82%E6%AD%A5%E6%8E%A5%E5%8F%A3%E6%95%B4%E6%94%B9FAQ) 973