redis 事件處理
阿新 • • 發佈:2019-01-24
事件處理其實很簡單,下面這個函式
403 //主函式 404 void aeMain(aeEventLoop *eventLoop) { 405 eventLoop->stop = 0; 406 while (!eventLoop->stop) { 407 if (eventLoop->beforesleep != NULL) 408 eventLoop->beforesleep(eventLoop); 409 aeProcessEvents(eventLoop, AE_ALL_EVENTS); 410 } 411 }
就是不斷的迴圈,呼叫 aeProcessEvents.
aeProcessEvents:
這個函式就是處理事件的,包括了時間事件和檔案事件。
int aeProcessEvents(aeEventLoop *eventLoop, int flags) { int processed = 0, numevents; /* Nothing to do? return ASAP */ if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0; /* Note that we want call select() even if there are no * file events to process as long as we want to process time * events, in order to sleep until the next time event is ready * to fire. */ //即使沒有檔案事件,只要有時間事件(並且 AE_DONT_WAIT), 也計算等待時間 if (eventLoop->maxfd != -1 || ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) { int j; aeTimeEvent *shortest = NULL; struct timeval tv, *tvp; //查詢和現在最近的事件 if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT)) shortest = aeSearchNearestTimer(eventLoop); if (shortest) { //最早觸發事件的時間 long now_sec, now_ms; /* Calculate the time missing for the nearest * timer to fire. */ aeGetTime(&now_sec, &now_ms); tvp = &tv; tvp->tv_sec = shortest->when_sec - now_sec; //計算時間差值,微妙不夠,從秒這裡拿1 if (shortest->when_ms < now_ms) { tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000; tvp->tv_sec --; } else { tvp->tv_usec = (shortest->when_ms - now_ms)*1000; } //最早觸發時間已經過了,那就不需要等了 if (tvp->tv_sec < 0) tvp->tv_sec = 0; if (tvp->tv_usec < 0) tvp->tv_usec = 0; } else { /* If we have to check for events but need to return * ASAP because of AE_DONT_WAIT we need to se the timeout * to zero */ if (flags & AE_DONT_WAIT) { tv.tv_sec = tv.tv_usec = 0; tvp = &tv; } else { /* Otherwise we can block */ tvp = NULL; /* wait forever */ } } //從上面計算的到在這裡阻塞的時間 numevents = aeApiPoll(eventLoop, tvp); for (j = 0; j < numevents; j++) { aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd]; int mask = eventLoop->fired[j].mask; int fd = eventLoop->fired[j].fd; int rfired = 0; /* note the fe->mask & mask & ... code: maybe an already processed * event removed an element that fired and we still didn't * processed, so we check if the event is still valid. */ if (fe->mask & mask & AE_READABLE) { rfired = 1; fe->rfileProc(eventLoop,fd,fe->clientData,mask); } if (fe->mask & mask & AE_WRITABLE) { if (!rfired || fe->wfileProc != fe->rfileProc) fe->wfileProc(eventLoop,fd,fe->clientData,mask); } processed++; } } /* Check time events */ if (flags & AE_TIME_EVENTS) processed += processTimeEvents(eventLoop); return processed; /* return the number of processed file/time events */ }
我們可以把主程式當作是一個開車的父親,時間事件是接女兒放學,檔案事件是去車站接客人賺錢。
那麼AE_DONT_WAIT可以理解為不能在車站停靠。
1 首先決定是否需要計算在車站等待時間:
if (eventLoop->maxfd != -1 ||
((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT)))
需要滿足下面任何一個條件:
一 有客人會出現
二 今天要去接女兒 並且 車站允許停靠車子
2 計算女兒放學時間:
如果今天上學,
那麼就得到放學時間,和當前時間比較,如果還沒有到,那麼再等等,到了就不要等了
如果不上學,那麼就只要處理乘客,如果車站不讓聽,馬上走,如果給停,一定等待乘客出現
3 把乘客送過去(如果有)
4 送女兒回家(如果上學)