【redis源码】(六)Ae.c

和memcached不同的是,redis没有使用第三方的事件框架,而是自己封装了io处理机制。

有些细节上,redis并没有做到最优化,比如超时事件管理,redis仅仅使用了一个单链表,最新插入的超时事件放在链表头,作者在源码中也提到超时事件上的一些可以改进的地方【比如libevent超时事件采用最大堆实现】

“Note that's O(N) since time events are unsorted.
Possible optimizations (not needed by Redis so far, but...):
1) Insert the event in order, so that the nearest is just the head. Much better but still insertion or deletion of timers is O(N).
2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)).”

另外一个小细节是,如果使用epoll做io复用模型的话,redis会使用水平触发作为工作方式。

 

哦了,贴代码,看了好久才想清楚~ 感觉表述越来越不清楚了,还是自己理解的不够透彻,再接再厉

Ae_select.c

 1 /* Select()-based ae.c module
 2  * Copyright (C) 2009-2010 Salvatore Sanfilippo - antirez@gmail.com
 3  * Released under the BSD license. See the COPYING file for more info. */
 4 
 5 #include <string.h>
 6 
 7 //select底层底层封装,被ae.c使用,用来处理读写文件描述符的时间管理
 8 typedef struct aeApiState {
 9     //用来保存注册到select文件描述符
10     fd_set rfds, wfds;
11     /* We need to have a copy of the fd sets as it's not safe to reuse
12      * FD sets after select(). */
13     //select操作时使用的fd_set文件
14     fd_set _rfds, _wfds;
15 } aeApiState;
16 
17 //给上层zip调用的方法,用于初始化一个select事件管理
18 static int aeApiCreate(aeEventLoop *eventLoop) {
19     aeApiState *state = zmalloc(sizeof(aeApiState));
20 
21     if (!state) return -1;
22     //初始化aeApiState中的fd_set
23     FD_ZERO(&state->rfds);
24     FD_ZERO(&state->wfds);
25     eventLoop->apidata = state;
26     return 0;
27 }
28 
29 //释放aeApiState内存
30 static void aeApiFree(aeEventLoop *eventLoop) {
31     zfree(eventLoop->apidata);
32 }
33 
34 //向eventLoop添加指定mask的文件描述符
35 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
36     aeApiState *state = eventLoop->apidata;
37 
38     //插入读事件文件描述符
39     if (mask & AE_READABLE) FD_SET(fd,&state->rfds);
40     //插入写事件文件描述符
41     if (mask & AE_WRITABLE) FD_SET(fd,&state->wfds);
42     return 0;
43 }
44 
45 //从eventLoop中删除描述符fd的指定监听事件
46 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {
47     aeApiState *state = eventLoop->apidata;
48 
49     if (mask & AE_READABLE) FD_CLR(fd,&state->rfds);
50     if (mask & AE_WRITABLE) FD_CLR(fd,&state->wfds);
51 }
52 
53 //执行事件监听,超时时间为tvp
54 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
55     aeApiState *state = eventLoop->apidata;
56     int retval, j, numevents = 0;
57 
58     //复制最新的state->rfds & state->wfds到_rfds,_wfds
59     memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));
60     memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));
61 
62     //执行select,超时时间tvp
63     retval = select(eventLoop->maxfd+1,
64                 &state->_rfds,&state->_wfds,NULL,tvp);
65     if (retval > 0) {
66         for (j = 0; j <= eventLoop->maxfd; j++) {
67             int mask = 0;
68             aeFileEvent *fe = &eventLoop->events[j];
69 
70             if (fe->mask == AE_NONE) continue;
71             if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))
72                 mask |= AE_READABLE;
73             if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))
74                 mask |= AE_WRITABLE;
75             //将可读或者可写的文件描述符状态更新到eventLoop结构体中
76             eventLoop->fired[numevents].fd = j;
77             eventLoop->fired[numevents].mask = mask;
78             numevents++;
79         }
80     }
81     //返回可读可写的文件描述符总数量
82     return numevents;
83 }
84 
85 static char *aeApiName(void) {
86     return "select";
87 }

