libuv很是高效, 它利用事件驱动/异步IO, 实现线程的高度复用; 好比定时器, 网络传输等, 均可以使用同一个线程来执行. 本文是以unix/core.c为例.linux
int uv_run(uv_loop_t* loop, uv_run_mode mode) { int timeout; int r; int ran_pending; r = uv__loop_alive(loop); if (!r) uv__update_time(loop); //主循环 while (r != 0 && loop->stop_flag == 0) { //获取当前系统时间, linux上调用系统的clock_gettime uv__update_time(loop); //检查定时器是否达到触发条件, 若是须要触发, 将执行timer的回调函数 uv__run_timers(loop); //执行其它的待处理的任务, 好比网络事件, uv__io_poll触发网络事件时, 会将触发的socket存入poll_fds ran_pending = uv__run_pending(loop); //uv__run_idle和uv__run_prepare是用宏定义出来的, IDE没办法直接找到它的定义; //见loop-watcher.c中的#define UV_LOOP_WATCHER_DEFINE(name, type) //监听idle事件和prepare事件, 它们的本质是同样的; 若是设置了这样的事件, 则本循环将一直循环, 不会停顿; uv__run_idle(loop); uv__run_prepare(loop); //计算下一次须要定时的时间; 若是设置了idle或者是prepare事件, 这个值为0, 不然就是timer中最短的那个超时时间 timeout = 0; if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); //linux调用epoll来监听网络事件, 并利用它实现定时 uv__io_poll(loop, timeout); //与uv__run_idle, uv__run_prepare同样的机制, 用的少 uv__run_check(loop); //close的相关操做也能够是异步的. uv__run_closing_handles(loop); if (mode == UV_RUN_ONCE) { /* UV_RUN_ONCE implies forward progress: at least one callback must have * been invoked when it returns. uv__io_poll() can return without doing * I/O (meaning: no callbacks) when its timeout expires - which means we * have pending timers that satisfy the forward progress constraint. * * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from * the check. */ 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; }
在由loop调用的各类回调函数中, 添加或删除定时器, 或建立/销毁新的网络链接, 是安全的. 可是若是在其它的线程中, 直接调用loop的接口, 不是线程安全的, 很是危险. 因此libuv一般的例子是这样的:安全
int main() { loop = uv_default_loop(); //在loop循环以前, 先把各类定时或网络任务设置好. uv_timer_init(loop, &gc_req); uv_unref((uv_handle_t*) &gc_req); uv_timer_start(&gc_req, gc, 0, 2000); // could actually be a TCP download or something uv_timer_init(loop, &fake_job_req); uv_timer_start(&fake_job_req, fake_job, 9000, 0); //各类定时任务初始化完成以后, 再执行loop循环 return uv_run(loop, UV_RUN_DEFAULT); }