Open xiaoxiaojx opened 2 years ago
不常见 api 偶尔在某些库中看到有使用, 只能回头看看 uv 代码与文档。隔一阵子又忘记了, 于是决定记录一下 📝
// demo
int err = uv_async_init(uv_default_loop(), &(l->async), (uv_async_cb) fuse_native_dispatch); assert(err >= 0);
uv_unref((uv_handle_t *) &(l->async));
在 uv 代码中看到 uv_unref 其实是把当前的活跃句柄给减 1, 活跃句柄的数量是决定事件循环是否继续 uv__loop_alive 判断的条件之一, 所以如果当前任务是事件循环中剩下的最后一个任务时, 则事件循环可以不用考虑该任务, 直接进入退出程序。 为什么少见 uv_ref 的调用, 可以认为 uv_async_init 等操作中已经包含了给活跃句柄加 1 的功能。 ```c // uv 实现 void uv_unref(uv_handle_t* handle) { uv__handle_unref(handle); } #define uv__handle_unref(h) \ do { \ if (((h)->flags & UV_HANDLE_REF) == 0) break; \ (h)->flags &= ~UV_HANDLE_REF; \ if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \ if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ } \ while (0) static int uv__loop_alive(const uv_loop_t* loop) { return uv__has_active_handles(loop) || uv__has_active_reqs(loop) || loop->closing_handles != NULL; }
// demo void on_close(uv_handle_t *handle) { delete handle; } void cleanup(void* data) { uv_close((uv_handle_t *)data, on_close); } void Start(const Napi::CallbackInfo &args) { Napi::Env env = args.Env(); uv_loop_t *loop; v8::Isolate* isolate = v8::Isolate::GetCurrent(); napi_get_uv_event_loop(env, &loop); uv_prepare_t* prepare_handle = new uv_prepare_t; uv_prepare_init(loop, prepare_handle); uv_unref((uv_handle_t *)prepare_handle); uv_prepare_start(prepare_handle, [](uv_prepare_t *handle) {}); node::AddEnvironmentCleanupHook(isolate, cleanup, prepare_handle); }
可以使用 uvclose 轻易代替 uv##name##close / uv##name##_stop, 通过如下 uv_close 的实现可知
// uv 实现
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { assert(!uv__is_closing(handle));
handle->flags |= UV_HANDLE_CLOSING; handle->close_cb = close_cb;
switch (handle->type) { case UV_NAMED_PIPE: uv__pipe_close((uv_pipe_t*)handle); break;
case UV_TTY: uv__stream_close((uv_stream_t*)handle); break;
case UV_TCP: uv__tcp_close((uv_tcp_t*)handle); break;
case UV_UDP: uv__udp_close((uv_udp_t*)handle); break;
case UV_PREPARE: uv__prepare_close((uv_prepare_t*)handle); break;
case UV_CHECK: uv__check_close((uv_check_t*)handle); break;
case UV_IDLE: uv__idle_close((uv_idle_t*)handle); break;
case UV_ASYNC: uv__async_close((uv_async_t*)handle); break;
case UV_TIMER: uv__timer_close((uv_timer_t*)handle); break;
case UV_PROCESS: uv__process_close((uv_process_t*)handle); break;
case UV_FS_EVENT: uv__fs_event_close((uv_fs_event_t*)handle); break;
case UV_POLL: uv__poll_close((uv_poll_t*)handle); break;
case UV_FS_POLL: uv__fs_poll_close((uv_fs_poll_t)handle); / Poll handles use file system requests, and one of them may still be
running. The poll code will call uv__make_close_pending() for us. */ return;
case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); break;
default: assert(0); }
uv__make_close_pending(handle); }
最终是调用 tcgetattr 函数与 tcsetattr 函数控制终端。 如果在某处通过 uv_tty_set_mode 修改了终端参数, 此处用于复原。
// src/node.cc void ResetStdio() { uv_tty_reset_mode(); #ifdef __POSIX__ for (auto& s : stdio) { const int fd = &s - stdio; struct stat tmp; if (-1 == fstat(fd, &tmp)) { CHECK_EQ(errno, EBADF); // Program closed file descriptor. continue; } } #endif // __POSIX__ }
释放 uv 持有的任何全局状态。 uv 通常会在卸载时自动执行此操作,但可以指示它手动执行清理。调用 uv_library_shutdown() 后不能继续调用 uv 函数
uv_unref
int err = uv_async_init(uv_default_loop(), &(l->async), (uv_async_cb) fuse_native_dispatch); assert(err >= 0);
uv_unref((uv_handle_t *) &(l->async));
uv_close
可以使用 uvclose 轻易代替 uv##name##close / uv##name##_stop, 通过如下 uv_close 的实现可知
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { assert(!uv__is_closing(handle));
handle->flags |= UV_HANDLE_CLOSING; handle->close_cb = close_cb;
switch (handle->type) { case UV_NAMED_PIPE: uv__pipe_close((uv_pipe_t*)handle); break;
case UV_TTY: uv__stream_close((uv_stream_t*)handle); break;
case UV_TCP: uv__tcp_close((uv_tcp_t*)handle); break;
case UV_UDP: uv__udp_close((uv_udp_t*)handle); break;
case UV_PREPARE: uv__prepare_close((uv_prepare_t*)handle); break;
case UV_CHECK: uv__check_close((uv_check_t*)handle); break;
case UV_IDLE: uv__idle_close((uv_idle_t*)handle); break;
case UV_ASYNC: uv__async_close((uv_async_t*)handle); break;
case UV_TIMER: uv__timer_close((uv_timer_t*)handle); break;
case UV_PROCESS: uv__process_close((uv_process_t*)handle); break;
case UV_FS_EVENT: uv__fs_event_close((uv_fs_event_t*)handle); break;
case UV_POLL: uv__poll_close((uv_poll_t*)handle); break;
case UV_FS_POLL: uv__fs_poll_close((uv_fs_poll_t)handle); / Poll handles use file system requests, and one of them may still be
running. The poll code will call uv__make_close_pending() for us. */ return;
case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); break;
default: assert(0); }
uv__make_close_pending(handle); }
uv_tty_reset_mode
最终是调用 tcgetattr 函数与 tcsetattr 函数控制终端。 如果在某处通过 uv_tty_set_mode 修改了终端参数, 此处用于复原。
uv_library_shutdown
释放 uv 持有的任何全局状态。 uv 通常会在卸载时自动执行此操作,但可以指示它手动执行清理。调用 uv_library_shutdown() 后不能继续调用 uv 函数