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.
  • 相关阅读:
    Maven常用命令:
    正向代理、反向代理、透明代理
    linux命令ps aux|grep xxx详解
    Java中Comparable和Comparator区别小结
    Java Queue之PriorityQueue
    java读写分离的实现
    CSS颜色名称和颜色值
    使用Access-Control-Allow-Origin解决跨域
    Tomcat 下启用 https:// 访问
    使用Jedis操作redis
  • 原文地址:https://www.cnblogs.com/igloo1986/p/2665820.html
Copyright © 2011-2022 走看看