Skip to content

Commit d8e0383

Browse files
committed
select: Add initial epoll implementation.
epoll is chosen as most efficient on Linux and FFI-friendly.
1 parent ef8aa98 commit d8e0383

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

select/select.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import ffi
2+
import struct
3+
import os
4+
5+
6+
libc = ffi.open("libc.so.6")
7+
8+
#int epoll_create(int size);
9+
epoll_create = libc.func("i", "epoll_create", "i")
10+
#int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
11+
epoll_ctl = libc.func("i", "epoll_ctl", "iiip")
12+
#int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
13+
epoll_wait = libc.func("i", "epoll_wait", "ipii")
14+
15+
EPOLLIN = 0x001
16+
EPOLLPRI = 0x002
17+
EPOLLOUT = 0x004
18+
19+
EPOLL_CTL_ADD = 1
20+
EPOLL_CTL_DEL = 2
21+
EPOLL_CTL_MOD = 3
22+
23+
24+
class Epoll:
25+
26+
def __init__(self, epfd):
27+
self.epfd = epfd
28+
self.evbuf = struct.pack("IQ", 0, 0)
29+
30+
def register(self, fd, eventmask=EPOLLIN|EPOLLPRI|EPOLLOUT, retval=None):
31+
if retval is None:
32+
retval = fd
33+
s = struct.pack("IQ", eventmask, retval)
34+
r = epoll_ctl(self.epfd, EPOLL_CTL_ADD, fd, s)
35+
os.check_error(r)
36+
37+
def poll(self, timeout=-1):
38+
s = bytearray(self.evbuf)
39+
n = epoll_wait(self.epfd, s, 1, timeout)
40+
os.check_error(n)
41+
res = []
42+
if n > 0:
43+
ev, h = struct.unpack("IQ", s)
44+
res.append((h, ev))
45+
return res
46+
47+
48+
def epoll():
49+
fd = epoll_create(4)
50+
os.check_error(fd)
51+
return Epoll(fd)

0 commit comments

Comments
 (0)