summaryrefslogtreecommitdiff
path: root/Lib/selectors.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/selectors.py')
-rw-r--r--Lib/selectors.py77
1 files changed, 67 insertions, 10 deletions
diff --git a/Lib/selectors.py b/Lib/selectors.py
index 7b6da29863..6d569c30ad 100644
--- a/Lib/selectors.py
+++ b/Lib/selectors.py
@@ -174,9 +174,9 @@ class BaseSelector(metaclass=ABCMeta):
SelectorKey for this file object
"""
mapping = self.get_map()
+ if mapping is None:
+ raise RuntimeError('Selector is closed')
try:
- if mapping is None:
- raise KeyError
return mapping[fileobj]
except KeyError:
raise KeyError("{!r} is not registered".format(fileobj)) from None
@@ -445,10 +445,66 @@ if hasattr(select, 'epoll'):
return ready
def close(self):
+ self._epoll.close()
+ super().close()
+
+
+if hasattr(select, 'devpoll'):
+
+ class DevpollSelector(_BaseSelectorImpl):
+ """Solaris /dev/poll selector."""
+
+ def __init__(self):
+ super().__init__()
+ self._devpoll = select.devpoll()
+
+ def fileno(self):
+ return self._devpoll.fileno()
+
+ def register(self, fileobj, events, data=None):
+ key = super().register(fileobj, events, data)
+ poll_events = 0
+ if events & EVENT_READ:
+ poll_events |= select.POLLIN
+ if events & EVENT_WRITE:
+ poll_events |= select.POLLOUT
+ self._devpoll.register(key.fd, poll_events)
+ return key
+
+ def unregister(self, fileobj):
+ key = super().unregister(fileobj)
+ self._devpoll.unregister(key.fd)
+ return key
+
+ def select(self, timeout=None):
+ if timeout is None:
+ timeout = None
+ elif timeout <= 0:
+ timeout = 0
+ else:
+ # devpoll() has a resolution of 1 millisecond, round away from
+ # zero to wait *at least* timeout seconds.
+ timeout = math.ceil(timeout * 1e3)
+ ready = []
try:
- self._epoll.close()
- finally:
- super().close()
+ fd_event_list = self._devpoll.poll(timeout)
+ except InterruptedError:
+ return ready
+ for fd, event in fd_event_list:
+ events = 0
+ if event & ~select.POLLIN:
+ events |= EVENT_WRITE
+ if event & ~select.POLLOUT:
+ events |= EVENT_READ
+
+ key = self._key_from_fd(fd)
+ if key:
+ ready.append((key, events & key.events))
+ return ready
+
+ def close(self):
+ self._devpoll.close()
+ super().close()
if hasattr(select, 'kqueue'):
@@ -519,18 +575,19 @@ if hasattr(select, 'kqueue'):
return ready
def close(self):
- try:
- self._kqueue.close()
- finally:
- super().close()
+ self._kqueue.close()
+ super().close()
-# Choose the best implementation: roughly, epoll|kqueue > poll > select.
+# Choose the best implementation, roughly:
+# epoll|kqueue|devpoll > poll > select.
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
if 'KqueueSelector' in globals():
DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
DefaultSelector = EpollSelector
+elif 'DevpollSelector' in globals():
+ DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
DefaultSelector = PollSelector
else: