@@ -339,92 +339,86 @@ def select(self, timeout=None):
339339 return ready
340340
341341
342- if hasattr (select , 'poll' ):
342+ class _PollLikeSelector (_BaseSelectorImpl ):
343+ """Base class shared between poll, epoll and devpoll selectors."""
344+ _selector_cls = None
343345
344- class PollSelector (_BaseSelectorImpl ):
345- """Poll-based selector."""
346+ def __init__ (self ):
347+ super ().__init__ ()
348+ self ._selector = self ._selector_cls ()
346349
347- def __init__ (self ):
348- super ().__init__ ()
349- 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 ._selector .register (key .fd , poller_events )
359+ except Exception :
360+ super ().unregister (fileobj )
361+ raise
362+ return key
350363
351- def register (self , fileobj , events , data = None ):
352- key = super ().register (fileobj , events , data )
353- poll_events = 0
354- if events & EVENT_READ :
355- poll_events |= select . POLLIN
356- if events & EVENT_WRITE :
357- poll_events |= select . POLLOUT
358- self . _poll . register ( key . fd , poll_events )
359- return key
364+ def unregister (self , fileobj ):
365+ key = super ().unregister (fileobj )
366+ try :
367+ self . _selector . 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
360373
361- def unregister (self , fileobj ):
362- key = super ().unregister (fileobj )
363- self ._poll .unregister (key .fd )
364- 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 ._selector .poll (timeout )
388+ except InterruptedError :
389+ return ready
390+ for fd , event in fd_event_list :
391+ events = 0
392+ if event & ~ self ._EVENT_READ :
393+ events |= EVENT_WRITE
394+ if event & ~ self ._EVENT_WRITE :
395+ events |= EVENT_READ
365396
366- def select (self , timeout = None ):
367- if timeout is None :
368- timeout = None
369- elif timeout <= 0 :
370- timeout = 0
371- else :
372- # poll() has a resolution of 1 millisecond, round away from
373- # zero to wait *at least* timeout seconds.
374- timeout = math .ceil (timeout * 1e3 )
375- ready = []
376- try :
377- fd_event_list = self ._poll .poll (timeout )
378- except InterruptedError :
379- return ready
380- for fd , event in fd_event_list :
381- events = 0
382- if event & ~ select .POLLIN :
383- events |= EVENT_WRITE
384- if event & ~ select .POLLOUT :
385- events |= EVENT_READ
397+ key = self ._key_from_fd (fd )
398+ if key :
399+ ready .append ((key , events & key .events ))
400+ return ready
386401
387- key = self ._key_from_fd (fd )
388- if key :
389- ready .append ((key , events & key .events ))
390- return ready
402+
403+ if hasattr (select , 'poll' ):
404+
405+ class PollSelector (_PollLikeSelector ):
406+ """Poll-based selector."""
407+ _selector_cls = select .poll
408+ _EVENT_READ = select .POLLIN
409+ _EVENT_WRITE = select .POLLOUT
391410
392411
393412if hasattr (select , 'epoll' ):
394413
395- class EpollSelector (_BaseSelectorImpl ):
414+ class EpollSelector (_PollLikeSelector ):
396415 """Epoll-based selector."""
397-
398- def __init__ (self ):
399- super ().__init__ ()
400- self ._epoll = select .epoll ()
416+ _selector_cls = select .epoll
417+ _EVENT_READ = select .EPOLLIN
418+ _EVENT_WRITE = select .EPOLLOUT
401419
402420 def fileno (self ):
403- return self ._epoll .fileno ()
404-
405- def register (self , fileobj , events , data = None ):
406- key = super ().register (fileobj , events , data )
407- epoll_events = 0
408- if events & EVENT_READ :
409- epoll_events |= select .EPOLLIN
410- if events & EVENT_WRITE :
411- epoll_events |= select .EPOLLOUT
412- try :
413- self ._epoll .register (key .fd , epoll_events )
414- except BaseException :
415- super ().unregister (fileobj )
416- raise
417- return key
418-
419- def unregister (self , fileobj ):
420- key = super ().unregister (fileobj )
421- try :
422- self ._epoll .unregister (key .fd )
423- except OSError :
424- # This can happen if the FD was closed since it
425- # was registered.
426- pass
427- return key
421+ return self ._selector .fileno ()
428422
429423 def select (self , timeout = None ):
430424 if timeout is None :
@@ -443,7 +437,7 @@ def select(self, timeout=None):
443437
444438 ready = []
445439 try :
446- fd_event_list = self ._epoll .poll (timeout , max_ev )
440+ fd_event_list = self ._selector .poll (timeout , max_ev )
447441 except InterruptedError :
448442 return ready
449443 for fd , event in fd_event_list :
@@ -459,65 +453,23 @@ def select(self, timeout=None):
459453 return ready
460454
461455 def close (self ):
462- self ._epoll .close ()
456+ self ._selector .close ()
463457 super ().close ()
464458
465459
466460if hasattr (select , 'devpoll' ):
467461
468- class DevpollSelector (_BaseSelectorImpl ):
462+ class DevpollSelector (_PollLikeSelector ):
469463 """Solaris /dev/poll selector."""
470-
471- def __init__ (self ):
472- super ().__init__ ()
473- self ._devpoll = select .devpoll ()
464+ _selector_cls = select .devpoll
465+ _EVENT_READ = select .POLLIN
466+ _EVENT_WRITE = select .POLLOUT
474467
475468 def fileno (self ):
476- return self ._devpoll .fileno ()
477-
478- def register (self , fileobj , events , data = None ):
479- key = super ().register (fileobj , events , data )
480- poll_events = 0
481- if events & EVENT_READ :
482- poll_events |= select .POLLIN
483- if events & EVENT_WRITE :
484- poll_events |= select .POLLOUT
485- self ._devpoll .register (key .fd , poll_events )
486- return key
487-
488- def unregister (self , fileobj ):
489- key = super ().unregister (fileobj )
490- self ._devpoll .unregister (key .fd )
491- return key
492-
493- def select (self , timeout = None ):
494- if timeout is None :
495- timeout = None
496- elif timeout <= 0 :
497- timeout = 0
498- else :
499- # devpoll() has a resolution of 1 millisecond, round away from
500- # zero to wait *at least* timeout seconds.
501- timeout = math .ceil (timeout * 1e3 )
502- ready = []
503- try :
504- fd_event_list = self ._devpoll .poll (timeout )
505- except InterruptedError :
506- return ready
507- for fd , event in fd_event_list :
508- events = 0
509- if event & ~ select .POLLIN :
510- events |= EVENT_WRITE
511- if event & ~ select .POLLOUT :
512- events |= EVENT_READ
513-
514- key = self ._key_from_fd (fd )
515- if key :
516- ready .append ((key , events & key .events ))
517- return ready
469+ return self ._selector .fileno ()
518470
519471 def close (self ):
520- self ._devpoll .close ()
472+ self ._selector .close ()
521473 super ().close ()
522474
523475
@@ -528,23 +480,23 @@ class KqueueSelector(_BaseSelectorImpl):
528480
529481 def __init__ (self ):
530482 super ().__init__ ()
531- self ._kqueue = select .kqueue ()
483+ self ._selector = select .kqueue ()
532484
533485 def fileno (self ):
534- return self ._kqueue .fileno ()
486+ return self ._selector .fileno ()
535487
536488 def register (self , fileobj , events , data = None ):
537489 key = super ().register (fileobj , events , data )
538490 try :
539491 if events & EVENT_READ :
540492 kev = select .kevent (key .fd , select .KQ_FILTER_READ ,
541493 select .KQ_EV_ADD )
542- self ._kqueue .control ([kev ], 0 , 0 )
494+ self ._selector .control ([kev ], 0 , 0 )
543495 if events & EVENT_WRITE :
544496 kev = select .kevent (key .fd , select .KQ_FILTER_WRITE ,
545497 select .KQ_EV_ADD )
546- self ._kqueue .control ([kev ], 0 , 0 )
547- except BaseException :
498+ self ._selector .control ([kev ], 0 , 0 )
499+ except Exception :
548500 super ().unregister (fileobj )
549501 raise
550502 return key
@@ -555,7 +507,7 @@ def unregister(self, fileobj):
555507 kev = select .kevent (key .fd , select .KQ_FILTER_READ ,
556508 select .KQ_EV_DELETE )
557509 try :
558- self ._kqueue .control ([kev ], 0 , 0 )
510+ self ._selector .control ([kev ], 0 , 0 )
559511 except OSError :
560512 # This can happen if the FD was closed since it
561513 # was registered.
@@ -564,7 +516,7 @@ def unregister(self, fileobj):
564516 kev = select .kevent (key .fd , select .KQ_FILTER_WRITE ,
565517 select .KQ_EV_DELETE )
566518 try :
567- self ._kqueue .control ([kev ], 0 , 0 )
519+ self ._selector .control ([kev ], 0 , 0 )
568520 except OSError :
569521 # See comment above.
570522 pass
@@ -575,7 +527,7 @@ def select(self, timeout=None):
575527 max_ev = len (self ._fd_to_key )
576528 ready = []
577529 try :
578- kev_list = self ._kqueue .control (None , max_ev , timeout )
530+ kev_list = self ._selector .control (None , max_ev , timeout )
579531 except InterruptedError :
580532 return ready
581533 for kev in kev_list :
@@ -593,7 +545,7 @@ def select(self, timeout=None):
593545 return ready
594546
595547 def close (self ):
596- self ._kqueue .close ()
548+ self ._selector .close ()
597549 super ().close ()
598550
599551
0 commit comments