| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2006 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 """ | |
| 5 Interface to epoll I/O event notification facility. | |
| 6 """ | |
| 7 | |
| 8 # NOTE: The version of Pyrex you are using probably _does not work_ with | |
| 9 # Python 2.5. If you need to recompile this file, _make sure you are using | |
| 10 # a version of Pyrex which works with Python 2.5_. I am using 0.9.4.1 from | |
| 11 # <http://codespeak.net/svn/lxml/pyrex/>. -exarkun | |
| 12 | |
| 13 cdef extern from "stdio.h": | |
| 14 cdef extern void *malloc(int) | |
| 15 cdef extern void free(void *) | |
| 16 cdef extern int close(int) | |
| 17 | |
| 18 cdef extern from "errno.h": | |
| 19 cdef extern int errno | |
| 20 cdef extern char *strerror(int) | |
| 21 | |
| 22 cdef extern from "string.h": | |
| 23 cdef extern void *memset(void* s, int c, int n) | |
| 24 | |
| 25 cdef extern from "stdint.h": | |
| 26 ctypedef unsigned long uint32_t | |
| 27 ctypedef unsigned long long uint64_t | |
| 28 | |
| 29 cdef extern from "sys/epoll.h": | |
| 30 | |
| 31 cdef enum: | |
| 32 EPOLL_CTL_ADD = 1 | |
| 33 EPOLL_CTL_DEL = 2 | |
| 34 EPOLL_CTL_MOD = 3 | |
| 35 | |
| 36 cdef enum EPOLL_EVENTS: | |
| 37 EPOLLIN = 0x001 | |
| 38 EPOLLPRI = 0x002 | |
| 39 EPOLLOUT = 0x004 | |
| 40 EPOLLRDNORM = 0x040 | |
| 41 EPOLLRDBAND = 0x080 | |
| 42 EPOLLWRNORM = 0x100 | |
| 43 EPOLLWRBAND = 0x200 | |
| 44 EPOLLMSG = 0x400 | |
| 45 EPOLLERR = 0x008 | |
| 46 EPOLLHUP = 0x010 | |
| 47 EPOLLET = (1 << 31) | |
| 48 | |
| 49 ctypedef union epoll_data_t: | |
| 50 void *ptr | |
| 51 int fd | |
| 52 uint32_t u32 | |
| 53 uint64_t u64 | |
| 54 | |
| 55 cdef struct epoll_event: | |
| 56 uint32_t events | |
| 57 epoll_data_t data | |
| 58 | |
| 59 int epoll_create(int size) | |
| 60 int epoll_ctl(int epfd, int op, int fd, epoll_event *event) | |
| 61 int epoll_wait(int epfd, epoll_event *events, int maxevents, int timeout) | |
| 62 | |
| 63 cdef extern from "Python.h": | |
| 64 ctypedef struct PyThreadState | |
| 65 cdef extern PyThreadState *PyEval_SaveThread() | |
| 66 cdef extern void PyEval_RestoreThread(PyThreadState*) | |
| 67 | |
| 68 cdef class epoll: | |
| 69 """ | |
| 70 Represent a set of file descriptors being monitored for events. | |
| 71 """ | |
| 72 | |
| 73 cdef int fd | |
| 74 cdef int initialized | |
| 75 | |
| 76 def __init__(self, int size): | |
| 77 self.fd = epoll_create(size) | |
| 78 if self.fd == -1: | |
| 79 raise IOError(errno, strerror(errno)) | |
| 80 self.initialized = 1 | |
| 81 | |
| 82 def __dealloc__(self): | |
| 83 if self.initialized: | |
| 84 close(self.fd) | |
| 85 self.initialized = 0 | |
| 86 | |
| 87 def close(self): | |
| 88 """ | |
| 89 Close the epoll file descriptor. | |
| 90 """ | |
| 91 if self.initialized: | |
| 92 if close(self.fd) == -1: | |
| 93 raise IOError(errno, strerror(errno)) | |
| 94 self.initialized = 0 | |
| 95 | |
| 96 def fileno(self): | |
| 97 """ | |
| 98 Return the epoll file descriptor number. | |
| 99 """ | |
| 100 return self.fd | |
| 101 | |
| 102 def _control(self, int op, int fd, int events): | |
| 103 """ | |
| 104 Modify the monitored state of a particular file descriptor. | |
| 105 | |
| 106 Wrap epoll_ctl(2). | |
| 107 | |
| 108 @type op: C{int} | |
| 109 @param op: One of CTL_ADD, CTL_DEL, or CTL_MOD | |
| 110 | |
| 111 @type fd: C{int} | |
| 112 @param fd: File descriptor to modify | |
| 113 | |
| 114 @type events: C{int} | |
| 115 @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET. | |
| 116 | |
| 117 @raise IOError: Raised if the underlying epoll_ctl() call fails. | |
| 118 """ | |
| 119 cdef int result | |
| 120 cdef epoll_event evt | |
| 121 evt.events = events | |
| 122 evt.data.fd = fd | |
| 123 result = epoll_ctl(self.fd, op, fd, &evt) | |
| 124 if result == -1: | |
| 125 raise IOError(errno, strerror(errno)) | |
| 126 | |
| 127 def wait(self, unsigned int maxevents, int timeout): | |
| 128 """ | |
| 129 Wait for an I/O event, wrap epoll_wait(2). | |
| 130 | |
| 131 @type maxevents: C{int} | |
| 132 @param maxevents: Maximum number of events returned. | |
| 133 | |
| 134 @type timeout: C{int} | |
| 135 @param timeout: Maximum time waiting for events. 0 makes it return | |
| 136 immediately whereas -1 makes it wait indefinitely. | |
| 137 | |
| 138 @raise IOError: Raised if the underlying epoll_wait() call fails. | |
| 139 """ | |
| 140 cdef epoll_event *events | |
| 141 cdef int result | |
| 142 cdef int nbytes | |
| 143 cdef int fd | |
| 144 cdef PyThreadState *_save | |
| 145 | |
| 146 nbytes = sizeof(epoll_event) * maxevents | |
| 147 events = <epoll_event*>malloc(nbytes) | |
| 148 memset(events, 0, nbytes) | |
| 149 try: | |
| 150 fd = self.fd | |
| 151 | |
| 152 _save = PyEval_SaveThread() | |
| 153 result = epoll_wait(fd, events, maxevents, timeout) | |
| 154 PyEval_RestoreThread(_save) | |
| 155 | |
| 156 if result == -1: | |
| 157 raise IOError(errno, strerror(errno)) | |
| 158 results = [] | |
| 159 for i from 0 <= i < result: | |
| 160 results.append((events[i].data.fd, <int>events[i].events)) | |
| 161 return results | |
| 162 finally: | |
| 163 free(events) | |
| 164 | |
| 165 CTL_ADD = EPOLL_CTL_ADD | |
| 166 CTL_DEL = EPOLL_CTL_DEL | |
| 167 CTL_MOD = EPOLL_CTL_MOD | |
| 168 | |
| 169 IN = EPOLLIN | |
| 170 OUT = EPOLLOUT | |
| 171 PRI = EPOLLPRI | |
| 172 ERR = EPOLLERR | |
| 173 HUP = EPOLLHUP | |
| 174 ET = EPOLLET | |
| 175 | |
| 176 RDNORM = EPOLLRDNORM | |
| 177 RDBAND = EPOLLRDBAND | |
| 178 WRNORM = EPOLLWRNORM | |
| 179 WRBAND = EPOLLWRBAND | |
| 180 MSG = EPOLLMSG | |
| 181 | |
| OLD | NEW |