事件处理其实很简单,下面这个函数
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 送女儿回家(如果上学)