]>
Commit | Line | Data |
---|---|---|
f3053eb0 HM |
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 | typedef struct aeApiState { | |
10 | int kqfd; | |
11 | struct kevent events[AE_SETSIZE]; | |
12 | } aeApiState; | |
13 | ||
14 | static int aeApiCreate(aeEventLoop *eventLoop) { | |
15 | aeApiState *state = zmalloc(sizeof(aeApiState)); | |
16 | ||
17 | if (!state) return -1; | |
18 | state->kqfd = kqueue(); | |
fb293ccb | 19 | if (state->kqfd == -1) { |
20 | zfree(state); | |
21 | return -1; | |
22 | } | |
f3053eb0 HM |
23 | eventLoop->apidata = state; |
24 | ||
25 | return 0; | |
26 | } | |
27 | ||
28 | static void aeApiFree(aeEventLoop *eventLoop) { | |
29 | aeApiState *state = eventLoop->apidata; | |
30 | ||
31 | close(state->kqfd); | |
32 | zfree(state); | |
33 | } | |
34 | ||
35 | static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { | |
36 | aeApiState *state = eventLoop->apidata; | |
37 | struct kevent ke; | |
38 | ||
39 | if (mask & AE_READABLE) { | |
40 | EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); | |
41 | if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; | |
42 | } | |
43 | if (mask & AE_WRITABLE) { | |
44 | EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); | |
45 | if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; | |
46 | } | |
47 | return 0; | |
48 | } | |
49 | ||
50 | static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) { | |
51 | aeApiState *state = eventLoop->apidata; | |
52 | struct kevent ke; | |
53 | ||
54 | if (mask & AE_READABLE) { | |
55 | EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); | |
56 | kevent(state->kqfd, &ke, 1, NULL, 0, NULL); | |
57 | } | |
58 | if (mask & AE_WRITABLE) { | |
59 | EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); | |
60 | kevent(state->kqfd, &ke, 1, NULL, 0, NULL); | |
61 | } | |
62 | } | |
63 | ||
64 | static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) { | |
65 | aeApiState *state = eventLoop->apidata; | |
66 | int retval, numevents = 0; | |
67 | ||
68 | if (tvp != NULL) { | |
69 | struct timespec timeout; | |
70 | timeout.tv_sec = tvp->tv_sec; | |
71 | timeout.tv_nsec = tvp->tv_usec * 1000; | |
72 | retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, &timeout); | |
73 | } else { | |
74 | retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, NULL); | |
75 | } | |
76 | ||
77 | if (retval > 0) { | |
78 | int j; | |
79 | ||
80 | numevents = retval; | |
81 | for(j = 0; j < numevents; j++) { | |
82 | int mask = 0; | |
83 | struct kevent *e = state->events+j; | |
84 | ||
85 | if (e->filter == EVFILT_READ) mask |= AE_READABLE; | |
86 | if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE; | |
87 | eventLoop->fired[j].fd = e->ident; | |
88 | eventLoop->fired[j].mask = mask; | |
89 | } | |
f3053eb0 HM |
90 | } |
91 | return numevents; | |
17511391 | 92 | } |
7a932b74 | 93 | |
94 | static char *aeApiName(void) { | |
95 | return "kqueue"; | |
96 | } |