zoukankan      html  css  js  c++  java
  • 【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 }
    喜欢一起简单,实用的东西,拒绝复杂花哨,我不是GEEK.
  • 相关阅读:
    八数码难题 (codevs 1225)题解
    小木棍 (codevs 3498)题解
    sliding windows (poj 2823) 题解
    集合删数 (vijos 1545) 题解
    合并果子 (codevs 1063) 题解
    等价表达式 (codevs 1107)题解
    生理周期 (poj 1006) 题解
    区间 (vijos 1439) 题解
    区间覆盖问题 题解
    种树 (codevs 1653) 题解
  • 原文地址:https://www.cnblogs.com/igloo1986/p/2665820.html
Copyright © 2011-2022 走看看