1 /* Kqueue(2)-based ae.c module
2  * Copyright (C) 2009 Harish Mallipeddi - harish.mallipeddi@gmail.com
3  * Released under the BSD license. See the COPYING file for more info. */
4 
5 #include <sys/types.h>
6 #include <sys/event.h>
7 #include <sys/time.h>
8 
9 #include "beansdb.h"
10 
11 typedef struct aeApiState
12 {
13     int kqfd;
14     struct kevent events[AE_SETSIZE];
15 } aeApiState;
16 
aeApiCreate(EventLoop * eventLoop)17 static int aeApiCreate(EventLoop *eventLoop)
18 {
19     aeApiState *state = malloc(sizeof(aeApiState));
20 
21     if (!state) return -1;
22     state->kqfd = kqueue();
23     if (state->kqfd == -1) return -1;
24     eventLoop->apidata = state;
25 
26     return 0;
27 }
28 
aeApiFree(EventLoop * eventLoop)29 static void aeApiFree(EventLoop *eventLoop)
30 {
31     aeApiState *state = eventLoop->apidata;
32 
33     close(state->kqfd);
34     free(state);
35 }
36 
aeApiAddEvent(EventLoop * eventLoop,int fd,int mask)37 static int aeApiAddEvent(EventLoop *eventLoop, int fd, int mask)
38 {
39     aeApiState *state = eventLoop->apidata;
40     struct kevent ke;
41 
42     if (mask & AE_READABLE)
43     {
44         EV_SET(&ke, fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
45         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
46     }
47     if (mask & AE_WRITABLE)
48     {
49         EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
50         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
51     }
52     return 0;
53 }
54 
aeApiUpdateEvent(EventLoop * eventLoop,int fd,int mask)55 static int aeApiUpdateEvent(EventLoop *eventLoop, int fd, int mask)
56 {
57     return aeApiAddEvent(eventLoop, fd, mask);
58 }
59 
aeApiDelEvent(EventLoop * eventLoop,int fd)60 static int aeApiDelEvent(EventLoop *eventLoop, int fd)
61 {
62     aeApiState *state = eventLoop->apidata;
63     struct kevent ke;
64 
65     EV_SET(&ke, fd, EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
66     kevent(state->kqfd, &ke, 1, NULL, 0, NULL);
67     return 0;
68 }
69 
aeApiPoll(EventLoop * eventLoop,struct timeval * tvp)70 static int aeApiPoll(EventLoop *eventLoop, struct timeval *tvp)
71 {
72     aeApiState *state = eventLoop->apidata;
73     int retval, numevents = 0;
74 
75     if (tvp != NULL)
76     {
77         struct timespec timeout;
78         timeout.tv_sec = tvp->tv_sec;
79         timeout.tv_nsec = tvp->tv_usec * 1000;
80         retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, &timeout);
81     }
82     else
83     {
84         retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, NULL);
85     }
86 
87     if (retval > 0)
88     {
89         int j;
90 
91         numevents = retval;
92         for(j = 0; j < numevents; j++)
93         {
94             int mask = 0;
95             struct kevent *e = state->events+j;
96 
97             if (e->filter == EVFILT_READ) mask |= AE_READABLE;
98             if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;
99             eventLoop->fired[j] = e->ident;
100         }
101     }
102     return numevents;
103 }
104 
aeApiName(void)105 static char *aeApiName(void)
106 {
107     return "kqueue";
108 }
109