// 处理到时的时间事件和就绪的文件事件
// 如果flags = 0,函数什么都不做,直接返回
// 如果flags设置了 AE_ALL_EVENTS ,则执行所有类型的事件
// 如果flags设置了 AE_FILE_EVENTS ,则执行文件事件
// 如果flags设置了 AE_TIME_EVENTS ,则执行时间事件
// 如果flags设置了 AE_DONT_WAIT ,那么函数处理完事件后直接返回,不阻塞等待
// 函数返回执行的事件个数
int aeProcessEvents(aeEventLoop *eventLoop, int flags)
{
int processed = 0, numevents;
// 如果什么事件都没有设置则直接返回
if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;
// 请注意,既然我们要处理时间事件,即使没有要处理的文件事件,我们仍要调用select(),以便在下一次事件准备启动之前进行休眠
// 当前还没有要处理的文件事件,或者设置了时间事件但是没有设置不阻塞标识
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;
// 获取当前时间
aeGetTime(&now_sec, &now_ms);
tvp = &tv;
// 等待该时间事件到时所需要的时长
long long ms =
(shortest->when_sec - now_sec)*1000 +
shortest->when_ms - now_ms;
// 如果没到时
if (ms > 0) {
// 保存时长到tvp中
tvp->tv_sec = ms/1000;
tvp->tv_usec = (ms % 1000)*1000;
// 如果已经到时,则将tvp的时间设置为0
} else {
tvp->tv_sec = 0;
tvp->tv_usec = 0;
}
// 没有获取到了最早到时的时间事件,时间事件链表为空
} else {
// 如果设置了不阻塞标识
if (flags & AE_DONT_WAIT) {
// 将tvp的时间设置为0,就不会阻塞
tv.tv_sec = tv.tv_usec = 0;
tvp = &tv;
} else {
// 阻塞到第一个时间事件的到来
/* Otherwise we can block */
tvp = NULL; /* wait forever */
}
}
// 等待所监听文件描述符上有事件发生
// 如果tvp为NULL,则阻塞在此,否则等待tvp设置阻塞的时间,就会有时间事件到时
// 返回了就绪文件事件的个数
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;
// 如果是文件可读事件发生
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++; //执行的事件次数加1
}
}
/* Check time events */
// 执行时间事件
if (flags & AE_TIME_EVENTS)
processed += processTimeEvents(eventLoop);
return processed; /* return the number of processed file/time events */
}
|