-
-
Notifications
You must be signed in to change notification settings - Fork 31k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-30014: make poll-like selector's modify() method faster #1030
Changes from all commits
11f5491
43d5df1
614ef4a
0a4720c
00654cd
951e5f7
e153f84
d9a21b9
70fae77
964f175
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,7 +252,6 @@ def unregister(self, fileobj): | |
return key | ||
|
||
def modify(self, fileobj, events, data=None): | ||
# TODO: Subclasses can probably optimize this even further. | ||
try: | ||
key = self._fd_to_key[self._fileobj_lookup(fileobj)] | ||
except KeyError: | ||
|
@@ -342,6 +341,8 @@ def select(self, timeout=None): | |
class _PollLikeSelector(_BaseSelectorImpl): | ||
"""Base class shared between poll, epoll and devpoll selectors.""" | ||
_selector_cls = None | ||
_EVENT_READ = None | ||
_EVENT_WRITE = None | ||
|
||
def __init__(self): | ||
super().__init__() | ||
|
@@ -371,6 +372,33 @@ def unregister(self, fileobj): | |
pass | ||
return key | ||
|
||
def modify(self, fileobj, events, data=None): | ||
try: | ||
key = self._fd_to_key[self._fileobj_lookup(fileobj)] | ||
except KeyError: | ||
raise KeyError(f"{fileobj!r} is not registered") from None | ||
|
||
changed = False | ||
if events != key.events: | ||
selector_events = 0 | ||
if events & EVENT_READ: | ||
selector_events |= self._EVENT_READ | ||
if events & EVENT_WRITE: | ||
selector_events |= self._EVENT_WRITE | ||
try: | ||
self._selector.modify(key.fd, selector_events) | ||
except Exception: | ||
super().unregister(fileobj) | ||
raise | ||
changed = True | ||
if data != key.data: | ||
changed = True | ||
|
||
if changed: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How common is the case of unchanged There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how common it is but
|
||
key = key._replace(events=events, data=data) | ||
self._fd_to_key[key.fd] = key | ||
return key | ||
|
||
def select(self, timeout=None): | ||
# This is shared between poll() and epoll(). | ||
# epoll() has a different signature and handling of timeout parameter. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it isn't time to switch this (and other except clauses in this module) to BaseException. Otherwise a KeyboardInterrupt (in particular) could leave us in a bad state. This has been a recurring problem in asyncio; we eventually are planning to address it in asyncio, and then having it not be a problem here would be a requirement. (Though I'd be okay with filing a separate issue for this instead of folding it into this PR.)