annotate mercurial/thirdparty/selectors2.py @ 40955:f6187e60f792

help: present boolean arguments as "--[no-]foo" This should make it much more discoverable (we document it in `hg help flags`, but most users don't think to look there). Note that flags that default to None (and not False) will not get this new presentation. We can change the defaults to False later for flags where it makes sense (probably almost all boolean flags). Differential Revision: https://phab.mercurial-scm.org/D5432
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 14 Dec 2018 13:44:46 -0800
parents d1bda397df73
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
33502
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
1 """ Back-ported, durable, and portable selectors """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
2
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
3 # MIT License
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
4 #
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
5 # Copyright (c) 2017 Seth Michael Larson
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
6 #
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
8 # of this software and associated documentation files (the "Software"), to deal
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
9 # in the Software without restriction, including without limitation the rights
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
11 # copies of the Software, and to permit persons to whom the Software is
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
12 # furnished to do so, subject to the following conditions:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
13 #
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
14 # The above copyright notice and this permission notice shall be included in all
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
15 # copies or substantial portions of the Software.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
16 #
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
23 # SOFTWARE.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
24
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
25 from __future__ import absolute_import
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
26
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
27 import collections
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
28 import errno
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
29 import math
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
30 import select
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
31 import socket
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
32 import sys
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
33 import time
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
34
35245
414114a7c18f thirdparty: move selectors2 module to where it should be
Yuya Nishihara <yuya@tcha.org>
parents: 34639
diff changeset
35 from .. import pycompat
34639
a568a46751b6 selectors2: do not use platform.system()
Jun Wu <quark@fb.com>
parents: 33502
diff changeset
36
33502
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
37 namedtuple = collections.namedtuple
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
38 Mapping = collections.Mapping
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
39
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
40 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
41 monotonic = time.monotonic
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
42 except AttributeError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
43 monotonic = time.time
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
44
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
45 __author__ = 'Seth Michael Larson'
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
46 __email__ = 'sethmichaellarson@protonmail.com'
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
47 __version__ = '2.0.0'
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
48 __license__ = 'MIT'
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
49 __url__ = 'https://www.github.com/SethMichaelLarson/selectors2'
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
50
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
51 __all__ = ['EVENT_READ',
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
52 'EVENT_WRITE',
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
53 'SelectorKey',
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
54 'DefaultSelector',
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
55 'BaseSelector']
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
56
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
57 EVENT_READ = (1 << 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
58 EVENT_WRITE = (1 << 1)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
59 _DEFAULT_SELECTOR = None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
60 _SYSCALL_SENTINEL = object() # Sentinel in case a system call returns None.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
61 _ERROR_TYPES = (OSError, IOError, socket.error)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
62
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
63
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
64 SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
65
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
66
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
67 class _SelectorMapping(Mapping):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
68 """ Mapping of file objects to selector keys """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
69
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
70 def __init__(self, selector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
71 self._selector = selector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
72
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
73 def __len__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
74 return len(self._selector._fd_to_key)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
75
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
76 def __getitem__(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
77 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
78 fd = self._selector._fileobj_lookup(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
79 return self._selector._fd_to_key[fd]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
80 except KeyError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
81 raise KeyError("{0!r} is not registered.".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
82
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
83 def __iter__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
84 return iter(self._selector._fd_to_key)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
85
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
86
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
87 def _fileobj_to_fd(fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
88 """ Return a file descriptor from a file object. If
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
89 given an integer will simply return that integer back. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
90 if isinstance(fileobj, int):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
91 fd = fileobj
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
92 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
93 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
94 fd = int(fileobj.fileno())
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
95 except (AttributeError, TypeError, ValueError):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
96 raise ValueError("Invalid file object: {0!r}".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
97 if fd < 0:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
98 raise ValueError("Invalid file descriptor: {0}".format(fd))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
99 return fd
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
100
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
101
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
102 class BaseSelector(object):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
103 """ Abstract Selector class
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
104
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
105 A selector supports registering file objects to be monitored
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
106 for specific I/O events.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
107
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
108 A file object is a file descriptor or any object with a
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
109 `fileno()` method. An arbitrary object can be attached to the
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
110 file object which can be used for example to store context info,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
111 a callback, etc.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
112
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
113 A selector can use various implementations (select(), poll(), epoll(),
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
114 and kqueue()) depending on the platform. The 'DefaultSelector' class uses
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
115 the most efficient implementation for the current platform.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
116 """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
117 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
118 # Maps file descriptors to keys.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
119 self._fd_to_key = {}
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
120
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
121 # Read-only mapping returned by get_map()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
122 self._map = _SelectorMapping(self)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
123
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
124 def _fileobj_lookup(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
125 """ Return a file descriptor from a file object.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
126 This wraps _fileobj_to_fd() to do an exhaustive
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
127 search in case the object is invalid but we still
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
128 have it in our map. Used by unregister() so we can
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
129 unregister an object that was previously registered
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
130 even if it is closed. It is also used by _SelectorMapping
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
131 """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
132 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
133 return _fileobj_to_fd(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
134 except ValueError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
135
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
136 # Search through all our mapped keys.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
137 for key in self._fd_to_key.values():
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
138 if key.fileobj is fileobj:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
139 return key.fd
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
140
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
141 # Raise ValueError after all.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
142 raise
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
143
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
144 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
145 """ Register a file object for a set of events to monitor. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
146 if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
147 raise ValueError("Invalid events: {0!r}".format(events))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
148
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
149 key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
150
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
151 if key.fd in self._fd_to_key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
152 raise KeyError("{0!r} (FD {1}) is already registered"
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
153 .format(fileobj, key.fd))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
154
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
155 self._fd_to_key[key.fd] = key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
156 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
157
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
158 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
159 """ Unregister a file object from being monitored. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
160 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
161 key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
162 except KeyError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
163 raise KeyError("{0!r} is not registered".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
164
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
165 # Getting the fileno of a closed socket on Windows errors with EBADF.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
166 except socket.error as err:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
167 if err.errno != errno.EBADF:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
168 raise
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
169 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
170 for key in self._fd_to_key.values():
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
171 if key.fileobj is fileobj:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
172 self._fd_to_key.pop(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
173 break
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
174 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
175 raise KeyError("{0!r} is not registered".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
176 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
177
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
178 def modify(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
179 """ Change a registered file object monitored events and data. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
180 # NOTE: Some subclasses optimize this operation even further.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
181 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
182 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
183 except KeyError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
184 raise KeyError("{0!r} is not registered".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
185
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
186 if events != key.events:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
187 self.unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
188 key = self.register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
189
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
190 elif data != key.data:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
191 # Use a shortcut to update the data.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
192 key = key._replace(data=data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
193 self._fd_to_key[key.fd] = key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
194
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
195 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
196
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
197 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
198 """ Perform the actual selection until some monitored file objects
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
199 are ready or the timeout expires. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
200 raise NotImplementedError()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
201
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
202 def close(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
203 """ Close the selector. This must be called to ensure that all
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
204 underlying resources are freed. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
205 self._fd_to_key.clear()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
206 self._map = None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
207
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
208 def get_key(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
209 """ Return the key associated with a registered file object. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
210 mapping = self.get_map()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
211 if mapping is None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
212 raise RuntimeError("Selector is closed")
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
213 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
214 return mapping[fileobj]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
215 except KeyError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
216 raise KeyError("{0!r} is not registered".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
217
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
218 def get_map(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
219 """ Return a mapping of file objects to selector keys """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
220 return self._map
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
221
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
222 def _key_from_fd(self, fd):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
223 """ Return the key associated to a given file descriptor
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
224 Return None if it is not found. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
225 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
226 return self._fd_to_key[fd]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
227 except KeyError:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
228 return None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
229
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
230 def __enter__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
231 return self
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
232
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
233 def __exit__(self, *_):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
234 self.close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
235
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
236
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
237 # Almost all platforms have select.select()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
238 if hasattr(select, "select"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
239 class SelectSelector(BaseSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
240 """ Select-based selector. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
241 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
242 super(SelectSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
243 self._readers = set()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
244 self._writers = set()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
245
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
246 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
247 key = super(SelectSelector, self).register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
248 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
249 self._readers.add(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
250 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
251 self._writers.add(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
252 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
253
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
254 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
255 key = super(SelectSelector, self).unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
256 self._readers.discard(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
257 self._writers.discard(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
258 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
259
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
260 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
261 # Selecting on empty lists on Windows errors out.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
262 if not len(self._readers) and not len(self._writers):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
263 return []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
264
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
265 timeout = None if timeout is None else max(timeout, 0.0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
266 ready = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
267 r, w, _ = _syscall_wrapper(self._wrap_select, True, self._readers,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
268 self._writers, timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
269 r = set(r)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
270 w = set(w)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
271 for fd in r | w:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
272 events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
273 if fd in r:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
274 events |= EVENT_READ
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
275 if fd in w:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
276 events |= EVENT_WRITE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
277
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
278 key = self._key_from_fd(fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
279 if key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
280 ready.append((key, events & key.events))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
281 return ready
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
282
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
283 def _wrap_select(self, r, w, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
284 """ Wrapper for select.select because timeout is a positional arg """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
285 return select.select(r, w, [], timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
286
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
287 __all__.append('SelectSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
288
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
289 # Jython has a different implementation of .fileno() for socket objects.
34639
a568a46751b6 selectors2: do not use platform.system()
Jun Wu <quark@fb.com>
parents: 33502
diff changeset
290 if pycompat.isjython:
33502
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
291 class _JythonSelectorMapping(object):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
292 """ This is an implementation of _SelectorMapping that is built
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
293 for use specifically with Jython, which does not provide a hashable
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
294 value from socket.socket.fileno(). """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
295
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
296 def __init__(self, selector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
297 assert isinstance(selector, JythonSelectSelector)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
298 self._selector = selector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
299
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
300 def __len__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
301 return len(self._selector._sockets)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
302
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
303 def __getitem__(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
304 for sock, key in self._selector._sockets:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
305 if sock is fileobj:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
306 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
307 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
308 raise KeyError("{0!r} is not registered.".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
309
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
310 class JythonSelectSelector(SelectSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
311 """ This is an implementation of SelectSelector that is for Jython
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
312 which works around that Jython's socket.socket.fileno() does not
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
313 return an integer fd value. All SelectorKey.fd will be equal to -1
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
314 and should not be used. This instead uses object id to compare fileobj
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
315 and will only use select.select as it's the only selector that allows
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
316 directly passing in socket objects rather than registering fds.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
317 See: http://bugs.jython.org/issue1678
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
318 https://wiki.python.org/jython/NewSocketModule#socket.fileno.28.29_does_not_return_an_integer
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
319 """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
320
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
321 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
322 super(JythonSelectSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
323
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
324 self._sockets = [] # Uses a list of tuples instead of dictionary.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
325 self._map = _JythonSelectorMapping(self)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
326 self._readers = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
327 self._writers = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
328
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
329 # Jython has a select.cpython_compatible_select function in older versions.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
330 self._select_func = getattr(select, 'cpython_compatible_select', select.select)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
331
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
332 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
333 for sock, _ in self._sockets:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
334 if sock is fileobj:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
335 raise KeyError("{0!r} is already registered"
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
336 .format(fileobj, sock))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
337
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
338 key = SelectorKey(fileobj, -1, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
339 self._sockets.append((fileobj, key))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
340
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
341 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
342 self._readers.append(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
343 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
344 self._writers.append(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
345 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
346
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
347 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
348 for i, (sock, key) in enumerate(self._sockets):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
349 if sock is fileobj:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
350 break
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
351 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
352 raise KeyError("{0!r} is not registered.".format(fileobj))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
353
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
354 if key.events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
355 self._readers.remove(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
356 if key.events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
357 self._writers.remove(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
358
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
359 del self._sockets[i]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
360 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
361
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
362 def _wrap_select(self, r, w, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
363 """ Wrapper for select.select because timeout is a positional arg """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
364 return self._select_func(r, w, [], timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
365
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
366 __all__.append('JythonSelectSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
367 SelectSelector = JythonSelectSelector # Override so the wrong selector isn't used.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
368
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
369
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
370 if hasattr(select, "poll"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
371 class PollSelector(BaseSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
372 """ Poll-based selector """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
373 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
374 super(PollSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
375 self._poll = select.poll()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
376
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
377 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
378 key = super(PollSelector, self).register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
379 event_mask = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
380 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
381 event_mask |= select.POLLIN
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
382 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
383 event_mask |= select.POLLOUT
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
384 self._poll.register(key.fd, event_mask)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
385 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
386
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
387 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
388 key = super(PollSelector, self).unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
389 self._poll.unregister(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
390 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
391
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
392 def _wrap_poll(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
393 """ Wrapper function for select.poll.poll() so that
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
394 _syscall_wrapper can work with only seconds. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
395 if timeout is not None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
396 if timeout <= 0:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
397 timeout = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
398 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
399 # select.poll.poll() has a resolution of 1 millisecond,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
400 # round away from zero to wait *at least* timeout seconds.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
401 timeout = math.ceil(timeout * 1000)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
402
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
403 result = self._poll.poll(timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
404 return result
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
405
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
406 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
407 ready = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
408 fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
409 for fd, event_mask in fd_events:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
410 events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
411 if event_mask & ~select.POLLIN:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
412 events |= EVENT_WRITE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
413 if event_mask & ~select.POLLOUT:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
414 events |= EVENT_READ
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
415
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
416 key = self._key_from_fd(fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
417 if key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
418 ready.append((key, events & key.events))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
419
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
420 return ready
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
421
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
422 __all__.append('PollSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
423
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
424 if hasattr(select, "epoll"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
425 class EpollSelector(BaseSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
426 """ Epoll-based selector """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
427 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
428 super(EpollSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
429 self._epoll = select.epoll()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
430
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
431 def fileno(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
432 return self._epoll.fileno()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
433
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
434 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
435 key = super(EpollSelector, self).register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
436 events_mask = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
437 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
438 events_mask |= select.EPOLLIN
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
439 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
440 events_mask |= select.EPOLLOUT
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
441 _syscall_wrapper(self._epoll.register, False, key.fd, events_mask)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
442 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
443
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
444 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
445 key = super(EpollSelector, self).unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
446 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
447 _syscall_wrapper(self._epoll.unregister, False, key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
448 except _ERROR_TYPES:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
449 # This can occur when the fd was closed since registry.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
450 pass
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
451 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
452
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
453 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
454 if timeout is not None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
455 if timeout <= 0:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
456 timeout = 0.0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
457 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
458 # select.epoll.poll() has a resolution of 1 millisecond
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
459 # but luckily takes seconds so we don't need a wrapper
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
460 # like PollSelector. Just for better rounding.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
461 timeout = math.ceil(timeout * 1000) * 0.001
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
462 timeout = float(timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
463 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
464 timeout = -1.0 # epoll.poll() must have a float.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
465
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
466 # We always want at least 1 to ensure that select can be called
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
467 # with no file descriptors registered. Otherwise will fail.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
468 max_events = max(len(self._fd_to_key), 1)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
469
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
470 ready = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
471 fd_events = _syscall_wrapper(self._epoll.poll, True,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
472 timeout=timeout,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
473 maxevents=max_events)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
474 for fd, event_mask in fd_events:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
475 events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
476 if event_mask & ~select.EPOLLIN:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
477 events |= EVENT_WRITE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
478 if event_mask & ~select.EPOLLOUT:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
479 events |= EVENT_READ
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
480
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
481 key = self._key_from_fd(fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
482 if key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
483 ready.append((key, events & key.events))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
484 return ready
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
485
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
486 def close(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
487 self._epoll.close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
488 super(EpollSelector, self).close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
489
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
490 __all__.append('EpollSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
491
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
492
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
493 if hasattr(select, "devpoll"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
494 class DevpollSelector(BaseSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
495 """Solaris /dev/poll selector."""
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
496
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
497 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
498 super(DevpollSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
499 self._devpoll = select.devpoll()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
500
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
501 def fileno(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
502 return self._devpoll.fileno()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
503
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
504 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
505 key = super(DevpollSelector, self).register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
506 poll_events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
507 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
508 poll_events |= select.POLLIN
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
509 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
510 poll_events |= select.POLLOUT
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
511 self._devpoll.register(key.fd, poll_events)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
512 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
513
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
514 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
515 key = super(DevpollSelector, self).unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
516 self._devpoll.unregister(key.fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
517 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
518
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
519 def _wrap_poll(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
520 """ Wrapper function for select.poll.poll() so that
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
521 _syscall_wrapper can work with only seconds. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
522 if timeout is not None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
523 if timeout <= 0:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
524 timeout = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
525 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
526 # select.devpoll.poll() has a resolution of 1 millisecond,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
527 # round away from zero to wait *at least* timeout seconds.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
528 timeout = math.ceil(timeout * 1000)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
529
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
530 result = self._devpoll.poll(timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
531 return result
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
532
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
533 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
534 ready = []
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
535 fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
536 for fd, event_mask in fd_events:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
537 events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
538 if event_mask & ~select.POLLIN:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
539 events |= EVENT_WRITE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
540 if event_mask & ~select.POLLOUT:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
541 events |= EVENT_READ
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
542
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
543 key = self._key_from_fd(fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
544 if key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
545 ready.append((key, events & key.events))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
546
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
547 return ready
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
548
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
549 def close(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
550 self._devpoll.close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
551 super(DevpollSelector, self).close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
552
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
553 __all__.append('DevpollSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
554
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
555
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
556 if hasattr(select, "kqueue"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
557 class KqueueSelector(BaseSelector):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
558 """ Kqueue / Kevent-based selector """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
559 def __init__(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
560 super(KqueueSelector, self).__init__()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
561 self._kqueue = select.kqueue()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
562
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
563 def fileno(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
564 return self._kqueue.fileno()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
565
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
566 def register(self, fileobj, events, data=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
567 key = super(KqueueSelector, self).register(fileobj, events, data)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
568 if events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
569 kevent = select.kevent(key.fd,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
570 select.KQ_FILTER_READ,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
571 select.KQ_EV_ADD)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
572
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
573 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
574
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
575 if events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
576 kevent = select.kevent(key.fd,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
577 select.KQ_FILTER_WRITE,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
578 select.KQ_EV_ADD)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
579
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
580 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
581
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
582 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
583
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
584 def unregister(self, fileobj):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
585 key = super(KqueueSelector, self).unregister(fileobj)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
586 if key.events & EVENT_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
587 kevent = select.kevent(key.fd,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
588 select.KQ_FILTER_READ,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
589 select.KQ_EV_DELETE)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
590 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
591 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
592 except _ERROR_TYPES:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
593 pass
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
594 if key.events & EVENT_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
595 kevent = select.kevent(key.fd,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
596 select.KQ_FILTER_WRITE,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
597 select.KQ_EV_DELETE)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
598 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
599 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
600 except _ERROR_TYPES:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
601 pass
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
602
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
603 return key
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
604
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
605 def select(self, timeout=None):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
606 if timeout is not None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
607 timeout = max(timeout, 0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
608
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
609 max_events = len(self._fd_to_key) * 2
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
610 ready_fds = {}
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
611
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
612 kevent_list = _syscall_wrapper(self._kqueue.control, True,
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
613 None, max_events, timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
614
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
615 for kevent in kevent_list:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
616 fd = kevent.ident
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
617 event_mask = kevent.filter
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
618 events = 0
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
619 if event_mask == select.KQ_FILTER_READ:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
620 events |= EVENT_READ
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
621 if event_mask == select.KQ_FILTER_WRITE:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
622 events |= EVENT_WRITE
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
623
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
624 key = self._key_from_fd(fd)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
625 if key:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
626 if key.fd not in ready_fds:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
627 ready_fds[key.fd] = (key, events & key.events)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
628 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
629 old_events = ready_fds[key.fd][1]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
630 ready_fds[key.fd] = (key, (events | old_events) & key.events)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
631
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
632 return list(ready_fds.values())
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
633
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
634 def close(self):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
635 self._kqueue.close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
636 super(KqueueSelector, self).close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
637
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
638 __all__.append('KqueueSelector')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
639
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
640
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
641 def _can_allocate(struct):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
642 """ Checks that select structs can be allocated by the underlying
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
643 operating system, not just advertised by the select module. We don't
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
644 check select() because we'll be hopeful that most platforms that
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
645 don't have it available will not advertise it. (ie: GAE) """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
646 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
647 # select.poll() objects won't fail until used.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
648 if struct == 'poll':
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
649 p = select.poll()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
650 p.poll(0)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
651
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
652 # All others will fail on allocation.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
653 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
654 getattr(select, struct)().close()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
655 return True
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
656 except (OSError, AttributeError):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
657 return False
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
658
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
659
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
660 # Python 3.5 uses a more direct route to wrap system calls to increase speed.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
661 if sys.version_info >= (3, 5):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
662 def _syscall_wrapper(func, _, *args, **kwargs):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
663 """ This is the short-circuit version of the below logic
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
664 because in Python 3.5+ all selectors restart system calls. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
665 return func(*args, **kwargs)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
666 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
667 def _syscall_wrapper(func, recalc_timeout, *args, **kwargs):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
668 """ Wrapper function for syscalls that could fail due to EINTR.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
669 All functions should be retried if there is time left in the timeout
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
670 in accordance with PEP 475. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
671 timeout = kwargs.get("timeout", None)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
672 if timeout is None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
673 expires = None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
674 recalc_timeout = False
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
675 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
676 timeout = float(timeout)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
677 if timeout < 0.0: # Timeout less than 0 treated as no timeout.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
678 expires = None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
679 else:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
680 expires = monotonic() + timeout
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
681
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
682 args = list(args)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
683 if recalc_timeout and "timeout" not in kwargs:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
684 raise ValueError(
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
685 "Timeout must be in args or kwargs to be recalculated")
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
686
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
687 result = _SYSCALL_SENTINEL
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
688 while result is _SYSCALL_SENTINEL:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
689 try:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
690 result = func(*args, **kwargs)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
691 # OSError is thrown by select.select
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
692 # IOError is thrown by select.epoll.poll
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
693 # select.error is thrown by select.poll.poll
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
694 # Aren't we thankful for Python 3.x rework for exceptions?
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
695 except (OSError, IOError, select.error) as e:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
696 # select.error wasn't a subclass of OSError in the past.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
697 errcode = None
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
698 if hasattr(e, "errno"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
699 errcode = e.errno
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
700 elif hasattr(e, "args"):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
701 errcode = e.args[0]
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
702
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
703 # Also test for the Windows equivalent of EINTR.
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
704 is_interrupt = (errcode == errno.EINTR or (hasattr(errno, "WSAEINTR") and
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
705 errcode == errno.WSAEINTR))
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
706
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
707 if is_interrupt:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
708 if expires is not None:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
709 current_time = monotonic()
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
710 if current_time > expires:
40787
d1bda397df73 selectors2: backport minimal fix of timeout handling from 2.0.1
Yuya Nishihara <yuya@tcha.org>
parents: 35245
diff changeset
711 raise OSError(errno.ETIMEDOUT, 'Connection timed out')
33502
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
712 if recalc_timeout:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
713 if "timeout" in kwargs:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
714 kwargs["timeout"] = expires - current_time
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
715 continue
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
716 raise
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
717 return result
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
718
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
719
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
720 # Choose the best implementation, roughly:
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
721 # kqueue == devpoll == epoll > poll > select
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
722 # select() also can't accept a FD > FD_SETSIZE (usually around 1024)
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
723 def DefaultSelector():
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
724 """ This function serves as a first call for DefaultSelector to
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
725 detect if the select module is being monkey-patched incorrectly
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
726 by eventlet, greenlet, and preserve proper behavior. """
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
727 global _DEFAULT_SELECTOR
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
728 if _DEFAULT_SELECTOR is None:
34639
a568a46751b6 selectors2: do not use platform.system()
Jun Wu <quark@fb.com>
parents: 33502
diff changeset
729 if pycompat.isjython:
33502
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
730 _DEFAULT_SELECTOR = JythonSelectSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
731 elif _can_allocate('kqueue'):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
732 _DEFAULT_SELECTOR = KqueueSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
733 elif _can_allocate('devpoll'):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
734 _DEFAULT_SELECTOR = DevpollSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
735 elif _can_allocate('epoll'):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
736 _DEFAULT_SELECTOR = EpollSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
737 elif _can_allocate('poll'):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
738 _DEFAULT_SELECTOR = PollSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
739 elif hasattr(select, 'select'):
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
740 _DEFAULT_SELECTOR = SelectSelector
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
741 else: # Platform-specific: AppEngine
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
742 raise RuntimeError('Platform does not have a selector.')
5d0c0c8d2929 selector2: vendor selector2 library
Jun Wu <quark@fb.com>
parents:
diff changeset
743 return _DEFAULT_SELECTOR()