#30014: refactor poll-related classes#1035
Conversation
…poll() share the same methods for register(), unregister(), close() and select()
| """Poll-based selector.""" | ||
| def __init__(self): | ||
| super().__init__() | ||
| self._poller = self._poller() |
There was a problem hiding this comment.
This looks strange: I assume that self._poller is the poller class (e.g. select, poll, etc).
It's used here but not defined in this base class: maybe make it an abstract property to force its definition?
Also, assigning
self._poller = self._poller() is very confusing: you're reusing the same member for the instance and the class.
Maybe use poller_cls, or poller_type for the type of the poller, to avoid confusion with the instance?
There was a problem hiding this comment.
Yes, the idea is to have a _poller attribute which can be referenced by all 3 classes. Actually I think it'd be cool to do the same also for select and kqueue.
And yes, it's probably better to also have _poller_cls.
I don't have a strong opinion about abstract properties but it's up to you.
There was a problem hiding this comment.
How would you feel about having a _selector attribute for all classes (also kqueue and select)?
| poller_events |= self._EVENT_WRITE | ||
| try: | ||
| self._poller.register(key.fd, poller_events) | ||
| except BaseException: |
There was a problem hiding this comment.
I think catching BaseException is discouraged, shouldn't it be Exception?
There was a problem hiding this comment.
yes, I think it should; I think I copied it from the previous code
| key = super().unregister(fileobj) | ||
| try: | ||
| self._poller.unregister(key.fd) | ||
| except OSError: |
There was a problem hiding this comment.
Why catch OSError here and BaseException in register()?
There was a problem hiding this comment.
I copied it from the previous code:
Line 423 in 2e576f5
...although the original code did that for epoll only wheres with this it's applied to all 3 selectors. Not sure if it matters. Probably not.
In general I think it would make sense to always catch OSError (also in kqueue).
There was a problem hiding this comment.
Agreed, let's catch OSError everywhere.
| _EVENT_WRITE = select.POLLOUT | ||
|
|
||
| def fileno(self): | ||
| return self._devpoll.fileno() |
There was a problem hiding this comment.
This can't work, self._devpoll has been replaced by self._poller.
There was a problem hiding this comment.
Good catch. Fixed.
| ready.append((key, events & key.events)) | ||
| return ready | ||
| def close(self): | ||
| if hasattr(self._poller, "close"): |
There was a problem hiding this comment.
Doing such a hasattr() is a bit naughty: why not instead override close() in EpollSelector and DevPollSelector to close the underlying FD?
If you want to maximize code reuse, maybe we could add a _FDBasedSelector - common to al implementations using a file descriptor - in which you could define close() and fileno()?
There was a problem hiding this comment.
I overrode close() in EpollSelector and DevPollSelector to close the underlying FD as per your suggestion.
cf-natali
left a comment
There was a problem hiding this comment.
Sorry for the delay, didn't see this message.
With the proposed changes, sounds great!
giampaolo
left a comment
There was a problem hiding this comment.
Sorry for the delay, didn't see this message.
No problem. ;-)
OK, I think it's ready.
| """Poll-based selector.""" | ||
| def __init__(self): | ||
| super().__init__() | ||
| self._poller = self._poller() |
| poller_events |= self._EVENT_WRITE | ||
| try: | ||
| self._poller.register(key.fd, poller_events) | ||
| except BaseException: |
| ready.append((key, events & key.events)) | ||
| return ready | ||
| def close(self): | ||
| if hasattr(self._poller, "close"): |
There was a problem hiding this comment.
I overrode close() in EpollSelector and DevPollSelector to close the underlying FD as per your suggestion.
| _EVENT_WRITE = select.POLLOUT | ||
|
|
||
| def fileno(self): | ||
| return self._devpoll.fileno() |
There was a problem hiding this comment.
Good catch. Fixed.
|
Cool. Merged. I'll submit a PR for a faster |
|
Congrats giampaolo for fixing that old issue :-) I hope that it will make
further selectors enhancements simpler.
|
|
Thanks Victor. ;) |
Refactor poll-related classes so that poll(), epoll() and devpoll() share the same methods for register(), unregister(), close() and select().
This was inspired by http://bugs.python.org/issue30014 and serves as a strategy to avoid duplicating the implementation of modify() method.
UPDATE 2017-05-20: also use a single
self._pollerattribute for all classes instead of havingself._poll,self._kqueueetc..@Haypo