2014-04-19 17:36:23 +00:00
|
|
|
import ffi
|
|
|
|
import struct
|
|
|
|
import os
|
2014-04-21 21:33:13 +00:00
|
|
|
import errno
|
2014-04-19 17:36:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
libc = ffi.open("libc.so.6")
|
|
|
|
|
|
|
|
#int epoll_create(int size);
|
|
|
|
epoll_create = libc.func("i", "epoll_create", "i")
|
|
|
|
#int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
|
2014-04-21 21:39:21 +00:00
|
|
|
epoll_ctl = libc.func("i", "epoll_ctl", "iiiP")
|
2014-04-19 17:36:23 +00:00
|
|
|
#int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
|
|
|
|
epoll_wait = libc.func("i", "epoll_wait", "ipii")
|
|
|
|
|
|
|
|
EPOLLIN = 0x001
|
|
|
|
EPOLLPRI = 0x002
|
|
|
|
EPOLLOUT = 0x004
|
|
|
|
|
|
|
|
EPOLL_CTL_ADD = 1
|
|
|
|
EPOLL_CTL_DEL = 2
|
|
|
|
EPOLL_CTL_MOD = 3
|
|
|
|
|
|
|
|
|
|
|
|
class Epoll:
|
|
|
|
|
2014-04-19 20:41:35 +00:00
|
|
|
# Second value is actually of uint64_t size, so struct
|
|
|
|
# will be smaller on 32bit, but seem to not segfault.
|
|
|
|
epoll_event = "IO"
|
|
|
|
|
2014-04-19 17:36:23 +00:00
|
|
|
def __init__(self, epfd):
|
|
|
|
self.epfd = epfd
|
2014-04-19 20:41:35 +00:00
|
|
|
self.evbuf = struct.pack(self.epoll_event, 0, 0)
|
2014-04-19 17:36:23 +00:00
|
|
|
|
|
|
|
def register(self, fd, eventmask=EPOLLIN|EPOLLPRI|EPOLLOUT, retval=None):
|
2014-04-19 20:41:35 +00:00
|
|
|
"retval is extension to stdlib, value to use in results from .poll()."
|
2014-04-19 17:36:23 +00:00
|
|
|
if retval is None:
|
|
|
|
retval = fd
|
2014-04-19 20:41:35 +00:00
|
|
|
s = struct.pack(self.epoll_event, eventmask, retval)
|
2014-04-19 17:36:23 +00:00
|
|
|
r = epoll_ctl(self.epfd, EPOLL_CTL_ADD, fd, s)
|
2014-04-21 21:33:13 +00:00
|
|
|
if r == -1 and os.errno.get() == errno.EEXIST:
|
2014-04-20 03:10:27 +00:00
|
|
|
r = epoll_ctl(self.epfd, EPOLL_CTL_MOD, fd, s)
|
2014-04-19 17:36:23 +00:00
|
|
|
os.check_error(r)
|
|
|
|
|
2014-04-23 21:59:43 +00:00
|
|
|
def unregister(self, fd):
|
|
|
|
# Pass dummy event structure, to workaround kernel bug
|
|
|
|
r = epoll_ctl(self.epfd, EPOLL_CTL_DEL, fd, self.evbuf)
|
|
|
|
os.check_error(r)
|
|
|
|
|
2014-04-19 17:36:23 +00:00
|
|
|
def poll(self, timeout=-1):
|
|
|
|
s = bytearray(self.evbuf)
|
|
|
|
n = epoll_wait(self.epfd, s, 1, timeout)
|
|
|
|
os.check_error(n)
|
|
|
|
res = []
|
|
|
|
if n > 0:
|
2014-04-19 20:41:35 +00:00
|
|
|
vals = struct.unpack(self.epoll_event, s)
|
|
|
|
res.append((vals[1], vals[0]))
|
2014-04-19 17:36:23 +00:00
|
|
|
return res
|
|
|
|
|
|
|
|
|
2014-04-19 20:08:42 +00:00
|
|
|
def epoll(sizehint=4):
|
|
|
|
fd = epoll_create(sizehint)
|
2014-04-19 17:36:23 +00:00
|
|
|
os.check_error(fd)
|
|
|
|
return Epoll(fd)
|