8000 #30014: refactor poll-related classes so that poll(), epoll() and dev… · xiaolanpython/cpython@29b6fee · GitHub
[go: up one dir, main page]

Skip to content

Commit 29b6fee

Browse files
committed
python#30014: refactor poll-related classes so that poll(), epoll() and devpoll() share the same methods for register(), unregister(), close() and select()
1 parent fd0cd07 commit 29b6fee

File tree

1 file changed

+78
-128
lines changed

1 file changed

+78
-128
lines changed

Lib/selectors.py

Lines changed: 78 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -338,92 +338,92 @@ def select(self, timeout=None):
338338
return ready
339339

340340

341-
if hasattr(select, 'poll'):
341+
class _PollLikeSelector(_BaseSelectorImpl):
342+
"""Base class shared between poll, epoll and devpoll selectors."""
342343

343-
class PollSelector(_BaseSelectorImpl):
344-
"""Poll-based selector."""
344+
def __init__(self):
345+
super().__init__()
346+
self._poller = self._poller()
347+
self._is_epoll = hasattr(select, "epoll") and \
348+
isinstance(self._poller, select.epoll)
345349

346-
def __init__(self):
347-
super().__init__()
348-
self._poll = select.poll()
350+
def register(self, fileobj, events, data=None):
351+
key = super().register(fileobj, events, data)
352+
poller_events = 0
353+
if events & EVENT_READ:
354+
poller_events |= self._EVENT_READ
355+
if events & EVENT_WRITE:
356+
poller_events |= self._EVENT_WRITE
357+
try:
358+
self._poller.register(key.fd, poller_events)
359+
except BaseException:
360+
super().unregister(fileobj)
361+
raise
362+
return key
349363

350-
def register(self, fileobj, events, data=None):
351-
key = super().register(fileobj, events, data)
352-
poll_events = 0
353-
if events & EVENT_READ:
354-
poll_events |= select.POLLIN
355-
if events & EVENT_WRITE:
356-
poll_events |= select.POLLOUT
357-
self._poll.register(key.fd, poll_events)
358-
return key
364+
def unregister(self, fileobj):
365+
key = super().unregister(fileobj)
366+
try:
367+
self._poller.unregister(key.fd)
368+
except OSError:
369+
# This can happen if the FD was closed since it
370+
# was registered.
371+
pass
372+
return key
359373

360-
def unregister(self, fileobj):
361-
key = super().unregister(fileobj)
362-
self._poll.unregister(key.fd)
363-
return key
374+
def select(self, timeout=None):
375+
# This is shared between poll() and epoll().
376+
# epoll() has a different signature and handling of timeout parameter.
377+
if timeout is None:
378+
timeout = None
379+
elif timeout <= 0:
380+
timeout = 0
381+
else:
382+
# poll() has a resolution of 1 millisecond, round away from
383+
# zero to wait *at least* timeout seconds.
384+
timeout = math.ceil(timeout * 1e3)
385+
ready = []
386+
try:
387+
fd_event_list = self._poller.poll(timeout)
388+
except InterruptedError:
389+
return ready
390+
for fd, event in fd_event_list:
391+
events = 0
392+
if event & ~select.POLLIN:
393+
events |= EVENT_WRITE
394+
if event & ~select.POLLOUT:
395+
events |= EVENT_READ
364396

365-
def select(self, timeout=None):
366-
if timeout is None:
367-
timeout = None
368-
elif timeout <= 0:
369-
timeout = 0
370-
else:
371-
# poll() has a resolution of 1 millisecond, round away from
372-
# zero to wait *at least* timeout seconds.
373-
timeout = math.ceil(timeout * 1e3)
374-
ready = []
375-
try:
376-
fd_event_list = self._poll.poll(timeout)
377-
except InterruptedError:
378-
return ready
379-
for fd, event in fd_event_list:
380-
events = 0
381 28BE -
if event & ~select.POLLIN:
382-
events |= EVENT_WRITE
383-
if event & ~select.POLLOUT:
384-
events |= EVENT_READ
397+
key = self._key_from_fd(fd)
398+
if key:
399+
ready.append((key, events & key.events))
400+
return ready
385401

386-
key = self._key_from_fd(fd)
387-
if key:
388-
ready.append((key, events & key.events))
389-
return ready
402+
def close(self):
403+
if hasattr(self._poller, "close"):
404+
self._poller.close()
405+
super().close()
390406

391407

