1
# Copyright (c) 2001-2006 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:
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*)
70
Represent a set of file descriptors being monitored for events.
76
def __init__(self, int size):
77
self.fd = epoll_create(size)
79
raise IOError(errno, strerror(errno))
82
def __dealloc__(self):
89
Close the epoll file descriptor.
92
if close(self.fd) == -1:
93
raise IOError(errno, strerror(errno))
98
Return the epoll file descriptor number.
102
def _control(self, int op, int fd, int events):
104
Modify the monitored state of a particular file descriptor.
109
@param op: One of CTL_ADD, CTL_DEL, or CTL_MOD
112
@param fd: File descriptor to modify
115
@param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.
117
@raise IOError: Raised if the underlying epoll_ctl() call fails.
123
result = epoll_ctl(self.fd, op, fd, &evt)
125
raise IOError(errno, strerror(errno))
127
def wait(self, unsigned int maxevents, int timeout):
129
Wait for an I/O event, wrap epoll_wait(2).
131
@type maxevents: C{int}
132
@param maxevents: Maximum number of events returned.
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.
138
@raise IOError: Raised if the underlying epoll_wait() call fails.
140
cdef epoll_event *events
144
cdef PyThreadState *_save
146
nbytes = sizeof(epoll_event) * maxevents
147
events = <epoll_event*>malloc(nbytes)
148
memset(events, 0, nbytes)
152
_save = PyEval_SaveThread()
153
result = epoll_wait(fd, events, maxevents, timeout)
154
PyEval_RestoreThread(_save)
157
raise IOError(errno, strerror(errno))
159
for i from 0 <= i < result:
160
results.append((events[i].data.fd, <int>events[i].events))
165
CTL_ADD = EPOLL_CTL_ADD
166
CTL_DEL = EPOLL_CTL_DEL
167
CTL_MOD = EPOLL_CTL_MOD