[Day 26] Node thread pool 1

前言

回顾昨天提到, pending 阶段处理 polling 得来的事件, 且调用特定的 callback 。

大家对 pending stage 的各种 case 调用的回调可以稍微研究一下, 会发现 2 种 case 。

一种是 cb (一般回调), 一种是 async_cb (非同步回调)。其中我们知道 cb 是直接接着执行, 那 async_cb 是甚麽呢 ?

导引

查看 uv_process_async_wakeup_req , 这是昨天提到的 pending stage 之一

void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
    uv_req_t* req) {
  assert(handle->type == UV_ASYNC);
  assert(req->type == UV_WAKEUP);

  handle->async_sent = 0;

  if (handle->flags & UV_HANDLE_CLOSING) {
    uv_want_endgame(loop, (uv_handle_t*)handle);
  } else if (handle->async_cb != NULL) {
    handle->async_cb(handle);
  }
}

可以看到 handle->async_cb(handle); 我们接下来的任务就是看看 async_cb 在干啥

https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/deps/uv/src/win/async.c

正文

查看 uv_async_init ,

它的作用是把 callback 设定进 handle 中, 这样在 polling stage 才有 callback 触发

int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
  uv_req_t* req;
	// 把 handle 加入 handle queue
  uv__handle_init(loop, (uv_handle_t*) handle, UV_ASYNC);
	// 标示任务未完成
  handle->async_sent = 0;
	// 设定 handle 的 callback
  handle->async_cb = async_cb;

  req = &handle->async_req;
  UV_REQ_INIT(req, UV_WAKEUP);
  req->data = handle;

  uv__handle_start(handle);

  return 0;
}

其中 async_sent = 0; 表示任务未完成

查看 uv_async_send 它的作用是使 main thread 可以得知该任务完成

int uv_async_send(uv_async_t* handle) {
  uv_loop_t* loop = handle->loop;

  if (handle->type != UV_ASYNC) {
    /* Can't set errno because that's not thread-safe. */
    return -1;
  }

  /* The user should make sure never to call uv_async_send to a closing or
   * closed handle. */
  assert(!(handle->flags & UV_HANDLE_CLOSING));
	// atomic 的把 async_sent 设为 1
  if (!uv__atomic_exchange_set(&handle->async_sent)) {
    POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
  }

  return 0;
}

uv__atomic_exchange_set(&handle->async_sent) 把 async_sent 设为 1 , 表示任务完成

最後看 uv_async_endgame

这是 uv_run 这个循环的最後一个阶段 ( endgame stage ) 中调用的方法, 会检查 handle 中的 async_sent , 如果该任务已经完成就会把任务移出 handle queue。

void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
  if (handle->flags & UV_HANDLE_CLOSING &&
      !handle->async_sent) {
    assert(!(handle->flags & UV_HANDLE_CLOSED));
    uv__handle_close(handle);
  }
}

整理

我们发现 async_cb 是被 uv_async_init 设定到 handle 物件中的, 这里的 handle 是被放进 pending queue 的任务

另外, handle 中有一个值 async_sent 会被设为 0 , 当 handle 被 thread pool 完成时会调用 uv_async_send 方法把 async_sent 设为 1 使 main thread 在 endgame stage 藉由调用 uv_async_endgame 得知该非同步任务完成 , 所以调用结束该任务的方法。

上面所用的方法算是非常重要, 因为这正是 Node 中 threadpool 向 main thread 通讯的方法。

明天进度

聊聊 TP 的创建, 和 TP 运行的方法

明天见 !


<<:  Day 12:Commitizen

>>:  Day_14 : 让 Vite 来开启你的Vue 之 Composition API

[Day 21] Facial Recognition: 只需要OpenCV就可以达成即时人脸辨识

昨天的内容还可以吸收吗? 也许有人会问: 这些神经网路模型还有GPU、CUDA什麽的我都不懂,能不能...

Python入门 Day 6 : # While True的用法

while 是循环结构(while一定要小写),while 後面搭配布林值(boolean)并用,F...

利用 Google App Script 将资料存到 Google Sheet(2)

延续昨天的内容,今天我们要完成写入&读取的功能 将信件内容写入到 Google Sheet ...

Day19-多重指标

继续讲*指标,指标不是只能有一个还能继续层层指下去 #include <stdio.h>...

Day 25路由

前言 路由简单来说就是连接介面的桥梁,而这个桥梁就叫做Navigator,就是导航的意思,用於管理进...