How to analyze the stages of idle, check and prepare in libuv
In this issue, the editor will bring you about how to analyze the idle, check and prepare stages of libuv. The article is rich in content and analyzes and narrates it from a professional point of view. I hope you can get something after reading this article.
Idle, check and prepare are the three stages in the libuv event cycle, which mainly take tasks out of their respective queues and have their own corresponding data structures. Nodejs's setImmediate uses these phases.
# include "uv.h"
# include "internal.h"
# define UV_LOOP_WATCHER_DEFINE (name, type)
Int uv_##name##_init (uv_loop_t* loop, uv_##name##_t* handle) {
/ / initialize the type of handle, the loop to which it belongs, type UV_HANDLE_REF, and insert handle into the end of the loop- > handle_queue queue
Uv__handle_init (loop, (uv_handle_t*) handle, UV_##type)
Handle- > name##_cb = NULL
Return 0
}
Int uv_##name##_start (uv_##name##_t* handle, uv_##name##_cb cb) {
/ / return directly if the start function has been executed
If (uv__is_active (handle)) return 0
If (cb = = NULL) return UV_EINVAL
/ / insert handle into the corresponding type of queue in loop. Loop has three queues: prepare,idle and check.
QUEUE_INSERT_HEAD (& handle- > loop- > name##_handles, & handle- > queue)
/ / Mount the callback, which will be executed in the next loop
Handle- > name##_cb = cb
/ / set the UV_HANDLE_ACTIVE flag bit, and add one to the number of handle in the loop. When init, the handle is only active when the handle is mounted to the loop,start.
Uv__handle_start (handle)
Return 0
}
Int uv_##name##_stop (uv_##name##_t* handle) {
If (! uv__is_active (handle)) return 0
/ / remove handle from the corresponding queue in loop, but also mount it to handle_queue
QUEUE_REMOVE (& handle- > queue)
/ / clear the active tag and subtract the number of active of the handle in the loop
Uv__handle_stop (handle)
Return 0
}
/ / execute this function in each loop. For more information, please see uv_run.
Void uv__run_##name (uv_loop_t* loop) {
Uv_##name##_t* h
QUEUE queue
QUEUE* q
/ / remove all the nodes in the queue corresponding to this type and mount them to the queue variable
QUEUE_MOVE (& loop- > name##_handles, & queue)
/ / iterate through the queue and execute the functions in each node
While (! QUEUE_EMPTY (& queue)) {
/ / remove the node currently to be processed
Q = QUEUE_HEAD & queue)
/ / get the base address of the entire structure corresponding to the node
H = QUEUE_DATA (Q, uv_##name##_t, queue)
/ / move the node out of the current queue
QUEUE_REMOVE (Q)
/ / reinsert the original queue
QUEUE_INSERT_TAIL (& loop- > name##_handles, Q)
/ / execute callback function
H-> name##_cb (h)
}
}
Void uv__##name##_close (uv_##name##_t* handle) {
Uv_##name##_stop (handle)
}
UV_LOOP_WATCHER_DEFINE (prepare, PREPARE)
UV_LOOP_WATCHER_DEFINE (check, CHECK)
UV_LOOP_WATCHER_DEFINE (idle, IDLE)
Using the macro definition, it is extended to three different types of code in the preprocessing phase, but with the same processing logic. There are three types, which are prepare,check,idle.
The above is the editor for you to share how to analyze libuv in the idle, check, prepare stage, if you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.