]> git.saurik.com Git - redis.git/commitdiff
epoll module for ae.c implemented. Some more testing needed
authorantirez <antirez@gmail.com>
Mon, 23 Nov 2009 22:40:27 +0000 (23:40 +0100)
committerantirez <antirez@gmail.com>
Mon, 23 Nov 2009 22:40:27 +0000 (23:40 +0100)
Makefile
ae_epoll.c [new file with mode: 0644]

index 7d9bdc57c337c6cfb6cbf20ad2f4792d858722b6..34b35f5767c188b63b8fe9e342bf8d3335a6be98 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ all: redis-server redis-benchmark redis-cli
 
 # Deps (use make dep to generate this)
 adlist.o: adlist.c adlist.h zmalloc.h
-ae.o: ae.c ae.h zmalloc.h ae_select.c
+ae.o: ae.c ae.h zmalloc.h ae_select.c ae_epoll.c
 ae_select.o: ae_select.c
 anet.o: anet.c fmacros.h anet.h
 benchmark.o: benchmark.c fmacros.h ae.h anet.h sds.h adlist.h zmalloc.h
diff --git a/ae_epoll.c b/ae_epoll.c
new file mode 100644 (file)
index 0000000..b63b74b
--- /dev/null
@@ -0,0 +1,85 @@
+/* Linux epoll(2) based ae.c module
+ * Copyright (C) 2009 Salvatore Sanfilippo - antirez@gmail.com
+ * Released under the BSD license. See the COPYING file for more info. */
+
+#include <sys/epoll.h>
+
+typedef struct aeApiState {
+    int epfd;
+    struct epoll_event events[AE_SETSIZE];
+} aeApiState;
+
+static int aeApiCreate(aeEventLoop *eventLoop) {
+    aeApiState *state = zmalloc(sizeof(aeApiState));
+
+    if (!state) return -1;
+    state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */
+    if (state->epfd == -1) return -1;
+    eventLoop->apidata = state;
+    return 0;
+}
+
+static void aeApiFree(aeEventLoop *eventLoop) {
+    aeApiState *state = eventLoop->apidata;
+
+    close(state->epfd);
+    zfree(state);
+}
+
+static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
+    aeApiState *state = eventLoop->apidata;
+    struct epoll_event ee;
+    int op = eventLoop->events[fd].mask == AE_NONE ?
+            EPOLL_CTL_ADD : EPOLL_CTL_MOD;
+
+    ee.events = 0;
+    if (mask & AE_READABLE) ee.events |= EPOLLIN;
+    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
+    if (mask & AE_EXCEPTION) ee.events |= EPOLLPRI;
+    ee.data.fd = fd;
+    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;
+    return 0;
+}
+
+static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {
+    aeApiState *state = eventLoop->apidata;
+    struct epoll_event ee;
+    int mask = eventLoop->events[fd].mask & (~delmask);
+
+    ee.events = 0;
+    if (mask & AE_READABLE) ee.events |= EPOLLIN;
+    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
+    if (mask & AE_EXCEPTION) ee.events |= EPOLLPRI;
+    ee.data.fd = fd;
+    if (mask != AE_NONE) {
+        epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);
+    } else {
+        /* Note, Kernel < 2.6.9 requires a non null event pointer even for
+         * EPOLL_CTL_DEL. */
+        epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);
+    }
+}
+
+static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
+    aeApiState *state = eventLoop->apidata;
+    int retval, numevents = 0;
+
+    retval = epoll_wait(state->epfd,state->events,AE_SETSIZE,
+            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);
+    if (retval > 0) {
+        int j;
+
+        numevents = retval;
+        for (j = 0; j < numevents; j++) {
+            int mask = 0;
+            struct epoll_event *e = state->events+j;
+
+            if (e->events & EPOLLIN) mask |= AE_READABLE;
+            if (e->events & EPOLLOUT) mask |= AE_WRITABLE;
+            if (e->events & EPOLLPRI) mask |= AE_EXCEPTION;
+            eventLoop->fired[j].fd = e->data.fd;
+            eventLoop->fired[j].mask = mask;
+        }
+    }
+    return numevents;
+}