[pypy-svn] r46828 - in pypy/dist/pypy/rlib: . test
arigo at codespeak.net
arigo at codespeak.net
Sat Sep 22 17:55:23 CEST 2007
Author: arigo
Date: Sat Sep 22 17:55:23 2007
New Revision: 46828
Added:
pypy/dist/pypy/rlib/rpoll.py
pypy/dist/pypy/rlib/test/test_rpoll.py
Modified:
pypy/dist/pypy/rlib/_rsocket_rffi.py
pypy/dist/pypy/rlib/rsocket.py
Log:
Writing pypy.rlib.rpoll.
Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py
==============================================================================
--- pypy/dist/pypy/rlib/_rsocket_rffi.py (original)
+++ pypy/dist/pypy/rlib/_rsocket_rffi.py Sat Sep 22 17:55:23 2007
@@ -482,7 +482,9 @@
rffi.INT)
if _POSIX:
- poll = external('poll', [lltype.Ptr(pollfd), nfds_t, rffi.INT], rffi.INT)
+ pollfdarray = rffi.CArray(pollfd)
+ poll = external('poll', [lltype.Ptr(pollfdarray), nfds_t, rffi.INT],
+ rffi.INT)
elif MS_WINDOWS:
select = external('select',
[rffi.INT, lltype.Ptr(fd_set), lltype.Ptr(fd_set),
Added: pypy/dist/pypy/rlib/rpoll.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/rpoll.py Sat Sep 22 17:55:23 2007
@@ -0,0 +1,61 @@
+"""
+An RPython implementation of select.poll() based on rffi.
+Note that this is not a drop-in replacement: the interface is
+simplified - instead of a polling object there is only a poll()
+function that directly takes a dictionary as argument.
+"""
+
+import os
+from pypy.rlib import _rsocket_rffi as _c
+from pypy.rpython.lltypesystem import lltype, rffi
+
+# ____________________________________________________________
+# events
+#
+eventnames = '''POLLIN POLLPRI POLLOUT POLLERR POLLHUP POLLNVAL
+ POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG'''.split()
+
+eventnames = [name for name in eventnames
+ if getattr(_c.cConfig, name) is not None]
+
+for name in eventnames:
+ globals()[name] = getattr(_c.cConfig, name)
+
+# ____________________________________________________________
+# poll()
+#
+class PollError(Exception):
+ def __init__(self, errno):
+ self.errno = errno
+ def get_msg(self):
+ return os.strerror(self.errno)
+
+def poll(fddict, timeout=-1):
+ """'fddict' maps file descriptors to interesting events.
+ 'timeout' is an integer in milliseconds, and NOT a float
+ number of seconds, but it's the same in CPython. Use -1 for infinite.
+ Returns a list [(fd, events)].
+ """
+ numfd = len(fddict)
+ pollfds = lltype.malloc(_c.pollfdarray, numfd, flavor='raw')
+ try:
+ i = 0
+ for fd, events in fddict.iteritems():
+ rffi.setintfield(pollfds[i], 'c_fd', fd)
+ rffi.setintfield(pollfds[i], 'c_events', events)
+ i += 1
+ assert i == numfd
+
+ ret = _c.poll(pollfds, numfd, timeout)
+
+ if ret < 0:
+ raise PollError(_c.geterrno())
+
+ retval = []
+ for i in range(numfd):
+ pollfd = pollfds[i]
+ if pollfd.c_revents:
+ retval.append((pollfd.c_fd, pollfd.c_revents))
+ finally:
+ lltype.free(pollfds, flavor='raw')
+ return retval
Modified: pypy/dist/pypy/rlib/rsocket.py
==============================================================================
--- pypy/dist/pypy/rlib/rsocket.py (original)
+++ pypy/dist/pypy/rlib/rsocket.py Sat Sep 22 17:55:23 2007
@@ -556,7 +556,8 @@
else:
rffi.setintfield(pollfd, 'c_events', _c.POLLIN)
timeout = int(self.timeout * 1000.0 + 0.5)
- n = _c.poll(pollfd, 1, timeout)
+ n = _c.poll(rffi.cast(lltype.Ptr(_c.pollfdarray), pollfd),
+ 1, timeout)
finally:
lltype.free(pollfd, flavor='raw')
if n < 0:
Added: pypy/dist/pypy/rlib/test/test_rpoll.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/test/test_rpoll.py Sat Sep 22 17:55:23 2007
@@ -0,0 +1,45 @@
+import thread
+from pypy.rlib.rsocket import *
+from pypy.rlib.rpoll import *
+
+def test_simple():
+ serv = RSocket(AF_INET, SOCK_STREAM)
+ serv.bind(INETAddress('127.0.0.1', INADDR_ANY))
+ serv.listen(1)
+ servaddr = serv.getsockname()
+
+ events = poll({serv.fileno(): POLLIN}, timeout=100)
+ assert len(events) == 0
+
+ cli = RSocket(AF_INET, SOCK_STREAM)
+ cli.setblocking(False)
+ err = cli.connect_ex(servaddr)
+ assert err != 0
+
+ events = poll({serv.fileno(): POLLIN}, timeout=500)
+ assert len(events) == 1
+ assert events[0][0] == serv.fileno()
+ assert events[0][1] & POLLIN
+
+ servconn, cliaddr = serv.accept()
+
+ events = poll({serv.fileno(): POLLIN,
+ cli.fileno(): POLLOUT}, timeout=500)
+ assert len(events) == 1
+ assert events[0][0] == cli.fileno()
+ assert events[0][1] & POLLOUT
+
+ err = cli.connect_ex(servaddr)
+ assert err == 0
+
+ events = poll({servconn.fileno(): POLLIN,
+ cli.fileno(): POLLIN}, timeout=100)
+ assert len(events) == 0
+
+ events = poll({servconn.fileno(): POLLOUT,
+ cli.fileno(): POLLOUT}, timeout=100)
+ assert len(events) >= 1
+
+ cli.close()
+ servconn.close()
+ serv.close()
More information about the Pypy-commit
mailing list