回顾昨天提到, 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_14 : 让 Vite 来开启你的Vue 之 Composition API
昨天的内容还可以吸收吗? 也许有人会问: 这些神经网路模型还有GPU、CUDA什麽的我都不懂,能不能...
while 是循环结构(while一定要小写),while 後面搭配布林值(boolean)并用,F...
延续昨天的内容,今天我们要完成写入&读取的功能 将信件内容写入到 Google Sheet ...
继续讲*指标,指标不是只能有一个还能继续层层指下去 #include <stdio.h>...
前言 路由简单来说就是连接介面的桥梁,而这个桥梁就叫做Navigator,就是导航的意思,用於管理进...