[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