| // 处理到时的时间事件和就绪的文件事件
 // 如果flags = 0,函数什么都不做,直接返回
 // 如果flags设置了 AE_ALL_EVENTS ,则执行所有类型的事件
 // 如果flags设置了 AE_FILE_EVENTS ,则执行文件事件
 // 如果flags设置了 AE_TIME_EVENTS ,则执行时间事件
 // 如果flags设置了 AE_DONT_WAIT ,那么函数处理完事件后直接返回,不阻塞等待
 // 函数返回执行的事件个数
 intaeProcessEvents(aeEventLoop *eventLoop, intflags)
 {
     intprocessed = 0, numevents;
     // 如果什么事件都没有设置则直接返回
     if(!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return0;
     // 请注意,既然我们要处理时间事件,即使没有要处理的文件事件,我们仍要调用select(),以便在下一次事件准备启动之前进行休眠
     // 当前还没有要处理的文件事件,或者设置了时间事件但是没有设置不阻塞标识
     if(eventLoop->maxfd != -1 ||
         ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
         intj;
         aeTimeEvent *shortest = NULL;
         structtimeval tv, *tvp;
         // 如果设置了时间事件而没有设置不阻塞标识
         if(flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))
             // 获取最近到时的时间事件
             shortest = aeSearchNearestTimer(eventLoop);
         // 获取到了最早到时的时间事件
         if(shortest) {
             longnow_sec, now_ms;
             // 获取当前时间
             aeGetTime(&now_sec, &now_ms);
             tvp = &tv;
             // 等待该时间事件到时所需要的时长
             longlongms =
                 (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];
             // 获取就绪文件事件的类型,文件描述符
             intmask = eventLoop->fired[j].mask;
             intfd = eventLoop->fired[j].fd;
             intrfired = 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);
     returnprocessed; /* return the number of processed file/time events */
 }
 |