1.redis所有事件都被保存在一个aeEventLoop的结构中,一类是文件事件,另一类是时间事件
/* 文件事件 */
typedef struct aeFileEvent {
int mask; /* 事件的状态,读事件,写事件 */
aeFileProc *rfileProc;//读事件发生时要执行的读操作
aeFileProc *wfileProc;//写事件触发时要执行的写操作
void *clientData;//本事件关联的数据
} aeFileEvent;
/* 时间事件 */
typedef struct aeTimeEvent {
long long id; /* 事件id */
long when_sec; /* 事件发生的秒 */
long when_ms; /* 事件发生时的毫秒*/
aeTimeProc *timeProc;//事件触发时要执行的操作
aeEventFinalizerProc *finalizerProc;
void *clientData;//本事件关联的数据
struct aeTimeEvent *next;
} aeTimeEvent;
/* 已就绪的事件 */
typedef struct aeFiredEvent {
int fd;
int mask;
} aeFiredEvent;
/* 事件池结构 */
typedef struct aeEventLoop {
int maxfd; /* 当前已注册的最大文件描述符 */
int setsize; /* max number of file descriptors tracked */
long long timeEventNextId;
time_t lastTime; /* Used to detect system clock skew */
aeFileEvent *events; /* Registered events */
aeFiredEvent *fired; /* Fired events */
aeTimeEvent *timeEventHead;
int stop;
void *apidata; /* This is used for polling API specific data */
aeBeforeSleepProc *beforesleep;
} aeEventLoop;
2.ae.c源码注释
//创建一个事件池结构,
aeEventLoop *aeCreateEventLoop(int setsize/*事件的数量*/) {
aeEventLoop *eventLoop;
int i;
if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;
eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);
if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;
eventLoop->setsize = setsize;
eventLoop->lastTime = time(NULL);
eventLoop->timeEventHead = NULL;
eventLoop->timeEventNextId = 0;
eventLoop->stop = 0;
eventLoop->maxfd = -1;
eventLoop->beforesleep = NULL;
if (aeApiCreate(eventLoop) == -1) goto err;
/* Events with mask == AE_NONE are not set. So let's initialize the
* vector with it. */
for (i = 0; i < setsize; i++)
eventLoop->events[i].mask = AE_NONE;//刚开始每一个文件事件的状态都是ae_none
return eventLoop;
err:
if (eventLoop) {
zfree(eventLoop->events);
zfree(eventLoop->fired);
zfree(eventLoop);
}
return NULL;
}
//获取当前事件池的大小
int aeGetSetSize(aeEventLoop *eventLoop) {
return eventLoop->setsize;
}
//重新设置事件池的大小
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize) {
int i;
if (setsize == eventLoop->setsize) return AE_OK;
if (eventLoop->maxfd >= setsize) return AE_ERR;//不可以缩小,只能增大
if (aeApiResize(eventLoop,setsize) == -1) return AE_ERR;
eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent)*setsize);//重新分配内存
eventLoop->fired = zrealloc(eventLoop->fired,sizeof(aeFiredEvent)*setsize);
eventLoop->setsize = setsize;
//重新设置事件的状态为不读不写
for (i = eventLoop->maxfd+1; i < setsize; i++)
eventLoop->events[i].mask = AE_NONE;
return AE_OK;
}
//回收事件池的内存
void aeDeleteEventLoop(aeEventLoop *eventLoop) {
aeApiFree(eventLoop);
zfree(eventLoop->events);
zfree(eventLoop->fired);
zfree(eventLoop);
}
//设置事件池的状态为停止工作
void aeStop(aeEventLoop *eventLoop) {
eventLoop->stop = 1;
}
//给文件描述符创建一个文件事件,
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask/*事件的状态*/,
aeFileProc *proc/*事件的操作*/, void *clientData/*事件对应的数据*/)
{
if (fd >= eventLoop->setsize) {//如果文件描述符超出事件池的最大值,则报错
errno = ERANGE;
return AE_ERR;
}
aeFileEvent *fe = &eventLoop->events[fd];//找到文件描述符fd在事件池中对应的文件结构
if (aeApiAddEvent(eventLoop, fd, mask) == -1)//向系统底层注册事件
return AE_ERR;
fe->mask |= mask;//给事件添加状态
//给事件添加相关的操作
if (mask & AE_READABLE) fe->rfileProc = proc;
if (mask & AE_WRITABLE) fe->wfileProc = proc;
fe->clientData = clientData;
if (fd > eventLoop->maxfd)//记录当前最大的文件描述符
eventLoop->maxfd = fd;
return AE_OK;
}
//删除一个文件事件
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
{
if (fd >= eventLoop->setsize) return;
aeFileEvent *fe = &eventLoop->events[fd];//找到文件描述符fd在事件池中对应的文件结构
if (fe->mask == AE_NONE) return;//如果不是读或写事件,则无需删除
aeApiDelEvent(eventLoop, fd, mask);//从系统层删除
fe->mask = fe->mask & (~mask);//删除事件标记
if (fd == eventLoop->maxfd && fe->mask == AE_NONE) {
/* 更新已注册事件的最大文件描述符 */
int j;
for (j = eventLoop->maxfd-1; j >= 0; j--)
if (eventLoop->events[j].mask != AE_NONE) break;
eventLoop->maxfd = j;
}
}
//获取文件事件的掩码
int aeGetFileEvents(aeEventLoop *eventLoop, int fd) {
if (fd >= eventLoop->setsize) return 0;
aeFileEvent *fe = &eventLoop->events[fd];
return fe->mask;
}
//获取当前秒和毫秒
static void aeGetTime(long *seconds, long *milliseconds)
{
struct timeval tv;
gettimeofday(&tv, NULL);//获取当前的时间
*seconds = tv.tv_sec;
*milliseconds = tv.tv_usec/1000;
}
//给sec(秒)和ms(毫秒)赋值当前时间加上一段时间
static void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {
long cur_sec, cur_ms, when_sec, when_ms;
aeGetTime(&cur_sec, &cur_ms);
when_sec = cur_sec + milliseconds/1000;
when_ms = cur_ms + milliseconds%1000;
if (when_ms >= 1000) {
when_sec ++;
when_ms -= 1000;
}
*sec = when_sec;
*ms = when_ms;
}
//创建一个时间事件
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
aeTimeProc *proc, void *clientData,
aeEventFinalizerProc *finalizerProc)
{
long long id = eventLoop->timeEventNextId++;//算出当前时间事件的下一个id
aeTimeEvent *te;
te = zmalloc(sizeof(*te));
if (te == NULL) return AE_ERR;
te->id = id;
//在当前时间基础上加上milliseconds毫秒,赋值给te->when_sec, te->when_ms
aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);
te->timeProc = proc;//时间事件触发时的操作
te->finalizerProc = finalizerProc;//回收操作
te->clientData = clientData;//对应的数据
te->next = eventLoop->timeEventHead;//时间事件是一个单向链表,
eventLoop->timeEventHead = te;
return id;
}
//删除编号为id的时间事件,遍历一次时间事件的单链表,对比id,然后删除之
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)
{
aeTimeEvent *te = eventLoop->timeEventHead;
while(te) {
if (te->id == id) {
te->id = AE_DELETED_EVENT_ID;
return AE_OK;
}
te = te->next;
}
return AE_ERR; /* NO event with the specified ID found */
}
//找出最接近当前时间的时间事件
static aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)
{
aeTimeEvent *te = eventLoop->timeEventHead;
aeTimeEvent *nearest = NULL;
while(te) {
if (!nearest || te->when_sec < nearest->when_sec ||
(te->when_sec == nearest->when_sec &&
te->when_ms < nearest->when_ms))
nearest = te;
te = te->next;
}
return nearest;
}
/* 执行时间事件 */
static int processTimeEvents(aeEventLoop *eventLoop) {
int processed = 0;
aeTimeEvent *te, *prev;
long long maxId;
time_t now = time(NULL);
if (now < eventLoop->lastTime) {//如果系统管理员调整时间到未来又调回来了
te = eventLoop->timeEventHead;
while(te) {
te->when_sec = 0;
te = te->next;
}
}
eventLoop->lastTime = now;//保存上一次执行时间为现在
prev = NULL;
te = eventLoop->timeEventHead;
maxId = eventLoop->timeEventNextId-1;
while(te) {
long now_sec, now_ms;
long long id;
/* //删除带删除标记的时间事件 */
if (te->id == AE_DELETED_EVENT_ID) {
aeTimeEvent *next = te->next;
if (prev == NULL)
eventLoop->timeEventHead = te->next;
else
prev->next = te->next;
if (te->finalizerProc)//执行回收事件
te->finalizerProc(eventLoop, te->clientData);
zfree(te);
te = next;
continue;
}
//对未来事件的保护
if (te->id > maxId) {
te = te->next;
continue;
}
aeGetTime(&now_sec, &now_ms);//取当前时间
if (now_sec > te->when_sec ||//如果当前时间超过时间事件的时间,则执行之
(now_sec == te->when_sec && now_ms >= te->when_ms))
{
int retval;
id = te->id;
retval = te->timeProc(eventLoop, id, te->clientData);
processed++;//计数器
if (retval != AE_NOMORE) {//如果时间事件执行后返回的不是AE_NOMORE,表示该事件可以重复执行,则继续将该事件加入时间事件链表,否则将其id设置为删除标记的id
aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
} else {
te->id = AE_DELETED_EVENT_ID;
}
}
prev = te;
te = te->next;
}
return processed;
}
//执行事件
int aeProcessEvents(aeEventLoop *eventLoop, int flags/*文件或时间事件*/)
{
int processed = 0, numevents;
/* 如果不是文件或时间事件,则结束 */
if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;
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->tv_sec = ms/1000;
tvp->tv_usec = (ms % 1000)*1000;
} else {
tvp->tv_sec = 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 set 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;
/* 执行对应的读事件和写事件 */
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++;
}
}
/* 执行时间事件 */
if (flags & AE_TIME_EVENTS)
processed += processTimeEvents(eventLoop);
return processed; /* return the number of processed file/time events */
}
/* Wait for milliseconds until the given file descriptor becomes
* writable/readable/exception */
int aeWait(int fd, int mask, long long milliseconds) {
struct pollfd pfd;
int retmask = 0, retval;
memset(&pfd, 0, sizeof(pfd));
pfd.fd = fd;
if (mask & AE_READABLE) pfd.events |= POLLIN;
if (mask & AE_WRITABLE) pfd.events |= POLLOUT;
if ((retval = poll(&pfd, 1, milliseconds))== 1) {
if (pfd.revents & POLLIN) retmask |= AE_READABLE;
if (pfd.revents & POLLOUT) retmask |= AE_WRITABLE;
if (pfd.revents & POLLERR) retmask |= AE_WRITABLE;
if (pfd.revents & POLLHUP) retmask |= AE_WRITABLE;
return retmask;
} else {
return retval;
}
}
//启动事件处理程序
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0;
while (!eventLoop->stop) {
if (eventLoop->beforesleep != NULL)
eventLoop->beforesleep(eventLoop);
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}
}
//获取系统底层事件驱动的名字
char *aeGetApiName(void) {
return aeApiName();
}
//设置在执行事件池的事件之前的操作
void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) {
eventLoop->beforesleep = beforesleep;
}