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