redisソースノート-ae_epoll.c

12364 ワード

このコードは、特定のイベントトリガネットワークライブラリの最下位実装です.Linuxの下にはepoll施設があり、その効率は現在最も高い.注意redisのように効率的でも、自動ドキュメント-水平トリガ(自動ドキュメントと手動ドキュメントの故事は自分でgoogle)を選択しただけです.libeventも使用する水平トリガだそうです.くだらないことは言わないで、コードを見てください.
 1 #include <sys/epoll.h>

 2 

 3 typedef struct aeApiState {

 4     int epfd;

 5     struct epoll_event events[AE_SETSIZE]; //   epoll_wait          

 6 } aeApiState; //  eventLoop   apidata  

 7 

 8 static int aeApiCreate(aeEventLoop *eventLoop) {

 9     aeApiState *state = zmalloc(sizeof(aeApiState));

10 

11     if (!state) return -1;

12     state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */

13     if (state->epfd == -1) return -1;

14     eventLoop->apidata = state;

15     return 0;

16 }

17 

18 static void aeApiFree(aeEventLoop *eventLoop) {

19     aeApiState *state = eventLoop->apidata;

20 

21     close(state->epfd);

22     zfree(state);

23 }

24 

25 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {

26     aeApiState *state = eventLoop->apidata;

27     struct epoll_event ee;

28     /* If the fd was already monitored for some event, we need a MOD

29      * operation. Otherwise we need an ADD operation. */

30     int op = eventLoop->events[fd].mask == AE_NONE ?

31             EPOLL_CTL_ADD : EPOLL_CTL_MOD;

32 

33     ee.events = 0;

34     mask |= eventLoop->events[fd].mask; /* Merge old events */

35     if (mask & AE_READABLE) ee.events |= EPOLLIN;

36     if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;

37     ee.data.u64 = 0; /* avoid valgrind warning */

38     ee.data.fd = fd;

39     if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;

40     return 0;

41 }

42 

43 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {

44     aeApiState *state = eventLoop->apidata;

45     struct epoll_event ee;

46     int mask = eventLoop->events[fd].mask & (~delmask);

47 

48     ee.events = 0;

49     if (mask & AE_READABLE) ee.events |= EPOLLIN;

50     if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;

51     ee.data.u64 = 0; /* avoid valgrind warning */

52     ee.data.fd = fd;

53     if (mask != AE_NONE) {

54         epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);

55     } else {

56         /* Note, Kernel < 2.6.9 requires a non null event pointer even for

57          * EPOLL_CTL_DEL. */

58         epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);

59     }

60 }

61 

62 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {

63     aeApiState *state = eventLoop->apidata;

64     int retval, numevents = 0;

65 

66     retval = epoll_wait(state->epfd,state->events,AE_SETSIZE,

67             tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);

68     if (retval > 0) {

69         int j;

70 

71         numevents = retval;

72         for (j = 0; j < numevents; j++) {

73             int mask = 0;

74             struct epoll_event *e = state->events+j;

75 

76             if (e->events & EPOLLIN) mask |= AE_READABLE;

77             if (e->events & EPOLLOUT) mask |= AE_WRITABLE;

78             eventLoop->fired[j].fd = e->data.fd;

79             eventLoop->fired[j].mask = mask;
// fired
80 } 81 } 82 return numevents; 83 } 84 85 static char *aeApiName(void) { 86 return "epoll"; 87 }