Back to home page

Redis cross reference

 
 

    


0001 /* Kqueue(2)-based ae.c module
0002  *
0003  * Copyright (C) 2009 Harish Mallipeddi - harish.mallipeddi@gmail.com
0004  * All rights reserved.
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions are met:
0008  *
0009  *   * Redistributions of source code must retain the above copyright notice,
0010  *     this list of conditions and the following disclaimer.
0011  *   * Redistributions in binary form must reproduce the above copyright
0012  *     notice, this list of conditions and the following disclaimer in the
0013  *     documentation and/or other materials provided with the distribution.
0014  *   * Neither the name of Redis nor the names of its contributors may be used
0015  *     to endorse or promote products derived from this software without
0016  *     specific prior written permission.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 
0032 #include <sys/types.h>
0033 #include <sys/event.h>
0034 #include <sys/time.h>
0035 
0036 typedef struct aeApiState {
0037     int kqfd;
0038     struct kevent *events;
0039 } aeApiState;
0040 
0041 static int aeApiCreate(aeEventLoop *eventLoop) {
0042     aeApiState *state = zmalloc(sizeof(aeApiState));
0043 
0044     if (!state) return -1;
0045     state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);
0046     if (!state->events) {
0047         zfree(state);
0048         return -1;
0049     }
0050     state->kqfd = kqueue();
0051     if (state->kqfd == -1) {
0052         zfree(state->events);
0053         zfree(state);
0054         return -1;
0055     }
0056     eventLoop->apidata = state;
0057     
0058     return 0;    
0059 }
0060 
0061 static void aeApiFree(aeEventLoop *eventLoop) {
0062     aeApiState *state = eventLoop->apidata;
0063 
0064     close(state->kqfd);
0065     zfree(state->events);
0066     zfree(state);
0067 }
0068 
0069 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
0070     aeApiState *state = eventLoop->apidata;
0071     struct kevent ke;
0072     
0073     if (mask & AE_READABLE) {
0074         EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
0075         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
0076     }
0077     if (mask & AE_WRITABLE) {
0078         EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
0079         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
0080     }
0081     return 0;
0082 }
0083 
0084 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {
0085     aeApiState *state = eventLoop->apidata;
0086     struct kevent ke;
0087 
0088     if (mask & AE_READABLE) {
0089         EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
0090         kevent(state->kqfd, &ke, 1, NULL, 0, NULL);
0091     }
0092     if (mask & AE_WRITABLE) {
0093         EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
0094         kevent(state->kqfd, &ke, 1, NULL, 0, NULL);
0095     }
0096 }
0097 
0098 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
0099     aeApiState *state = eventLoop->apidata;
0100     int retval, numevents = 0;
0101 
0102     if (tvp != NULL) {
0103         struct timespec timeout;
0104         timeout.tv_sec = tvp->tv_sec;
0105         timeout.tv_nsec = tvp->tv_usec * 1000;
0106         retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
0107                         &timeout);
0108     } else {
0109         retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
0110                         NULL);
0111     }
0112 
0113     if (retval > 0) {
0114         int j;
0115         
0116         numevents = retval;
0117         for(j = 0; j < numevents; j++) {
0118             int mask = 0;
0119             struct kevent *e = state->events+j;
0120             
0121             if (e->filter == EVFILT_READ) mask |= AE_READABLE;
0122             if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;
0123             eventLoop->fired[j].fd = e->ident; 
0124             eventLoop->fired[j].mask = mask;           
0125         }
0126     }
0127     return numevents;
0128 }
0129 
0130 static char *aeApiName(void) {
0131     return "kqueue";
0132 }