@@ -339,92 +339,86 @@ def select(self, timeout=None):
339
339
return ready
340
340
341
341
342
- if hasattr (select , 'poll' ):
342
+ class _PollLikeSelector (_BaseSelectorImpl ):
343
+ """Base class shared between poll, epoll and devpoll selectors."""
344
+ _selector_cls = None
343
345
344
- class PollSelector (_BaseSelectorImpl ):
345
- """Poll-based selector."""
346
+ def __init__ (self ):
347
+ super ().__init__ ()
348
+ self ._selector = self ._selector_cls ()
346
349
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
350
363
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
360
373
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
365
396
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
386
401
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
391
410
392
411
393
412
if hasattr (select , 'epoll' ):
394
413
395
- class EpollSelector (_BaseSelectorImpl ):
414
+ class EpollSelector (_PollLikeSelector ):
396
415
"""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
401
419
402
420
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 ()
428
422
429
423
def select (self , timeout = None ):
430
424
if timeout is None :
@@ -443,7 +437,7 @@ def select(self, timeout=None):
443
437
444
438
ready = []
445
439
try :
446
- fd_event_list = self ._epoll .poll (timeout , max_ev )
440
+ fd_event_list = self ._selector .poll (timeout , max_ev )
447
441
except InterruptedError :
448
442
return ready
449
443
for fd , event in fd_event_list :
@@ -459,65 +453,23 @@ def select(self, timeout=None):
459
453
return ready
460
454
461
455
def close (self ):
462
- self ._epoll .close ()
456
+ self ._selector .close ()
463
457
super ().close ()
464
458
465
459
466
460
if hasattr (select , 'devpoll' ):
467
461
468
- class DevpollSelector (_BaseSelectorImpl ):
462
+ class DevpollSelector (_PollLikeSelector ):
469
463
"""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
474
467
475
468
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 ()
518
470
519
471
def close (self ):
520
- self ._devpoll .close ()
472
+ self ._selector .close ()
521
473
super ().close ()
522
474
523
475
@@ -528,23 +480,23 @@ class KqueueSelector(_BaseSelectorImpl):
528
480
529
481
def __init__ (self ):
530
482
super ().__init__ ()
531
- self ._kqueue = select .kqueue ()
483
+ self ._selector = select .kqueue ()
532
484
533
485
def fileno (self ):
534
- return self ._kqueue .fileno ()
486
+ return self ._selector .fileno ()
535
487
536
488
def register (self , fileobj , events , data = None ):
537
489
key = super ().register (fileobj , events , data )
538
490
try :
539
491
if events & EVENT_READ :
540
492
kev = select .kevent (key .fd , select .KQ_FILTER_READ ,
541
493
select .KQ_EV_ADD )
542
- self ._kqueue .control ([kev ], 0 , 0 )
494
+ self ._selector .control ([kev ], 0 , 0 )
543
495
if events & EVENT_WRITE :
544
496
kev = select .kevent (key .fd , select .KQ_FILTER_WRITE ,
545
497
select .KQ_EV_ADD )
546
- self ._kqueue .control ([kev ], 0 , 0 )
547
- except BaseException :
498
+ self ._selector .control ([kev ], 0 , 0 )
499
+ except Exception :
548
500
super ().unregister (fileobj )
549
501
raise
550
502
return key
@@ -555,7 +507,7 @@ def unregister(self, fileobj):
555
507
kev = select .kevent (key .fd , select .KQ_FILTER_READ ,
556
508
select .KQ_EV_DELETE )
557
509
try :
558
- self ._kqueue .control ([kev ], 0 , 0 )
510
+ self ._selector .control ([kev ], 0 , 0 )
559
511
except OSError :
560
512
# This can happen if the FD was closed since it
561
513
# was registered.
@@ -564,7 +516,7 @@ def unregister(self, fileobj):
564
516
kev = select .kevent (key .fd , select .KQ_FILTER_WRITE ,
565
517
select .KQ_EV_DELETE )
566
518
try :
567
- self ._kqueue .control ([kev ], 0 , 0 )
519
+ self ._selector .control ([kev ], 0 , 0 )
568
520
except OSError :
569
521
# See comment above.
570
522
pass
@@ -575,7 +527,7 @@ def select(self, timeout=None):
575
527
max_ev = len (self ._fd_to_key )
576
528
ready = []
577
529
try :
578
- kev_list = self ._kqueue .control (None , max_ev , timeout )
530
+ kev_list = self ._selector .control (None , max_ev , timeout )
579
531
except InterruptedError :
580
532
return ready
581
533
for kev in kev_list :
@@ -593,7 +545,7 @@ def select(self, timeout=None):
593
545
return ready
594
546
595
547
def close (self ):
596
- self ._kqueue .close ()
548
+ self ._selector .close ()
597
549
super ().close ()
598
550
599
551
0 commit comments