测试demo
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
void idle_cb(uv_idle_t *handle) {
printf("idle callback\n");
}
int main() {
uv_idle_t idle;
// 初始化
uv_idle_init(uv_default_loop(), &idle);
// 启动,每轮事件循环都会执行 idle_cb
uv_idle_start(&idle, idle_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}
uv_idle_t的数据结构
进入到uv_default_loop()
static uv_loop_t default_loop_struct;
static uv_loop_t* default_loop_ptr;
uv_loop_t* uv_default_loop(void) {
if (default_loop_ptr != NULL)
return default_loop_ptr;
if (uv_loop_init(&default_loop_struct))
return NULL;
default_loop_ptr = &default_loop_struct;
return default_loop_ptr;
}
进入到uv_loop_init并且返回默认的loop,如果执行过了话直接返回
loop结构体
进入到uv_loop_init 初始化loop
int uv_loop_init(uv_loop_t* loop) {
uv__loop_internal_fields_t* lfields;
void* saved_data;
int err;
saved_data = loop->data;
memset(loop, 0, sizeof(*loop));
loop->data = saved_data;
lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields));
if (lfields == NULL)
return UV_ENOMEM;
loop->internal_fields = lfields;
err = uv_mutex_init(&lfields->loop_metrics.lock);
if (err)
goto fail_metrics_mutex_init;
memset(&lfields->loop_metrics.metrics,
0,
sizeof(lfields->loop_metrics.metrics));
heap_init((struct heap*) &loop->timer_heap);
uv__queue_init(&loop->wq);
uv__queue_init(&loop->idle_handles);
uv__queue_init(&loop->async_handles);
uv__queue_init(&loop->check_handles);
uv__queue_init(&loop->prepare_handles);
uv__queue_init(&loop->handle_queue);
loop->active_handles = 0;
loop->active_reqs.count = 0;
loop->nfds = 0;
loop->watchers = NULL;
loop->nwatchers = 0;
uv__queue_init(&loop->pending_queue);
uv__queue_init(&loop->watcher_queue);
loop->closing_handles = NULL;
uv__update_time(loop);
loop->async_io_watcher.fd = -1;
loop->async_wfd = -1;
loop->signal_pipefd[0] = -1;
loop->signal_pipefd[1] = -1;
loop->backend_fd = -1;
loop->emfile_fd = -1;
loop->timer_counter = 0;
loop->stop_flag = 0;
err = uv__platform_loop_init(loop);
if (err)
goto fail_platform_init;
uv__signal_global_once_init();
err = uv__process_init(loop);
if (err)
goto fail_signal_init;
uv__queue_init(&loop->process_handles);
err = uv_rwlock_init(&loop->cloexec_lock);
if (err)
goto fail_rwlock_init;
err = uv_mutex_init(&loop->wq_mutex);
if (err)
goto fail_mutex_init;
err = uv_async_init(loop, &loop->wq_async, uv__work_done);
if (err)
goto fail_async_init;
uv__handle_unref(&loop->wq_async);
loop->wq_async.flags |= UV_HANDLE_INTERNAL;
return 0;
fail_async_init:
uv_mutex_destroy(&loop->wq_mutex);
fail_mutex_init:
uv_rwlock_destroy(&loop->cloexec_lock);
fail_rwlock_init:
uv__signal_loop_cleanup(loop);
fail_signal_init:
uv__platform_loop_delete(loop);
fail_platform_init:
uv_mutex_destroy(&lfields->loop_metrics.lock);
fail_metrics_mutex_init:
uv__free(lfields);
loop->internal_fields = NULL;
uv__free(loop->watchers);
loop->nwatchers = 0;
return err;
}
这次主要分析idle队列,着重看下面几个
// ...
uv__queue_init(&loop->idle_handles);
// ...
uv__queue_init(&loop->handle_queue);
// ...
err = uv_async_init(loop, &loop->wq_async, uv__work_done);
q就是队列的指针,队列的第一个元素指向队列的指针
static inline void uv__queue_init(struct uv__queue* q) {
q->next = q;
q->prev = q;
}
queue结构体如下
struct uv__queue {
struct uv__queue* next;
struct uv__queue* prev;
};
idle_handles队列的指针&loop->idle_handles = 0x00000001000794d8
handle_queue队列的指针&loop->handle_queue = 0x00000001000792a0
err = uv_async_init(loop, &loop->wq_async, uv__work_done);
这句涉及到异步,具体先略过,它对loop->handle_queue的影响是将wq_async->handle_queue插入到loop->handle_queue的头之前
wq_async->handle_queue队列的指针&loop->wq_async->handle_queue = 0x0000000100079378
uv_default_loop初始化完了, 下面执行uv_idle_init
idle_handle结构体
int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \
uv__handle_init(loop, (uv_handle_t*)handle, UV_##type); \
handle->name##_cb = NULL; \
return 0; \
}
#define uv__handle_init(loop_, h, type_) \
do { \
(h)->loop = (loop_); \
(h)->type = (type_); \
(h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \
uv__queue_insert_tail(&(loop_)->handle_queue, &(h)->handle_queue); \
uv__handle_platform_init(h); \
} \
while (0)
static inline void uv__queue_insert_tail(struct uv__queue* h,
struct uv__queue* q) {
q->next = h;
q->prev = h->prev;
q->prev->next = q;
h->prev = q;
}
这步会像uv_async_init一样,把idle_handle->handle_queue
插入到loop->handle_queue
因此,loop->handle_queue循环队列中有
- loop->handle_queue的指针
- wq_async->handle_queue的指针
- idle_handle->handle_queue的指针
进入到
v_idle_start(&idle, idle_cb);
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
if (cb == NULL) return UV_EINVAL; \
uv__queue_insert_head(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
return 0; \
}
h是loop->idle_handles, q是idle_handle->queue,不要弄混了
static inline void uv__queue_insert_head(struct uv__queue* h,
struct uv__queue* q) {
q->next = h->next;
q->prev = h;
q->next->prev = q;
h->next = q;
}
这是把idle_handle->queue插入到loop->idle_handles头之后 loop->idle_handles循环队列内容
- loop->idle_handles的指针
- idle_handle->queue的指针
之后启动
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
因为loop已经定义过了,uv_default_loop()直接返回定义过的loop
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
int timeout;
int r;
int can_sleep;
r = uv__loop_alive(loop);
if (!r)
uv__update_time(loop);
/* Maintain backwards compatibility by processing timers before entering the
* while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed
* once, which should be done after polling in order to maintain proper
* execution order of the conceptual event loop. */
if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
}
while (r != 0 && loop->stop_flag == 0) {
can_sleep =
uv__queue_empty(&loop->pending_queue) &&
uv__queue_empty(&loop->idle_handles);
uv__run_pending(loop);
uv__run_idle(loop);
uv__run_prepare(loop);
timeout = 0;
if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
timeout = uv__backend_timeout(loop);
uv__metrics_inc_loop_count(loop);
uv__io_poll(loop, timeout);
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
* times to avoid loop starvation.*/
for (r = 0; r < 8 && !uv__queue_empty(&loop->pending_queue); r++)
uv__run_pending(loop);
/* Run one final update on the provider_idle_time in case uv__io_poll
* returned because the timeout expired, but no events were received. This
* call will be ignored if the provider_entry_time was either never set (if
* the timeout == 0) or was already updated b/c an event was received.
*/
uv__metrics_update_idle_time(loop);
uv__run_check(loop);
uv__run_closing_handles(loop);
uv__update_time(loop);
uv__run_timers(loop);
r = uv__loop_alive(loop);
if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
/* The if statement lets gcc compile it to a conditional store. Avoids
* dirtying a cache line.
*/
if (loop->stop_flag != 0)
loop->stop_flag = 0;
return r;
}
这次只看uv__run_idle(loop);
void uv__run_##name(uv_loop_t* loop) { \
uv_##name##_t* h; \
struct uv__queue queue; \
struct uv__queue* q; \
uv__queue_move(&loop->name##_handles, &queue); \
while (!uv__queue_empty(&queue)) { \
q = uv__queue_head(&queue); \
h = uv__queue_data(q, uv_##name##_t, queue); \
uv__queue_remove(q); \
uv__queue_insert_tail(&loop->name##_handles, q); \
h->name##_cb(h); \
} \
}
static inline void uv__queue_move(struct uv__queue* h, struct uv__queue* n) {
if (uv__queue_empty(h))
uv__queue_init(n);
else
uv__queue_split(h, h->next, n);
}
loop->idle_handles不是空的
h是loop->idle_handles
q是loop->idle_handles->next
n是新定义的空队列
static inline void uv__queue_split(struct uv__queue* h,
struct uv__queue* q,
struct uv__queue* n) {
n->prev = h->prev;
n->prev->next = n;
n->next = q;
h->prev = q->prev;
h->prev->next = h;
q->prev = n;
}
loop->idle_handles被排除在队列外面了,新队列queue代替了loop->idle_handles的位置
进入到while循环
while (!uv__queue_empty(&queue)) { \
q = uv__queue_head(&queue); \
h = uv__queue_data(q, uv_##name##_t, queue); \
uv__queue_remove(q); \
uv__queue_insert_tail(&loop->name##_handles, q); \
h->name##_cb(h); \
}
q就是idle_handle->queue的指针
static inline struct uv__queue* uv__queue_head(const struct uv__queue* q) {
return q->next;
}
根据queue在结构体uv_idle_t中的位置以及idle_handle的指针,能推断出idle_handle的全部信息
h = uv__queue_data(q, uv_idle_t, queue);
#define uv__queue_data(pointer, type, field) \
((type*) ((char*) (pointer) - offsetof(type, field)))
将idle_handle从队列中排除
static inline void uv__queue_remove(struct uv__queue* q) {
q->prev->next = q->next;
q->next->prev = q->prev;
}
然后将idle_handle放回到loop->idle_handles
最后调用
h->name##_cb(h);
执行demo中的cb
void idle_cb(uv_idle_t *handle) {
printf("idle callback\n");
}
由于最后uv__queue_insert_tail把idle_handle重新放入loop->idle_handles队列之中,所以目前会一直执行这个回调