392-
if hasattr(select, 'epoll'):
408+
if hasattr(select, 'poll'):
393409

394-
class EpollSelector(_BaseSelectorImpl):
395-
"""Epoll-based selector."""
410+
class PollSelector(_PollLikeSelector):
411+
"""Poll-based selector."""
412+
_poller = select.poll
413+
_EVENT_READ = select.POLLIN
414+
_EVENT_WRITE = select.POLLOUT
396415

397-
def __init__(self):
398-
super().__init__()
399-
self._epoll = select.epoll()
400416

401-
def fileno(self):
402-
return self._epoll.fileno()
417+
if hasattr(select, 'epoll'):
403418

404-
def register(self, fileobj, events, data=None):
405-
key = super().register(fileobj, events, data)
406-
epoll_events = 0
407-
if events & EVENT_READ:
408-
epoll_events |= select.EPOLLIN
409-
if events & EVENT_WRITE:
410-
epoll_events |= select.EPOLLOUT
411-
try:
412-
self._epoll.register(key.fd, epoll_events)
413-
except BaseException:
414-
super().unregister(fileobj)
415-
raise
416-
return key
419+
class EpollSelector(_PollLikeSelector):
420+
"""Epoll-based selector."""
421+
_poller = select.epoll
422+
_EVENT_READ = select.EPOLLIN
423+
_EVENT_WRITE = select.EPOLLOUT
417424

418-
def unregister(self, fileobj):
419-
key = super().unregister(fileobj)
420-
try:
421-
self._epoll.unregister(key.fd)
422-
except OSError:
423-
# This can happen if the FD was closed since it
424-
# was registered.
425-
pass
426-
return key
425+
def fileno(self):
426+
return self._poller.fileno()
427427

428428
def select(self, timeout=None):
429429
if timeout is None:
@@ -442,7 +442,7 @@ def select(self, timeout=None):
442442

443443
ready = []
444444
try:
445-
fd_event_list = self._epoll.poll(timeout, max_ev)
445+
fd_event_list = self._poller.poll(timeout, max_ev)
446446
except InterruptedError:
447447
return ready
448448
for fd, event in fd_event_list:
@@ -457,68 +457,18 @@ def select(self, timeout=None):
457457
ready.append((key, events & key.events))
458458
return ready
459459

460-
def close(self):
461-
self._epoll.close()
462-
super().close()
463-
464460

465461
if hasattr(select, 'devpoll'):
466462

467-
class DevpollSelector(_BaseSelectorImpl):
463+
class DevpollSelector(_PollLikeSelector):
468464
"""Solaris /dev/poll selector."""
469-
470-
def __init__(self):
471-
super().__init__()
472-
self._devpoll = select.devpoll()
465+
_poller = select.devpoll
466+
_EVENT_READ = select.POLLIN
467+
_EVENT_WRITE = select.POLLOUT
473468

474469
def fileno(self):
475470
return self._devpoll.fileno()
476471

477-
def register(self, fileobj, events, data=None):
478-
key = super().register(fileobj, events, data)
479-
poll_events = 0
480-
if events & EVENT_READ:
481-
poll_events |= select.POLLIN
482-
if events & EVENT_WRITE:
483-
poll_events |= select.POLLOUT
484-
self._devpoll.register(key.fd, poll_events)
485-
return key
486-
487-
def unregister(self, fileobj):
488-
key = super().unregister(fileobj)
489-
self._devpoll.unregister(key.fd)
490-
return key
491-
492-
def select(self, timeout=None):
493-
if timeout is None:
494-
timeout = None
495-
elif timeout <= 0:
496-
timeout = 0
497-
else:
498-
# devpoll() has a resolution of 1 millisecond, round away from
499-
# zero to wait *at least* timeout seconds.
500-
timeout = math.ceil(timeout * 1e3)
501-
ready = []
502-
try:
503-
fd_event_list = self._devpoll.poll(timeout)
504-
except InterruptedError:
505-
return ready
506-
for fd, event in fd_event_list:
507-
events = 0
508-
if event & ~select.POLLIN:
509-
events |= EVENT_WRITE
510-
if event & ~select.POLLOUT:
511-
events |= EVENT_READ
512-
513-
key = self._key_from_fd(fd)
514-
if key:
515-
ready.append((key, events & key.events))
516-
return ready
517-
518-
def close(self):
519-
self._devpoll.close()
520-
super().close()
521-
522472

523473
if hasattr(select, 'kqueue'):
524474

0 commit comments

Comments
 (0)
0