好吧,神马都init好了,loop毕竟是个环呐,在哪跑起来呢,ok,他是ev_run的工作:
int ev_run (EV_P_ int flags){#if EV_FEATURE_API ++loop_depth;#endif assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); loop_done = EVBREAK_CANCEL; EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ do {#if EV_VERIFY >= 2 ev_verify (EV_A);#endif#ifndef _WIN32 if (expect_false (curpid)) /* penalise the forking check even more */ if (expect_false (getpid () != curpid)) { curpid = getpid (); postfork = 1; }#endif#if EV_FORK_ENABLE /* we might have forked, so queue fork handlers */ if (expect_false (postfork)) if (forkcnt) { queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK); EV_INVOKE_PENDING; }#endif#if EV_PREPARE_ENABLE /* queue prepare watchers (and execute them) */ if (expect_false (preparecnt)) { queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE); EV_INVOKE_PENDING; }#endif if (expect_false (loop_done)) break; /* we might have forked, so reify kernel state if necessary */ if (expect_false (postfork)) loop_fork (EV_A); /* update fd-related kernel structures */ fd_reify (EV_A); /* calculate blocking time */ { ev_tstamp waittime = 0.; ev_tstamp sleeptime = 0.; /* remember old timestamp for io_blocktime calculation */ ev_tstamp prev_mn_now = mn_now; /* update time to cancel out callback processing overhead */ time_update (EV_A_ 1e100); /* from now on, we want a pipe-wake-up */ pipe_write_wanted = 1; ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) { waittime = MAX_BLOCKTIME; if (timercnt) { ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now; if (waittime > to) waittime = to; }#if EV_PERIODIC_ENABLE if (periodiccnt) { ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now; if (waittime > to) waittime = to; }#endif /* don't let timeouts decrease the waittime below timeout_blocktime */ if (expect_false (waittime < timeout_blocktime)) waittime = timeout_blocktime; /* at this point, we NEED to wait, so we have to ensure */ /* to pass a minimum nonzero value to the backend */ if (expect_false (waittime < backend_mintime)) waittime = backend_mintime; /* extra check because io_blocktime is commonly 0 */ if (expect_false (io_blocktime)) { sleeptime = io_blocktime - (mn_now - prev_mn_now); if (sleeptime > waittime - backend_mintime) sleeptime = waittime - backend_mintime; if (expect_true (sleeptime > 0.)) { ev_sleep (sleeptime); waittime -= sleeptime; } } }#if EV_FEATURE_API ++loop_count;#endif assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ backend_poll (EV_A_ waittime); assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ pipe_write_wanted = 0; /* just an optimisation, no fence needed */ ECB_MEMORY_FENCE_ACQUIRE; if (pipe_write_skipped) { assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); } /* update ev_rt_now, do magic */ time_update (EV_A_ waittime + sleeptime); } /* queue pending timers and reschedule them */ timers_reify (EV_A); /* relative timers called last */#if EV_PERIODIC_ENABLE periodics_reify (EV_A); /* absolute timers called first */#endif#if EV_IDLE_ENABLE /* queue idle watchers unless other events are pending */ idle_reify (EV_A);#endif#if EV_CHECK_ENABLE /* queue check watchers, to be executed first */ if (expect_false (checkcnt)) queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);#endif EV_INVOKE_PENDING; } while (expect_true ( activecnt && !loop_done && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) )); if (loop_done == EVBREAK_ONE) loop_done = EVBREAK_CANCEL;#if EV_FEATURE_API --loop_depth;#endif return activecnt;}
看到了那么多ifdef有木有想shi的赶脚,尼玛。对于win32下,我们来精简下,哈哈:
1 int 2 ev_run (EV_P_ int flags) 3 { 4 assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); 5 6 loop_done = EVBREAK_CANCEL; 7 //激活已经pending的事件 8 EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ 9 10 do 11 { 12 if (expect_false (curpid)) /* penalise the forking check even more */ 13 if (expect_false (getpid () != curpid)) 14 { 15 curpid = getpid (); 16 postfork = 1; 17 } 18 19 if (expect_false (loop_done)) 20 break; 21 22 /* update fd-related kernel structures */ 23 fd_reify (EV_A);//把更改的事件进行更新 24 25 /* calculate blocking time */ 26 { 27 ev_tstamp waittime = 0.; 28 ev_tstamp sleeptime = 0.; 29 30 /* remember old timestamp for io_blocktime calculation */ 31 ev_tstamp prev_mn_now = mn_now; 32 33 /* update time to cancel out callback processing overhead */ 34 time_update (EV_A_ 1e100); 35 36 /* from now on, we want a pipe-wake-up */ 37 pipe_write_wanted = 1; 38 39 ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ 40 41 if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) 42 { 43 waittime = MAX_BLOCKTIME; 44 45 if (timercnt) 46 { 47 ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now; 48 if (waittime > to) waittime = to; 49 } 50 51 /* don't let timeouts decrease the waittime below timeout_blocktime */ 52 if (expect_false (waittime < timeout_blocktime)) 53 waittime = timeout_blocktime; 54 55 /* at this point, we NEED to wait, so we have to ensure */ 56 /* to pass a minimum nonzero value to the backend */ 57 if (expect_false (waittime < backend_mintime)) 58 waittime = backend_mintime; 59 60 /* extra check because io_blocktime is commonly 0 */ 61 if (expect_false (io_blocktime)) 62 { 63 sleeptime = io_blocktime - (mn_now - prev_mn_now); 64 65 if (sleeptime > waittime - backend_mintime) 66 sleeptime = waittime - backend_mintime; 67 68 if (expect_true (sleeptime > 0.)) 69 { 70 ev_sleep (sleeptime); //以上这么大一堆,都是在计算必要的sleep事件,其实就是阻塞嘛 71 waittime -= sleeptime; 72 } 73 } 74 } 75 76 assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ 77 backend_poll (EV_A_ waittime);//这里开始调用上层封装的epool,select进行轮询,收集pending事件 78 assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ 79 80 pipe_write_wanted = 0; /* just an optimisation, no fence needed */ 81 82 ECB_MEMORY_FENCE_ACQUIRE; 83 if (pipe_write_skipped) 84 { 85 assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); 86 ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); 87 } 88 89 90 /* update ev_rt_now, do magic */ 91 time_update (EV_A_ waittime + sleeptime); 92 } 93 94 /* queue pending timers and reschedule them */ 95 timers_reify (EV_A); /* relative timers called last *///对pending的timer事件进行收集 96 97 EV_INVOKE_PENDING; //遍历所有pending事件 98 } 99 while (expect_true (100 activecnt101 && !loop_done102 && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))103 ));104 105 if (loop_done == EVBREAK_ONE)106 loop_done = EVBREAK_CANCEL;107 108 return activecnt;109 }
所有总结下,ev_run是libev的核心,
他主要做了五件事情:
1.更新更改的FD事件
2.进行必要的sleep
3.backend_poll收集pending的IO事件
4.收集pending的timer事件
5.调用所有pending的事件
ok,就是这样了!但是还有很多细节啊,尼玛代码之虐心,非比寻常啊!