前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nodejs事件循环阶段之close

nodejs事件循环阶段之close

作者头像
theanarkh
发布2020-03-16 17:48:34
8820
发布2020-03-16 17:48:34
举报
文章被收录于专栏:原创分享原创分享

close是nodejs每轮事件循环中最后的一个阶段。我们看看怎么使用。我们知道对于一个handle,他的使用一般是init,start,stop。但是如果我们在stop一个handle之后,还有些事情需要处理怎么办?这时候就可以使用close阶段。close阶段可以用来关闭一个handle,并且执行一个回调。比如用于释放动态申请的内存。close阶段的任务由uv_close产生。

代码语言:javascript
复制
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
  // 正在关闭,但是还没执行回调等后置操作
  handle->flags |= UV_HANDLE_CLOSING;
  handle->close_cb = close_cb;

  switch (handle->type) {

  case UV_PREPARE:
    uv__prepare_close((uv_prepare_t*)handle);
    break;

  case UV_CHECK:
    uv__check_close((uv_check_t*)handle);
    break;
    ...
  default:
    assert(0);
  }

  uv__make_close_pending(handle);
}

uv_close设置回调和状态,然后根据handle类型调对应的close函数,一般就是stop这个handle。比如prepare的close函数。

代码语言:javascript
复制
void uv__prepare_close(uv_prepare_t* handle) {                           
    uv_prepare_stop(handle);                                                 
}

接着执行uv__make_close_pending往close队列追加节点。

代码语言:javascript
复制
// 头插法插入closing队列,在closing阶段被执行
void uv__make_close_pending(uv_handle_t* handle) {
  handle->next_closing = handle->loop->closing_handles;
  handle->loop->closing_handles = handle;
}

产生的节点在closing_handles队列中保存,然后在close节点逐个处理。

代码语言:javascript
复制
// 执行closing阶段的的回调
static void uv__run_closing_handles(uv_loop_t* loop) {
  uv_handle_t* p;
  uv_handle_t* q;

  p = loop->closing_handles;
  loop->closing_handles = NULL;

  while (p) {
    q = p->next_closing;
    uv__finish_close(p);
    p = q;
  }
}

// 执行closing阶段的回调
static void uv__finish_close(uv_handle_t* handle) {
  handle->flags |= UV_HANDLE_CLOSED;
  ...
  uv__handle_unref(handle);
  QUEUE_REMOVE(&handle->handle_queue);
  if (handle->close_cb) {
    handle->close_cb(handle);
  }
}

逐个执行回调,close和stop有一点不同的是,stop一个handle,他不会从事件循环中被移除,但是close一个handle,他会从事件循环的handle队列中移除。 我们看一个使用了uv_close的例子(省略部分代码)。

代码语言:javascript
复制
int uv_fs_poll_start(uv_fs_poll_t* handle,
                     uv_fs_poll_cb cb,
                     const char* path,
                     unsigned int interval) {
  struct poll_ctx* ctx;
  // 分配一块堆内存存上下文结构体和path对应的字符串
  ctx = uv__calloc(1, sizeof(*ctx) + len);
  // 挂载上下文到handle
  handle->poll_ctx = ctx;

}

uv_fs_poll_start是用于监听文件是否有改变的函数。他在handle里挂载了一个基于堆结构体。当结束监听的时候,他需要释放掉这块内存。

代码语言:javascript
复制
// 停止poll
int uv_fs_poll_stop(uv_fs_poll_t* handle) {
  struct poll_ctx* ctx;
  ctx = handle->poll_ctx;
  handle->poll_ctx = NULL;
  uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
}

uv_fs_poll_stop通过uv_close函数关闭handle,传的回调是timer_close_cb。

代码语言:javascript
复制
// 释放上下文结构体的内存
static void timer_close_cb(uv_handle_t* handle) {
  uv__free(container_of(handle, struct poll_ctx, timer_handle));
}

所以在close阶段就会是否这块内存。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档