Ae_epoll.c

 1 /* Linux epoll(2) based ae.c module
 2  * Copyright (C) 2009-2010 Salvatore Sanfilippo - antirez@gmail.com
 3  * Released under the BSD license. See the COPYING file for more info. */
 4 
 5 #include <sys/epoll.h>
 6 
 7 
 8 typedef struct aeApiState {
 9     int epfd;
10     struct epoll_event events[AE_SETSIZE];
11 } aeApiState;
12 
13 //初始化一个epoll时间管理结构体eventLoop
14 static int aeApiCreate(aeEventLoop *eventLoop) {
15     aeApiState *state = zmalloc(sizeof(aeApiState));
16 
17     if (!state) return -1;
18     //epoll_create(size)中的size参数不使用
19     //初始化epoll_fd
20     state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */
21     if (state->epfd == -1) return -1;
22     eventLoop->apidata = state;
23     return 0;
24 }
25 
26 //释放aeApiState空间
27 static void aeApiFree(aeEventLoop *eventLoop) {
28     aeApiState *state = eventLoop->apidata;
29 
30     close(state->epfd);
31     zfree(state);
32 }
33 
34 //为eventLoop添加文件描述符与其相应的监听事件
35 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
36     aeApiState *state = eventLoop->apidata;
37     struct epoll_event ee;
38     /* If the fd was already monitored for some event, we need a MOD
39      * operation. Otherwise we need an ADD operation. */
40     int op = eventLoop->events[fd].mask == AE_NONE ?
41             EPOLL_CTL_ADD : EPOLL_CTL_MOD;
42 
43     ee.events = 0;
44     mask |= eventLoop->events[fd].mask; /* Merge old events */
45     if (mask & AE_READABLE) ee.events |= EPOLLIN;
46     if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
47     ee.data.u64 = 0; /* avoid valgrind warning */
48     ee.data.fd = fd;
49     if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;
50     return 0;
51 }
52 
53 //从eventLoop中删除fd的delmask时间类型
54 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {
55     aeApiState *state = eventLoop->apidata;
56     struct epoll_event ee;
57     int mask = eventLoop->events[fd].mask & (~delmask);
58 
59     ee.events = 0;
60     if (mask & AE_READABLE) ee.events |= EPOLLIN;
61     if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
62     ee.data.u64 = 0; /* avoid valgrind warning */
63     ee.data.fd = fd;
64     if (mask != AE_NONE) {
65         epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);
66     } else {
67         /* Note, Kernel < 2.6.9 requires a non null event pointer even for
68          * EPOLL_CTL_DEL. */
69         epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);
70     }
71 }
72 
73 //poll操作,返回事件就绪的fd数量
74 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
75     aeApiState *state = eventLoop->apidata;
76     int retval, numevents = 0;
77 
78     retval = epoll_wait(state->epfd,state->events,AE_SETSIZE,
79             tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);
80     if (retval > 0) {
81         int j;
82 
83         numevents = retval;
84         for (j = 0; j < numevents; j++) {
85             int mask = 0;
86             struct epoll_event *e = state->events+j;
87 
88             if (e->events & EPOLLIN) mask |= AE_READABLE;
89             if (e->events & EPOLLOUT) mask |= AE_WRITABLE;
90             eventLoop->fired[j].fd = e->data.fd;
91             eventLoop->fired[j].mask = mask;
92         }
93     }
94     return numevents;
95 }
96 
97 static char *aeApiName(void) {
98     return "epoll";
99 }

Ae.h

 1 #ifndef __AE_H__
 2 #define __AE_H__
 3 
 4 //支持的最大监听fd的数量
 5 #define AE_SETSIZE (1024*10)    /* Max number of fd supported */
 6 
 7 #define AE_OK 0
 8 #define AE_ERR -1
 9 
