blob: a9a0801ef0713bc92eea7d165e87c5595caf9696 [file] [log] [blame]
Charles-François Natali243d8d82013-09-04 19:02:49 +02001"""Selectors module.
2
3This module allows high-level and efficient I/O multiplexing, built upon the
4`select` module primitives.
5"""
6
7
Victor Stinnerda492a82014-02-20 10:37:27 +01008from abc import ABCMeta, abstractmethod
Serhiy Storchaka2e576f52017-04-24 09:05:00 +03009from collections import namedtuple
10from collections.abc import Mapping
Victor Stinnerdcd97402014-01-31 12:12:53 +010011import math
Charles-François Natali243d8d82013-09-04 19:02:49 +020012import select
13import sys
14
15
16# generic events, that must be mapped to implementation-specific ones
17EVENT_READ = (1 << 0)
18EVENT_WRITE = (1 << 1)
19
20
21def _fileobj_to_fd(fileobj):
22 """Return a file descriptor from a file object.
23
24 Parameters:
25 fileobj -- file object or file descriptor
26
27 Returns:
28 corresponding file descriptor
Guido van Rossum9710ff02013-12-07 15:57:01 -080029
30 Raises:
31 ValueError if the object is invalid
Charles-François Natali243d8d82013-09-04 19:02:49 +020032 """
33 if isinstance(fileobj, int):
34 fd = fileobj
35 else:
36 try:
37 fd = int(fileobj.fileno())
38 except (AttributeError, TypeError, ValueError):
39 raise ValueError("Invalid file object: "
40 "{!r}".format(fileobj)) from None
41 if fd < 0:
42 raise ValueError("Invalid file descriptor: {}".format(fd))
43 return fd
44
45
46SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
Charles-François Natali243d8d82013-09-04 19:02:49 +020047
Yury Selivanov0c6a3442016-03-02 10:37:59 -050048SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
49
50 Object used to associate a file object to its backing
51 file descriptor, selected event mask, and attached data.
52"""
53if sys.version_info >= (3, 5):
54 SelectorKey.fileobj.__doc__ = 'File object registered.'
55 SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
56 SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
57 SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
58 For example, this could be used to store a per-client session ID.''')
Charles-François Natali243d8d82013-09-04 19:02:49 +020059
Charles-François Natali4574b492013-10-30 20:31:04 +010060class _SelectorMapping(Mapping):
61 """Mapping of file objects to selector keys."""
62
63 def __init__(self, selector):
64 self._selector = selector
65
66 def __len__(self):
67 return len(self._selector._fd_to_key)
68
69 def __getitem__(self, fileobj):
70 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -080071 fd = self._selector._fileobj_lookup(fileobj)
72 return self._selector._fd_to_key[fd]
Charles-François Natali4574b492013-10-30 20:31:04 +010073 except KeyError:
74 raise KeyError("{!r} is not registered".format(fileobj)) from None
75
76 def __iter__(self):
77 return iter(self._selector._fd_to_key)
78
79
Charles-François Natali243d8d82013-09-04 19:02:49 +020080class BaseSelector(metaclass=ABCMeta):
Charles-François Natalib3330a0a2013-12-01 11:04:17 +010081 """Selector abstract base class.
Charles-François Natali243d8d82013-09-04 19:02:49 +020082
83 A selector supports registering file objects to be monitored for specific
84 I/O events.
85
86 A file object is a file descriptor or any object with a `fileno()` method.
87 An arbitrary object can be attached to the file object, which can be used
88 for example to store context information, a callback, etc.
89
90 A selector can use various implementations (select(), poll(), epoll()...)
91 depending on the platform. The default `Selector` class uses the most
Yury Selivanovb0b0e622014-02-18 22:27:48 -050092 efficient implementation on the current platform.
Charles-François Natali243d8d82013-09-04 19:02:49 +020093 """
94
Charles-François Natalib3330a0a2013-12-01 11:04:17 +010095 @abstractmethod
Charles-François Natali243d8d82013-09-04 19:02:49 +020096 def register(self, fileobj, events, data=None):
97 """Register a file object.
98
99 Parameters:
100 fileobj -- file object or file descriptor
101 events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
102 data -- attached data
103
104 Returns:
105 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800106
107 Raises:
108 ValueError if events is invalid
109 KeyError if fileobj is already registered
110 OSError if fileobj is closed or otherwise is unacceptable to
111 the underlying system call (if a system call is made)
112
113 Note:
114 OSError may or may not be raised
Charles-François Natali243d8d82013-09-04 19:02:49 +0200115 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100116 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200117
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100118 @abstractmethod
Charles-François Natali243d8d82013-09-04 19:02:49 +0200119 def unregister(self, fileobj):
120 """Unregister a file object.
121
122 Parameters:
123 fileobj -- file object or file descriptor
124
125 Returns:
126 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800127
128 Raises:
129 KeyError if fileobj is not registered
130
131 Note:
132 If fileobj is registered but has since been closed this does
133 *not* raise OSError (even if the wrapped syscall does)
Charles-François Natali243d8d82013-09-04 19:02:49 +0200134 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100135 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200136
137 def modify(self, fileobj, events, data=None):
138 """Change a registered file object monitored events or attached data.
139
140 Parameters:
141 fileobj -- file object or file descriptor
142 events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
143 data -- attached data
144
145 Returns:
146 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800147
148 Raises:
149 Anything that unregister() or register() raises
Charles-François Natali243d8d82013-09-04 19:02:49 +0200150 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100151 self.unregister(fileobj)
152 return self.register(fileobj, events, data)
Charles-François Natali243d8d82013-09-04 19:02:49 +0200153
154 @abstractmethod
155 def select(self, timeout=None):
156 """Perform the actual selection, until some monitored file objects are
157 ready or a timeout expires.
158
159 Parameters:
160 timeout -- if timeout > 0, this specifies the maximum wait time, in
161 seconds
162 if timeout <= 0, the select() call won't block, and will
163 report the currently ready file objects
164 if timeout is None, select() will block until a monitored
165 file object becomes ready
166
167 Returns:
168 list of (key, events) for ready file objects
169 `events` is a bitwise mask of EVENT_READ|EVENT_WRITE
170 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100171 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200172
173 def close(self):
174 """Close the selector.
175
176 This must be called to make sure that any underlying resource is freed.
177 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100178 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200179
180 def get_key(self, fileobj):
181 """Return the key associated to a registered file object.
182
183 Returns:
184 SelectorKey for this file object
185 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100186 mapping = self.get_map()
Victor Stinner458fc6f2015-01-13 10:00:55 +0100187 if mapping is None:
188 raise RuntimeError('Selector is closed')
Charles-François Natali243d8d82013-09-04 19:02:49 +0200189 try:
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100190 return mapping[fileobj]
Charles-François Natali243d8d82013-09-04 19:02:49 +0200191 except KeyError:
192 raise KeyError("{!r} is not registered".format(fileobj)) from None
193
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100194 @abstractmethod
Charles-François Natali4574b492013-10-30 20:31:04 +0100195 def get_map(self):
196 """Return a mapping of file objects to selector keys."""
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100197 raise NotImplementedError
Charles-François Natali4574b492013-10-30 20:31:04 +0100198
Charles-François Natali243d8d82013-09-04 19:02:49 +0200199 def __enter__(self):
200 return self
201
202 def __exit__(self, *args):
203 self.close()
204
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100205
206class _BaseSelectorImpl(BaseSelector):
207 """Base selector implementation."""
208
209 def __init__(self):
210 # this maps file descriptors to keys
211 self._fd_to_key = {}
212 # read-only mapping returned by get_map()
213 self._map = _SelectorMapping(self)
214
Guido van Rossum9710ff02013-12-07 15:57:01 -0800215 def _fileobj_lookup(self, fileobj):
216 """Return a file descriptor from a file object.
217
218 This wraps _fileobj_to_fd() to do an exhaustive search in case
219 the object is invalid but we still have it in our map. This
220 is used by unregister() so we can unregister an object that
221 was previously registered even if it is closed. It is also
222 used by _SelectorMapping.
223 """
224 try:
225 return _fileobj_to_fd(fileobj)
226 except ValueError:
227 # Do an exhaustive search.
228 for key in self._fd_to_key.values():
229 if key.fileobj is fileobj:
230 return key.fd
231 # Raise ValueError after all.
232 raise
233
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100234 def register(self, fileobj, events, data=None):
235 if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
236 raise ValueError("Invalid events: {!r}".format(events))
237
Guido van Rossum9710ff02013-12-07 15:57:01 -0800238 key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100239
240 if key.fd in self._fd_to_key:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800241 raise KeyError("{!r} (FD {}) is already registered"
242 .format(fileobj, key.fd))
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100243
244 self._fd_to_key[key.fd] = key
245 return key
246
247 def unregister(self, fileobj):
248 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800249 key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100250 except KeyError:
251 raise KeyError("{!r} is not registered".format(fileobj)) from None
252 return key
253
254 def modify(self, fileobj, events, data=None):
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100255 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800256 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100257 except KeyError:
258 raise KeyError("{!r} is not registered".format(fileobj)) from None
259 if events != key.events:
260 self.unregister(fileobj)
261 key = self.register(fileobj, events, data)
262 elif data != key.data:
263 # Use a shortcut to update the data.
264 key = key._replace(data=data)
265 self._fd_to_key[key.fd] = key
266 return key
267
268 def close(self):
269 self._fd_to_key.clear()
Victor Stinner38dc2502015-01-13 09:58:33 +0100270 self._map = None
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100271
272 def get_map(self):
273 return self._map
274
Charles-François Natali243d8d82013-09-04 19:02:49 +0200275 def _key_from_fd(self, fd):
276 """Return the key associated to a given file descriptor.
277
278 Parameters:
279 fd -- file descriptor
280
281 Returns:
282 corresponding key, or None if not found
283 """
284 try:
285 return self._fd_to_key[fd]
286 except KeyError:
287 return None
288
289
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100290class SelectSelector(_BaseSelectorImpl):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200291 """Select-based selector."""
292
293 def __init__(self):
294 super().__init__()
295 self._readers = set()
296 self._writers = set()
297
298 def register(self, fileobj, events, data=None):
299 key = super().register(fileobj, events, data)
300 if events & EVENT_READ:
301 self._readers.add(key.fd)
302 if events & EVENT_WRITE:
303 self._writers.add(key.fd)
304 return key
305
306 def unregister(self, fileobj):
307 key = super().unregister(fileobj)
308 self._readers.discard(key.fd)
309 self._writers.discard(key.fd)
310 return key
311
312 if sys.platform == 'win32':
313 def _select(self, r, w, _, timeout=None):
314 r, w, x = select.select(r, w, w, timeout)
315 return r, w + x, []
316 else:
317 _select = select.select
318
319 def select(self, timeout=None):
320 timeout = None if timeout is None else max(timeout, 0)
321 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400322 try:
323 r, w, _ = self._select(self._readers, self._writers, [], timeout)
324 except InterruptedError:
325 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200326 r = set(r)
327 w = set(w)
328 for fd in r | w:
329 events = 0
330 if fd in r:
331 events |= EVENT_READ
332 if fd in w:
333 events |= EVENT_WRITE
334
335 key = self._key_from_fd(fd)
336 if key:
337 ready.append((key, events & key.events))
338 return ready
339
340
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200341class _PollLikeSelector(_BaseSelectorImpl):
342 """Base class shared between poll, epoll and devpoll selectors."""
343 _selector_cls = None
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200344 _EVENT_READ = None
345 _EVENT_WRITE = None
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200346
347 def __init__(self):
348 super().__init__()
349 self._selector = self._selector_cls()
350
351 def register(self, fileobj, events, data=None):
352 key = super().register(fileobj, events, data)
353 poller_events = 0
354 if events & EVENT_READ:
355 poller_events |= self._EVENT_READ
356 if events & EVENT_WRITE:
357 poller_events |= self._EVENT_WRITE
358 try:
359 self._selector.register(key.fd, poller_events)
Giampaolo Rodolaced36a92017-06-12 14:43:40 +0200360 except:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200361 super().unregister(fileobj)
362 raise
363 return key
364
365 def unregister(self, fileobj):
366 key = super().unregister(fileobj)
367 try:
368 self._selector.unregister(key.fd)
369 except OSError:
370 # This can happen if the FD was closed since it
371 # was registered.
372 pass
373 return key
374
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200375 def modify(self, fileobj, events, data=None):
376 try:
377 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
378 except KeyError:
379 raise KeyError(f"{fileobj!r} is not registered") from None
380
381 changed = False
382 if events != key.events:
383 selector_events = 0
384 if events & EVENT_READ:
385 selector_events |= self._EVENT_READ
386 if events & EVENT_WRITE:
387 selector_events |= self._EVENT_WRITE
388 try:
389 self._selector.modify(key.fd, selector_events)
Giampaolo Rodola05dc20f2017-06-11 01:51:52 +0200390 except:
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200391 super().unregister(fileobj)
392 raise
393 changed = True
394 if data != key.data:
395 changed = True
396
397 if changed:
398 key = key._replace(events=events, data=data)
399 self._fd_to_key[key.fd] = key
400 return key
401
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200402 def select(self, timeout=None):
403 # This is shared between poll() and epoll().
404 # epoll() has a different signature and handling of timeout parameter.
405 if timeout is None:
406 timeout = None
407 elif timeout <= 0:
408 timeout = 0
409 else:
410 # poll() has a resolution of 1 millisecond, round away from
411 # zero to wait *at least* timeout seconds.
412 timeout = math.ceil(timeout * 1e3)
413 ready = []
414 try:
415 fd_event_list = self._selector.poll(timeout)
416 except InterruptedError:
417 return ready
418 for fd, event in fd_event_list:
419 events = 0
420 if event & ~self._EVENT_READ:
421 events |= EVENT_WRITE
422 if event & ~self._EVENT_WRITE:
423 events |= EVENT_READ
424
425 key = self._key_from_fd(fd)
426 if key:
427 ready.append((key, events & key.events))
428 return ready
429
430
Charles-François Natali243d8d82013-09-04 19:02:49 +0200431if hasattr(select, 'poll'):
432
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200433 class PollSelector(_PollLikeSelector):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200434 """Poll-based selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200435 _selector_cls = select.poll
436 _EVENT_READ = select.POLLIN
437 _EVENT_WRITE = select.POLLOUT
Charles-François Natali243d8d82013-09-04 19:02:49 +0200438
439
440if hasattr(select, 'epoll'):
441
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200442 class EpollSelector(_PollLikeSelector):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200443 """Epoll-based selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200444 _selector_cls = select.epoll
445 _EVENT_READ = select.EPOLLIN
446 _EVENT_WRITE = select.EPOLLOUT
Charles-François Natali243d8d82013-09-04 19:02:49 +0200447
448 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200449 return self._selector.fileno()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200450
451 def select(self, timeout=None):
Victor Stinner567b26e2014-01-21 21:00:47 +0100452 if timeout is None:
453 timeout = -1
454 elif timeout <= 0:
455 timeout = 0
Victor Stinnerdcd97402014-01-31 12:12:53 +0100456 else:
457 # epoll_wait() has a resolution of 1 millisecond, round away
458 # from zero to wait *at least* timeout seconds.
459 timeout = math.ceil(timeout * 1e3) * 1e-3
Yury Selivanovd60ef4a2014-12-08 12:21:58 -0500460
Yury Selivanovdfc44e02014-12-08 12:30:10 -0500461 # epoll_wait() expects `maxevents` to be greater than zero;
Yury Selivanovd60ef4a2014-12-08 12:21:58 -0500462 # we want to make sure that `select()` can be called when no
463 # FD is registered.
464 max_ev = max(len(self._fd_to_key), 1)
465
Charles-François Natali243d8d82013-09-04 19:02:49 +0200466 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400467 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200468 fd_event_list = self._selector.poll(timeout, max_ev)
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400469 except InterruptedError:
470 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200471 for fd, event in fd_event_list:
472 events = 0
473 if event & ~select.EPOLLIN:
474 events |= EVENT_WRITE
475 if event & ~select.EPOLLOUT:
476 events |= EVENT_READ
477
478 key = self._key_from_fd(fd)
479 if key:
480 ready.append((key, events & key.events))
481 return ready
482
483 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200484 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400485 super().close()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200486
487
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100488if hasattr(select, 'devpoll'):
489
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200490 class DevpollSelector(_PollLikeSelector):
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100491 """Solaris /dev/poll selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200492 _selector_cls = select.devpoll
493 _EVENT_READ = select.POLLIN
494 _EVENT_WRITE = select.POLLOUT
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100495
496 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200497 return self._selector.fileno()
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100498
499 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200500 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400501 super().close()
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100502
503
Charles-François Natali243d8d82013-09-04 19:02:49 +0200504if hasattr(select, 'kqueue'):
505
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100506 class KqueueSelector(_BaseSelectorImpl):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200507 """Kqueue-based selector."""
508
509 def __init__(self):
510 super().__init__()
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200511 self._selector = select.kqueue()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200512
513 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200514 return self._selector.fileno()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200515
516 def register(self, fileobj, events, data=None):
517 key = super().register(fileobj, events, data)
Yury Selivanov525aedc2016-09-15 19:30:42 -0400518 try:
519 if events & EVENT_READ:
520 kev = select.kevent(key.fd, select.KQ_FILTER_READ,
521 select.KQ_EV_ADD)
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200522 self._selector.control([kev], 0, 0)
Yury Selivanov525aedc2016-09-15 19:30:42 -0400523 if events & EVENT_WRITE:
524 kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
525 select.KQ_EV_ADD)
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200526 self._selector.control([kev], 0, 0)
Giampaolo Rodola05dc20f2017-06-11 01:51:52 +0200527 except:
Yury Selivanov525aedc2016-09-15 19:30:42 -0400528 super().unregister(fileobj)
529 raise
Charles-François Natali243d8d82013-09-04 19:02:49 +0200530 return key
531
532 def unregister(self, fileobj):
533 key = super().unregister(fileobj)
534 if key.events & EVENT_READ:
535 kev = select.kevent(key.fd, select.KQ_FILTER_READ,
536 select.KQ_EV_DELETE)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800537 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200538 self._selector.control([kev], 0, 0)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800539 except OSError:
540 # This can happen if the FD was closed since it
541 # was registered.
542 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200543 if key.events & EVENT_WRITE:
544 kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
545 select.KQ_EV_DELETE)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800546 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200547 self._selector.control([kev], 0, 0)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800548 except OSError:
549 # See comment above.
550 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200551 return key
552
553 def select(self, timeout=None):
554 timeout = None if timeout is None else max(timeout, 0)
555 max_ev = len(self._fd_to_key)
556 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400557 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200558 kev_list = self._selector.control(None, max_ev, timeout)
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400559 except InterruptedError:
560 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200561 for kev in kev_list:
562 fd = kev.ident
563 flag = kev.filter
564 events = 0
565 if flag == select.KQ_FILTER_READ:
566 events |= EVENT_READ
567 if flag == select.KQ_FILTER_WRITE:
568 events |= EVENT_WRITE
569
570 key = self._key_from_fd(fd)
571 if key:
572 ready.append((key, events & key.events))
573 return ready
574
575 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200576 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400577 super().close()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200578
579
Victor Stinner53a6d742015-01-09 00:13:39 +0100580# Choose the best implementation, roughly:
581# epoll|kqueue|devpoll > poll > select.
Charles-François Natali243d8d82013-09-04 19:02:49 +0200582# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
583if 'KqueueSelector' in globals():
584 DefaultSelector = KqueueSelector
585elif 'EpollSelector' in globals():
586 DefaultSelector = EpollSelector
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100587elif 'DevpollSelector' in globals():
588 DefaultSelector = DevpollSelector
Charles-François Natali243d8d82013-09-04 19:02:49 +0200589elif 'PollSelector' in globals():
590 DefaultSelector = PollSelector
591else:
592 DefaultSelector = SelectSelector