今天的內容是整理整個 threadpool (TP) 的調用過程
在 pending 階段當遇到 async 類型的任務會執行以下這段
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);
}
}
我們等下來看看 async_cb 是調用了甚麼方法
回去翻原始碼, 選了其中一種 case , 以下假設 async_cb 調用的是以下方法
void uv__work_done(uv_async_t* handle) {
struct uv__work* w;
uv_loop_t* loop;
QUEUE* q;
QUEUE wq;
int err;
loop = container_of(handle, uv_loop_t, wq_async);
uv_mutex_lock(&loop->wq_mutex);
QUEUE_MOVE(&loop->wq, &wq);
uv_mutex_unlock(&loop->wq_mutex);
while (!QUEUE_EMPTY(&wq)) {
q = QUEUE_HEAD(&wq);
QUEUE_REMOVE(q);
w = container_of(q, struct uv__work, wq);
err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
w->done(w, err);
}
}
其內容是讀取 work queue 中由 TP 完成 IO 的任務, 繼續接下去把當初在上層設置的 callback 跑完。
node 的 threadpool 機制可以稱得上是十分複雜, 在探索的過程中, 有部分我也看得不是很懂, 也有因為篇幅問題做一些省略, 接著我試著用我個人的理解大概講述一下 node 的 threadpool。
首先要理解 threadpool 執行的不是我們在 JS 層直接撰寫的程式碼, 其主要目的是處理 IO 的等待時間還有做基本的資料搬運。
舉個簡單的例子, 當 node 要讀取一張圖片且進行修圖需要經過幾個動作。
TP 能處理的就是步驟 1,2,4 。第3步會在 main thread 的 pending stage 執行。
所以我們可以認知 node 的 TP 是專門平行化特定任務 ( AIO ) 的。
接著我們按照步驟來講講 threadpool 的運行吧
今天聊完了 Node , 我明天會為這段時間 Node 的內容作些整理。
明天見 !