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