1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 Interface to epoll I/O event notification facility.
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
13 cdef extern from "stdio.h":
14 cdef extern void *malloc(int)
15 cdef extern void free(void *)
16 cdef extern int close(int)
18 cdef extern from "errno.h":
20 cdef extern char *strerror(int)
22 cdef extern from "string.h":
23 cdef extern void *memset(void* s, int c, int n)
25 cdef extern from "stdint.h":
26 ctypedef unsigned long uint32_t
27 ctypedef unsigned long long uint64_t
29 cdef extern from "sys/epoll.h":
36 cdef enum EPOLL_EVENTS:
37 c_EPOLLIN "EPOLLIN" = 0x001
38 c_EPOLLPRI "EPOLLPRI" = 0x002
39 c_EPOLLOUT "EPOLLOUT" = 0x004
40 c_EPOLLRDNORM "EPOLLRDNORM" = 0x040
41 c_EPOLLRDBAND "EPOLLRDBAND" = 0x080
42 c_EPOLLWRNORM "EPOLLWRNORM" = 0x100
43 c_EPOLLWRBAND "EPOLLWRBAND" = 0x200
44 c_EPOLLMSG "EPOLLMSG" = 0x400
45 c_EPOLLERR "EPOLLERR" = 0x008
46 c_EPOLLHUP "EPOLLHUP" = 0x010
47 c_EPOLLET "EPOLLET" = (1 << 31)
49 ctypedef union epoll_data_t:
55 cdef struct epoll_event:
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)
63 cdef extern from "Python.h":
64 ctypedef struct PyThreadState
65 cdef extern PyThreadState *PyEval_SaveThread()
66 cdef extern void PyEval_RestoreThread(PyThreadState*)
68 cdef call_epoll_wait(int fd, unsigned int maxevents, int timeout_msec):
70 Wait for an I/O event, wrap epoll_wait(2).
73 @param fd: The epoll file descriptor number.
75 @type maxevents: C{int}
76 @param maxevents: Maximum number of events returned.
78 @type timeout_msec: C{int}
79 @param timeout_msec: Maximum time in milliseconds waiting for events. 0
80 makes it return immediately whereas -1 makes it wait indefinitely.
82 @raise IOError: Raised if the underlying epoll_wait() call fails.
84 cdef epoll_event *events
87 cdef PyThreadState *_save
89 nbytes = sizeof(epoll_event) * maxevents
90 events = <epoll_event*>malloc(nbytes)
91 memset(events, 0, nbytes)
93 _save = PyEval_SaveThread()
94 result = epoll_wait(fd, events, maxevents, timeout_msec)
95 PyEval_RestoreThread(_save)
98 raise IOError(errno, strerror(errno))
100 for i from 0 <= i < result:
101 results.append((events[i].data.fd, <int>events[i].events))
108 Represent a set of file descriptors being monitored for events.
114 def __init__(self, int size=1023):
116 The constructor arguments are compatible with select.poll.__init__.
118 self.fd = epoll_create(size)
120 raise IOError(errno, strerror(errno))
123 def __dealloc__(self):
130 Close the epoll file descriptor.
133 if close(self.fd) == -1:
134 raise IOError(errno, strerror(errno))
139 Return the epoll file descriptor number.
143 def register(self, int fd, int events):
145 Add (register) a file descriptor to be monitored by self.
147 This method is compatible with select.epoll.register in Python 2.6.
152 @param fd: File descriptor to modify
155 @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.
157 @raise IOError: Raised if the underlying epoll_ctl() call fails.
163 result = epoll_ctl(self.fd, CTL_ADD, fd, &evt)
165 raise IOError(errno, strerror(errno))
167 def unregister(self, int fd):
169 Remove (unregister) a file descriptor monitored by self.
171 This method is compatible with select.epoll.unregister in Python 2.6.
176 @param fd: File descriptor to modify
178 @raise IOError: Raised if the underlying epoll_ctl() call fails.
182 # We don't have to fill evt.events for CTL_DEL.
184 result = epoll_ctl(self.fd, CTL_DEL, fd, &evt)
186 raise IOError(errno, strerror(errno))
188 def modify(self, int fd, int events):
190 Modify the modified state of a file descriptor monitored by self.
192 This method is compatible with select.epoll.modify in Python 2.6.
197 @param fd: File descriptor to modify
200 @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.
202 @raise IOError: Raised if the underlying epoll_ctl() call fails.
208 result = epoll_ctl(self.fd, CTL_MOD, fd, &evt)
210 raise IOError(errno, strerror(errno))
212 def _control(self, int op, int fd, int events):
214 Modify the monitored state of a particular file descriptor.
219 @param op: One of CTL_ADD, CTL_DEL, or CTL_MOD
222 @param fd: File descriptor to modify
225 @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.
227 @raise IOError: Raised if the underlying epoll_ctl() call fails.
233 result = epoll_ctl(self.fd, op, fd, &evt)
235 raise IOError(errno, strerror(errno))
237 def wait(self, unsigned int maxevents, int timeout):
239 Wait for an I/O event, wrap epoll_wait(2).
241 @type maxevents: C{int}
242 @param maxevents: Maximum number of events returned.
244 @type timeout: C{int}
245 @param timeout: Maximum time in milliseconds waiting for events. 0
246 makes it return immediately whereas -1 makes it wait indefinitely.
248 @raise IOError: Raised if the underlying epoll_wait() call fails.
250 return call_epoll_wait(self.fd, maxevents, timeout)
252 def poll(self, float timeout=-1, unsigned int maxevents=1024):
254 Wait for an I/O event, wrap epoll_wait(2).
256 This method is compatible with select.epoll.poll in Python 2.6.
258 @type maxevents: C{int}
259 @param maxevents: Maximum number of events returned.
261 @type timeout: C{int}
262 @param timeout: Maximum time waiting for events. 0 makes it return
263 immediately whereas -1 makes it wait indefinitely.
265 @raise IOError: Raised if the underlying epoll_wait() call fails.
267 return call_epoll_wait(self.fd, maxevents, <int>(timeout * 1000.0))
270 CTL_ADD = EPOLL_CTL_ADD
271 CTL_DEL = EPOLL_CTL_DEL
272 CTL_MOD = EPOLL_CTL_MOD
274 IN = EPOLLIN = c_EPOLLIN
275 OUT = EPOLLOUT = c_EPOLLOUT
276 PRI = EPOLLPRI = c_EPOLLPRI
277 ERR = EPOLLERR = c_EPOLLERR
278 HUP = EPOLLHUP = c_EPOLLHUP
279 ET = EPOLLET = c_EPOLLET
281 RDNORM = EPOLLRDNORM = c_EPOLLRDNORM
282 RDBAND = EPOLLRDBAND = c_EPOLLRDBAND
283 WRNORM = EPOLLWRNORM = c_EPOLLWRNORM
284 WRBAND = EPOLLWRBAND = c_EPOLLWRBAND
285 MSG = EPOLLMSG = c_EPOLLMSG