10 #define AE_NONE 0
11 #define AE_READABLE 1
12 #define AE_WRITABLE 2
13 
14 #define AE_FILE_EVENTS 1
15 #define AE_TIME_EVENTS 2
16 #define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)
17 #define AE_DONT_WAIT 4
18 
19 #define AE_NOMORE -1
20 
21 /* Macros */
22 #define AE_NOTUSED(V) ((void) V)
23 
24 //声明aeEventLoop
25 struct aeEventLoop;
26 
27 /* Types and data structures */
28 
29 typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
30 typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
31 typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
32 typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
33 
34 //描述符时间结构体,要么读,要么写
35 /* File event structure */
36 typedef struct aeFileEvent {
37     int mask; /* one of AE_(READABLE|WRITABLE) */
38     aeFileProc *rfileProc;
39     aeFileProc *wfileProc;
40     void *clientData;
41 } aeFileEvent;
42 
43 //超时事件结构体
44 /* Time event structure */
45 typedef struct aeTimeEvent {
46     long long id; /* time event identifier. */
47     long when_sec; /* seconds */
48     long when_ms; /* milliseconds */
49     aeTimeProc *timeProc;
50     aeEventFinalizerProc *finalizerProc;
51     void *clientData;
52     struct aeTimeEvent *next;
53 } aeTimeEvent;
54 
55 //已激活事件结构体
56 /* A fired event */
57 typedef struct aeFiredEvent {
58     int fd;
59     int mask;
60 } aeFiredEvent;
61 
62 /* State of an event based program */
63 typedef struct aeEventLoop {
64     int maxfd;
65     long long timeEventNextId;
66     aeFileEvent events[AE_SETSIZE]; /* Registered events */
67     aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
68     aeTimeEvent *timeEventHead;
69     int stop;
70     void *apidata; /* This is used for polling API specific data */
71     aeBeforeSleepProc *beforesleep;
72 } aeEventLoop;
73 
74 /* Prototypes */
75 aeEventLoop *aeCreateEventLoop(void);
76 void aeDeleteEventLoop(aeEventLoop *eventLoop);
77 void aeStop(aeEventLoop *eventLoop);
78 int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
79         aeFileProc *proc, void *clientData);
80 void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
81 long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
82         aeTimeProc *proc, void *clientData,
83         aeEventFinalizerProc *finalizerProc);
84 int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);
85 int aeProcessEvents(aeEventLoop *eventLoop, int flags);
86 int aeWait(int fd, int mask, long long milliseconds);
87 void aeMain(aeEventLoop *eventLoop);
88 char *aeGetApiName(void);
89 void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);
90 
91 #endif

Ae.c

  1 #include <stdio.h>
  2 #include <sys/time.h>
  3 #include <sys/types.h>
  4 #include <unistd.h>
  5 #include <stdlib.h>
  6 
  7 #include "ae.h"
  8 #include "zmalloc.h"
  9 #include "config.h"
 10 
 11 /* Include the best multiplexing layer supported by this system.
 12  * The following should be ordered by performances, descending. */
 13 //选择使用的底层事件管理API
 14 #ifdef HAVE_EPOLL
 15 #include "ae_epoll.c"
 16 #else
 17     #ifdef HAVE_KQUEUE
 18     #include "ae_kqueue.c"
 19     #else
 20     #include "ae_select.c"
 21     #endif
 22 #endif
 23 
 24 //初始化eventLoop结构体
 25 aeEventLoop *aeCreateEventLoop(void) {
 26     aeEventLoop *eventLoop;
 27     int i;
 28     //申请内存
 29     eventLoop = zmalloc(sizeof(*eventLoop));
 30     if (!eventLoop) return NULL;
 31     eventLoop->timeEventHead = NULL;
 32     eventLoop->timeEventNextId = 0;
 33     eventLoop->stop = 0;
 34     eventLoop->maxfd = -1;
 35     eventLoop->beforesleep = NULL;
 36     //初始化底层事件管理结构体aeApiState,赋值给*apidata
 37     if (aeApiCreate(eventLoop) == -1) {
 38         zfree(eventLoop);
 39         return NULL;
 40     }
 41     /* Events with mask == AE_NONE are not set. So let's initialize the
 42      * vector with it. */
 43     //为描述符事件初始化监视事件类型
 44     for (i = 0; i < AE_SETSIZE; i++)
 45         eventLoop->events[i].mask = AE_NONE;
 46     return eventLoop;
 47 }
 48 
 49 //释放aeEventLoop
 50 void aeDeleteEventLoop(aeEventLoop *eventLoop) {
 51     aeApiFree(eventLoop);
 52     zfree(eventLoop);
 53 }
 54 
 55 void aeStop(aeEventLoop *eventLoop) {
 56     eventLoop->stop = 1;
 57 }
 58 
 59 //添加一个fd及其处理函数
 60 int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
 61         aeFileProc *proc, void *clientData)
 62 {
 63     //文件描述符超过过了最大的值
 64     if (fd >= AE_SETSIZE) return AE_ERR;
 65     aeFileEvent *fe = &eventLoop->events[fd];
 66 
 67     if (aeApiAddEvent(eventLoop, fd, mask) == -1)
 68         return AE_ERR;
 69     fe->mask |= mask;
 70     if (mask & AE_READABLE) fe->rfileProc = proc;
 71     if (mask & AE_WRITABLE) fe->wfileProc = proc;
 72     fe->clientData = clientData;
 73     if (fd > eventLoop->maxfd)
 74         eventLoop->maxfd = fd;
 75     return AE_OK;
 76 }
 77 
 78 //从eventLoop中删除对fd的mask中知名的监听类型的删除
 79 void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
 80 {
 81     //文件描述符超过过了最大的值
 82     if (fd >= AE_SETSIZE) return;
 83     aeFileEvent *fe = &eventLoop->events[fd];
 84 
 85     //fd上并未绑定任何类型的时间
 86     if (fe->mask == AE_NONE) return;
 87     //对mask指定的bit置零
 88     fe->mask = fe->mask & (~mask);
 89     //如果去除的监听fd是最大的那个,并且此fd当前没有任何监听事件,则更新eventloop的maxfd字段
 90     if (fd == eventLoop->maxfd && fe->mask == AE_NONE) {
 91         /* Update the max fd */
 92         int j;
 93 
 94         for (j = eventLoop->maxfd-1; j >= 0; j--)
 95             if (eventLoop->events[j].mask != AE_NONE) break;
 96         eventLoop->maxfd = j;
 97     }
 98     //在api中删除对此fd的mask类事件的监听
 99     aeApiDelEvent(eventLoop, fd, mask);
100 }
101 
102 //得到当前时间
103 static void aeGetTime(long *seconds, long *milliseconds)
104 {
105     struct timeval tv;
106 
107     gettimeofday(&tv, NULL);
108     *seconds = tv.tv_sec;
109     *milliseconds = tv.tv_usec/1000;
110 }
111 
112 //得到millissconds后的时间
113 static void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {
114     long cur_sec, cur_ms, when_sec, when_ms;
115 
116     aeGetTime(&cur_sec, &cur_ms);
117     when_sec = cur_sec + milliseconds/1000;
118     when_ms = cur_ms + milliseconds%1000;
119     if (when_ms >= 1000) {
120         when_sec ++;
121         when_ms -= 1000;
122     }
123     *sec = when_sec;
124     *ms = when_ms;
125 }
126 
127 //注册一个超时事件
128 long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
129         aeTimeProc *proc, void *clientData,
130         aeEventFinalizerProc *finalizerProc)
131 {
132     //得到新的超时事件的id
133     long long id = eventLoop->timeEventNextId++;
134     aeTimeEvent *te;
135 
136     te = zmalloc(sizeof(*te));
137     if (te == NULL) return AE_ERR;
138     te->id = id;
139     aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);
140     te->timeProc = proc;
141     te->finalizerProc = finalizerProc;
142     te->clientData = clientData;
143     //将新的超时事件数据插到单链表的头部
144     te->next = eventLoop->timeEventHead;
145     eventLoop->timeEventHead = te;
146     return id;
147 }
148 
149 //删除id为id的超时事件,单链表操作
150 int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)
151 {
152     aeTimeEvent *te, *prev = NULL;
153 
154     te = eventLoop->timeEventHead;
155     while(te) {
156         if (te->id == id) {
157             if (prev == NULL)
158                 eventLoop->timeEventHead = te->next;
159             else
160                 prev->next = te->next;
161             if (te->finalizerProc)
162                 te->finalizerProc(eventLoop, te->clientData);
163             zfree(te);
164             return AE_OK;
165         }
166         prev = te;
167         te = te->next;
168     }
169     return AE_ERR; /* NO event with the specified ID found */
170 }
171 
172 /* Search the first timer to fire.
173  * This operation is useful to know how many time the select can be
174  * put in sleep without to delay any event.
175  * If there are no timers NULL is returned.
176  *
177  * Note that's O(N) since time events are unsorted.
178  * Possible optimizations (not needed by Redis so far, but...):
179  * 1) Insert the event in order, so that the nearest is just the head.
180  *    Much better but still insertion or deletion of timers is O(N).
181  *    最大堆呀最大堆,libevent
182  * 2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)).
183  */
184 static aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)
185 {
186     aeTimeEvent *te = eventLoop->timeEventHead;
187     aeTimeEvent *nearest = NULL;
188 
189     while(te) {
190         if (!nearest || te->when_sec < nearest->when_sec ||
191                 (te->when_sec == nearest->when_sec &&
192                  te->when_ms < nearest->when_ms))
193             nearest = te;
194         te = te->next;
195     }
196     return nearest;
197 }
198 
199 //遍历超时事件链表,把时间到了的一个一个处理
200 /* Process time events */
201 static int processTimeEvents(aeEventLoop *eventLoop) {
202     int processed = 0;
203     aeTimeEvent *te;
204     long long maxId;
205 
206     te = eventLoop->timeEventHead;
207     maxId = eventLoop->timeEventNextId-1;
208     while(te) {
209         long now_sec, now_ms;
210         long long id;
211 
212         if (te->id > maxId) {
213             te = te->next;
214             continue;
215         }
216         aeGetTime(&now_sec, &now_ms);
217         if (now_sec > te->when_sec ||
218             (now_sec == te->when_sec && now_ms >= te->when_ms))
219         {
220             int retval;
221 
222             id = te->id;
223             retval = te->timeProc(eventLoop, id, te->clientData);
224             processed++;
225             /* After an event is processed our time event list may
226              * no longer be the same, so we restart from head.
227              * Still we make sure to don't process events registered
228              * by event handlers itself in order to don't loop forever.
229              * To do so we saved the max ID we want to handle.
230              *
231              * FUTURE OPTIMIZATIONS:
232              * Note that this is NOT great algorithmically. Redis uses
233              * a single time event so it's not a problem but the right
234              * way to do this is to add the new elements on head, and
235              * to flag deleted elements in a special way for later
236              * deletion (putting references to the nodes to delete into
237              * another linked list). */
238             if (retval != AE_NOMORE) {
239                 aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
240             } else {
241                 aeDeleteTimeEvent(eventLoop, id);
242             }
243             te = eventLoop->timeEventHead;
244         } else {
245             te = te->next;
246         }
247     }
248     return processed;
249 }
250 
251 
252 //处理可处理的所有事件,包括文件事件和超时事件
253 /* Process every pending time event, then every pending file event
254  * (that may be registered by time event callbacks just processed).
255  * Without special flags the function sleeps until some file event
256  * fires, or when the next time event occurrs (if any).
257  *
258  * If flags is 0, the function does nothing and returns.
259  * if flags has AE_ALL_EVENTS set, all the kind of events are processed.
260  * if flags has AE_FILE_EVENTS set, file events are processed.
261  * if flags has AE_TIME_EVENTS set, time events are processed.
262  * if flags has AE_DONT_WAIT set the function returns ASAP until all
263  * the events that's possible to process without to wait are processed.
264  *
265  * The function returns the number of events processed. */
266 int aeProcessEvents(aeEventLoop *eventLoop, int flags)
267 {
268     int processed = 0, numevents;
269 
270     /* Nothing to do? return ASAP */
271     if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;
272 
273     /* Note that we want call select() even if there are no
274      * file events to process as long as we want to process time
275      * events, in order to sleep until the next time event is ready
276      * to fire. */
277     if (eventLoop->maxfd != -1 ||
278         ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
279         int j;
280         aeTimeEvent *shortest = NULL;
281         struct timeval tv, *tvp;
282 
283         if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))
284             shortest = aeSearchNearestTimer(eventLoop);
285         if (shortest) {
286             long now_sec, now_ms;
287 
288             /* Calculate the time missing for the nearest
289              * timer to fire. */
290             aeGetTime(&now_sec, &now_ms);
291             tvp = &tv;
292             tvp->tv_sec = shortest->when_sec - now_sec;
293             if (shortest->when_ms < now_ms) {
294                 tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000;
295                 tvp->tv_sec --;
296             } else {
297                 tvp->tv_usec = (shortest->when_ms - now_ms)*1000;
298             }
299             if (tvp->tv_sec < 0) tvp->tv_sec = 0;
300             if (tvp->tv_usec < 0) tvp->tv_usec = 0;
301         } else {
302             /* If we have to check for events but need to return
303              * ASAP because of AE_DONT_WAIT we need to se the timeout
304              * to zero */
305             if (flags & AE_DONT_WAIT) {
306                 tv.tv_sec = tv.tv_usec = 0;
307                 tvp = &tv;
308             } else {
309                 /* Otherwise we can block */
310                 tvp = NULL; /* wait forever */
311             }
312         }
313 
314         numevents = aeApiPoll(eventLoop, tvp);
315         for (j = 0; j < numevents; j++) {
316             aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
317             int mask = eventLoop->fired[j].mask;
318             int fd = eventLoop->fired[j].fd;
319             int rfired = 0;
320 
321         /* note the fe->mask & mask & ... code: maybe an already processed
322              * event removed an element that fired and we still didn't
323              * processed, so we check if the event is still valid. */
324             if (fe->mask & mask & AE_READABLE) {
325                 rfired = 1;
326                 fe->rfileProc(eventLoop,fd,fe->clientData,mask);
327             }
328             if (fe->mask & mask & AE_WRITABLE) {
329                 if (!rfired || fe->wfileProc != fe->rfileProc)
330                     fe->wfileProc(eventLoop,fd,fe->clientData,mask);
331             }
332             processed++;
333         }
334     }
335     /* Check time events */
336     if (flags & AE_TIME_EVENTS)
337         processed += processTimeEvents(eventLoop);
338 
339     return processed; /* return the number of processed file/time events */
340 }
341 
342 
343 //使用select模型,等待millseconds,返回0,表示超时,返回1,表明fd可读,返回2,表明fd可写
344 /* Wait for millseconds until the given file descriptor becomes
345  * writable/readable/exception */
346 int aeWait(int fd, int mask, long long milliseconds) {
347     struct timeval tv;
348     fd_set rfds, wfds, efds;
349     int retmask = 0, retval;
350 
351     tv.tv_sec = milliseconds/1000;
352     tv.tv_usec = (milliseconds%1000)*1000;
353     FD_ZERO(&rfds);
354     FD_ZERO(&wfds);
355     FD_ZERO(&efds);
356 
357     if (mask & AE_READABLE) FD_SET(fd,&rfds);
358     if (mask & AE_WRITABLE) FD_SET(fd,&wfds);
359     if ((retval = select(fd+1, &rfds, &wfds, &efds, &tv)) > 0) {
360         if (FD_ISSET(fd,&rfds)) retmask |= AE_READABLE;
361         if (FD_ISSET(fd,&wfds)) retmask |= AE_WRITABLE;
362         return retmask;
363     } else {
364         return retval;
365     }
366 }
367 
368 void aeMain(aeEventLoop *eventLoop) {
369     eventLoop->stop = 0;
370     while (!eventLoop->stop) {
371         if (eventLoop->beforesleep != NULL)
372             eventLoop->beforesleep(eventLoop);
373         aeProcessEvents(eventLoop, AE_ALL_EVENTS);
374     }
375 }
376 
377 char *aeGetApiName(void) {
378     return aeApiName();
379 }
380 
381 void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) {
382     eventLoop->beforesleep = beforesleep;
383 }
posted @ 2012-08-31 18:19  ~嘉言懿行~~我是煲仔饭~~  阅读(976)  评论(0编辑  收藏  举报