xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/selectors.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Selectors module.
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerThis module allows high-level and efficient I/O multiplexing, built upon the
4*cda5da8dSAndroid Build Coastguard Worker`select` module primitives.
5*cda5da8dSAndroid Build Coastguard Worker"""
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Workerfrom abc import ABCMeta, abstractmethod
9*cda5da8dSAndroid Build Coastguard Workerfrom collections import namedtuple
10*cda5da8dSAndroid Build Coastguard Workerfrom collections.abc import Mapping
11*cda5da8dSAndroid Build Coastguard Workerimport math
12*cda5da8dSAndroid Build Coastguard Workerimport select
13*cda5da8dSAndroid Build Coastguard Workerimport sys
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard Worker
16*cda5da8dSAndroid Build Coastguard Worker# generic events, that must be mapped to implementation-specific ones
17*cda5da8dSAndroid Build Coastguard WorkerEVENT_READ = (1 << 0)
18*cda5da8dSAndroid Build Coastguard WorkerEVENT_WRITE = (1 << 1)
19*cda5da8dSAndroid Build Coastguard Worker
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Workerdef _fileobj_to_fd(fileobj):
22*cda5da8dSAndroid Build Coastguard Worker    """Return a file descriptor from a file object.
23*cda5da8dSAndroid Build Coastguard Worker
24*cda5da8dSAndroid Build Coastguard Worker    Parameters:
25*cda5da8dSAndroid Build Coastguard Worker    fileobj -- file object or file descriptor
26*cda5da8dSAndroid Build Coastguard Worker
27*cda5da8dSAndroid Build Coastguard Worker    Returns:
28*cda5da8dSAndroid Build Coastguard Worker    corresponding file descriptor
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Worker    Raises:
31*cda5da8dSAndroid Build Coastguard Worker    ValueError if the object is invalid
32*cda5da8dSAndroid Build Coastguard Worker    """
33*cda5da8dSAndroid Build Coastguard Worker    if isinstance(fileobj, int):
34*cda5da8dSAndroid Build Coastguard Worker        fd = fileobj
35*cda5da8dSAndroid Build Coastguard Worker    else:
36*cda5da8dSAndroid Build Coastguard Worker        try:
37*cda5da8dSAndroid Build Coastguard Worker            fd = int(fileobj.fileno())
38*cda5da8dSAndroid Build Coastguard Worker        except (AttributeError, TypeError, ValueError):
39*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("Invalid file object: "
40*cda5da8dSAndroid Build Coastguard Worker                             "{!r}".format(fileobj)) from None
41*cda5da8dSAndroid Build Coastguard Worker    if fd < 0:
42*cda5da8dSAndroid Build Coastguard Worker        raise ValueError("Invalid file descriptor: {}".format(fd))
43*cda5da8dSAndroid Build Coastguard Worker    return fd
44*cda5da8dSAndroid Build Coastguard Worker
45*cda5da8dSAndroid Build Coastguard Worker
46*cda5da8dSAndroid Build Coastguard WorkerSelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
47*cda5da8dSAndroid Build Coastguard Worker
48*cda5da8dSAndroid Build Coastguard WorkerSelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
49*cda5da8dSAndroid Build Coastguard Worker
50*cda5da8dSAndroid Build Coastguard Worker    Object used to associate a file object to its backing
51*cda5da8dSAndroid Build Coastguard Worker    file descriptor, selected event mask, and attached data.
52*cda5da8dSAndroid Build Coastguard Worker"""
53*cda5da8dSAndroid Build Coastguard WorkerSelectorKey.fileobj.__doc__ = 'File object registered.'
54*cda5da8dSAndroid Build Coastguard WorkerSelectorKey.fd.__doc__ = 'Underlying file descriptor.'
55*cda5da8dSAndroid Build Coastguard WorkerSelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
56*cda5da8dSAndroid Build Coastguard WorkerSelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
57*cda5da8dSAndroid Build Coastguard WorkerFor example, this could be used to store a per-client session ID.''')
58*cda5da8dSAndroid Build Coastguard Worker
59*cda5da8dSAndroid Build Coastguard Worker
60*cda5da8dSAndroid Build Coastguard Workerclass _SelectorMapping(Mapping):
61*cda5da8dSAndroid Build Coastguard Worker    """Mapping of file objects to selector keys."""
62*cda5da8dSAndroid Build Coastguard Worker
63*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, selector):
64*cda5da8dSAndroid Build Coastguard Worker        self._selector = selector
65*cda5da8dSAndroid Build Coastguard Worker
66*cda5da8dSAndroid Build Coastguard Worker    def __len__(self):
67*cda5da8dSAndroid Build Coastguard Worker        return len(self._selector._fd_to_key)
68*cda5da8dSAndroid Build Coastguard Worker
69*cda5da8dSAndroid Build Coastguard Worker    def __getitem__(self, fileobj):
70*cda5da8dSAndroid Build Coastguard Worker        try:
71*cda5da8dSAndroid Build Coastguard Worker            fd = self._selector._fileobj_lookup(fileobj)
72*cda5da8dSAndroid Build Coastguard Worker            return self._selector._fd_to_key[fd]
73*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
74*cda5da8dSAndroid Build Coastguard Worker            raise KeyError("{!r} is not registered".format(fileobj)) from None
75*cda5da8dSAndroid Build Coastguard Worker
76*cda5da8dSAndroid Build Coastguard Worker    def __iter__(self):
77*cda5da8dSAndroid Build Coastguard Worker        return iter(self._selector._fd_to_key)
78*cda5da8dSAndroid Build Coastguard Worker
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Workerclass BaseSelector(metaclass=ABCMeta):
81*cda5da8dSAndroid Build Coastguard Worker    """Selector abstract base class.
82*cda5da8dSAndroid Build Coastguard Worker
83*cda5da8dSAndroid Build Coastguard Worker    A selector supports registering file objects to be monitored for specific
84*cda5da8dSAndroid Build Coastguard Worker    I/O events.
85*cda5da8dSAndroid Build Coastguard Worker
86*cda5da8dSAndroid Build Coastguard Worker    A file object is a file descriptor or any object with a `fileno()` method.
87*cda5da8dSAndroid Build Coastguard Worker    An arbitrary object can be attached to the file object, which can be used
88*cda5da8dSAndroid Build Coastguard Worker    for example to store context information, a callback, etc.
89*cda5da8dSAndroid Build Coastguard Worker
90*cda5da8dSAndroid Build Coastguard Worker    A selector can use various implementations (select(), poll(), epoll()...)
91*cda5da8dSAndroid Build Coastguard Worker    depending on the platform. The default `Selector` class uses the most
92*cda5da8dSAndroid Build Coastguard Worker    efficient implementation on the current platform.
93*cda5da8dSAndroid Build Coastguard Worker    """
94*cda5da8dSAndroid Build Coastguard Worker
95*cda5da8dSAndroid Build Coastguard Worker    @abstractmethod
96*cda5da8dSAndroid Build Coastguard Worker    def register(self, fileobj, events, data=None):
97*cda5da8dSAndroid Build Coastguard Worker        """Register a file object.
98*cda5da8dSAndroid Build Coastguard Worker
99*cda5da8dSAndroid Build Coastguard Worker        Parameters:
100*cda5da8dSAndroid Build Coastguard Worker        fileobj -- file object or file descriptor
101*cda5da8dSAndroid Build Coastguard Worker        events  -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
102*cda5da8dSAndroid Build Coastguard Worker        data    -- attached data
103*cda5da8dSAndroid Build Coastguard Worker
104*cda5da8dSAndroid Build Coastguard Worker        Returns:
105*cda5da8dSAndroid Build Coastguard Worker        SelectorKey instance
106*cda5da8dSAndroid Build Coastguard Worker
107*cda5da8dSAndroid Build Coastguard Worker        Raises:
108*cda5da8dSAndroid Build Coastguard Worker        ValueError if events is invalid
109*cda5da8dSAndroid Build Coastguard Worker        KeyError if fileobj is already registered
110*cda5da8dSAndroid Build Coastguard Worker        OSError if fileobj is closed or otherwise is unacceptable to
111*cda5da8dSAndroid Build Coastguard Worker                the underlying system call (if a system call is made)
112*cda5da8dSAndroid Build Coastguard Worker
113*cda5da8dSAndroid Build Coastguard Worker        Note:
114*cda5da8dSAndroid Build Coastguard Worker        OSError may or may not be raised
115*cda5da8dSAndroid Build Coastguard Worker        """
116*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
117*cda5da8dSAndroid Build Coastguard Worker
118*cda5da8dSAndroid Build Coastguard Worker    @abstractmethod
119*cda5da8dSAndroid Build Coastguard Worker    def unregister(self, fileobj):
120*cda5da8dSAndroid Build Coastguard Worker        """Unregister a file object.
121*cda5da8dSAndroid Build Coastguard Worker
122*cda5da8dSAndroid Build Coastguard Worker        Parameters:
123*cda5da8dSAndroid Build Coastguard Worker        fileobj -- file object or file descriptor
124*cda5da8dSAndroid Build Coastguard Worker
125*cda5da8dSAndroid Build Coastguard Worker        Returns:
126*cda5da8dSAndroid Build Coastguard Worker        SelectorKey instance
127*cda5da8dSAndroid Build Coastguard Worker
128*cda5da8dSAndroid Build Coastguard Worker        Raises:
129*cda5da8dSAndroid Build Coastguard Worker        KeyError if fileobj is not registered
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Worker        Note:
132*cda5da8dSAndroid Build Coastguard Worker        If fileobj is registered but has since been closed this does
133*cda5da8dSAndroid Build Coastguard Worker        *not* raise OSError (even if the wrapped syscall does)
134*cda5da8dSAndroid Build Coastguard Worker        """
135*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
136*cda5da8dSAndroid Build Coastguard Worker
137*cda5da8dSAndroid Build Coastguard Worker    def modify(self, fileobj, events, data=None):
138*cda5da8dSAndroid Build Coastguard Worker        """Change a registered file object monitored events or attached data.
139*cda5da8dSAndroid Build Coastguard Worker
140*cda5da8dSAndroid Build Coastguard Worker        Parameters:
141*cda5da8dSAndroid Build Coastguard Worker        fileobj -- file object or file descriptor
142*cda5da8dSAndroid Build Coastguard Worker        events  -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
143*cda5da8dSAndroid Build Coastguard Worker        data    -- attached data
144*cda5da8dSAndroid Build Coastguard Worker
145*cda5da8dSAndroid Build Coastguard Worker        Returns:
146*cda5da8dSAndroid Build Coastguard Worker        SelectorKey instance
147*cda5da8dSAndroid Build Coastguard Worker
148*cda5da8dSAndroid Build Coastguard Worker        Raises:
149*cda5da8dSAndroid Build Coastguard Worker        Anything that unregister() or register() raises
150*cda5da8dSAndroid Build Coastguard Worker        """
151*cda5da8dSAndroid Build Coastguard Worker        self.unregister(fileobj)
152*cda5da8dSAndroid Build Coastguard Worker        return self.register(fileobj, events, data)
153*cda5da8dSAndroid Build Coastguard Worker
154*cda5da8dSAndroid Build Coastguard Worker    @abstractmethod
155*cda5da8dSAndroid Build Coastguard Worker    def select(self, timeout=None):
156*cda5da8dSAndroid Build Coastguard Worker        """Perform the actual selection, until some monitored file objects are
157*cda5da8dSAndroid Build Coastguard Worker        ready or a timeout expires.
158*cda5da8dSAndroid Build Coastguard Worker
159*cda5da8dSAndroid Build Coastguard Worker        Parameters:
160*cda5da8dSAndroid Build Coastguard Worker        timeout -- if timeout > 0, this specifies the maximum wait time, in
161*cda5da8dSAndroid Build Coastguard Worker                   seconds
162*cda5da8dSAndroid Build Coastguard Worker                   if timeout <= 0, the select() call won't block, and will
163*cda5da8dSAndroid Build Coastguard Worker                   report the currently ready file objects
164*cda5da8dSAndroid Build Coastguard Worker                   if timeout is None, select() will block until a monitored
165*cda5da8dSAndroid Build Coastguard Worker                   file object becomes ready
166*cda5da8dSAndroid Build Coastguard Worker
167*cda5da8dSAndroid Build Coastguard Worker        Returns:
168*cda5da8dSAndroid Build Coastguard Worker        list of (key, events) for ready file objects
169*cda5da8dSAndroid Build Coastguard Worker        `events` is a bitwise mask of EVENT_READ|EVENT_WRITE
170*cda5da8dSAndroid Build Coastguard Worker        """
171*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
172*cda5da8dSAndroid Build Coastguard Worker
173*cda5da8dSAndroid Build Coastguard Worker    def close(self):
174*cda5da8dSAndroid Build Coastguard Worker        """Close the selector.
175*cda5da8dSAndroid Build Coastguard Worker
176*cda5da8dSAndroid Build Coastguard Worker        This must be called to make sure that any underlying resource is freed.
177*cda5da8dSAndroid Build Coastguard Worker        """
178*cda5da8dSAndroid Build Coastguard Worker        pass
179*cda5da8dSAndroid Build Coastguard Worker
180*cda5da8dSAndroid Build Coastguard Worker    def get_key(self, fileobj):
181*cda5da8dSAndroid Build Coastguard Worker        """Return the key associated to a registered file object.
182*cda5da8dSAndroid Build Coastguard Worker
183*cda5da8dSAndroid Build Coastguard Worker        Returns:
184*cda5da8dSAndroid Build Coastguard Worker        SelectorKey for this file object
185*cda5da8dSAndroid Build Coastguard Worker        """
186*cda5da8dSAndroid Build Coastguard Worker        mapping = self.get_map()
187*cda5da8dSAndroid Build Coastguard Worker        if mapping is None:
188*cda5da8dSAndroid Build Coastguard Worker            raise RuntimeError('Selector is closed')
189*cda5da8dSAndroid Build Coastguard Worker        try:
190*cda5da8dSAndroid Build Coastguard Worker            return mapping[fileobj]
191*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
192*cda5da8dSAndroid Build Coastguard Worker            raise KeyError("{!r} is not registered".format(fileobj)) from None
193*cda5da8dSAndroid Build Coastguard Worker
194*cda5da8dSAndroid Build Coastguard Worker    @abstractmethod
195*cda5da8dSAndroid Build Coastguard Worker    def get_map(self):
196*cda5da8dSAndroid Build Coastguard Worker        """Return a mapping of file objects to selector keys."""
197*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
198*cda5da8dSAndroid Build Coastguard Worker
199*cda5da8dSAndroid Build Coastguard Worker    def __enter__(self):
200*cda5da8dSAndroid Build Coastguard Worker        return self
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker    def __exit__(self, *args):
203*cda5da8dSAndroid Build Coastguard Worker        self.close()
204*cda5da8dSAndroid Build Coastguard Worker
205*cda5da8dSAndroid Build Coastguard Worker
206*cda5da8dSAndroid Build Coastguard Workerclass _BaseSelectorImpl(BaseSelector):
207*cda5da8dSAndroid Build Coastguard Worker    """Base selector implementation."""
208*cda5da8dSAndroid Build Coastguard Worker
209*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
210*cda5da8dSAndroid Build Coastguard Worker        # this maps file descriptors to keys
211*cda5da8dSAndroid Build Coastguard Worker        self._fd_to_key = {}
212*cda5da8dSAndroid Build Coastguard Worker        # read-only mapping returned by get_map()
213*cda5da8dSAndroid Build Coastguard Worker        self._map = _SelectorMapping(self)
214*cda5da8dSAndroid Build Coastguard Worker
215*cda5da8dSAndroid Build Coastguard Worker    def _fileobj_lookup(self, fileobj):
216*cda5da8dSAndroid Build Coastguard Worker        """Return a file descriptor from a file object.
217*cda5da8dSAndroid Build Coastguard Worker
218*cda5da8dSAndroid Build Coastguard Worker        This wraps _fileobj_to_fd() to do an exhaustive search in case
219*cda5da8dSAndroid Build Coastguard Worker        the object is invalid but we still have it in our map.  This
220*cda5da8dSAndroid Build Coastguard Worker        is used by unregister() so we can unregister an object that
221*cda5da8dSAndroid Build Coastguard Worker        was previously registered even if it is closed.  It is also
222*cda5da8dSAndroid Build Coastguard Worker        used by _SelectorMapping.
223*cda5da8dSAndroid Build Coastguard Worker        """
224*cda5da8dSAndroid Build Coastguard Worker        try:
225*cda5da8dSAndroid Build Coastguard Worker            return _fileobj_to_fd(fileobj)
226*cda5da8dSAndroid Build Coastguard Worker        except ValueError:
227*cda5da8dSAndroid Build Coastguard Worker            # Do an exhaustive search.
228*cda5da8dSAndroid Build Coastguard Worker            for key in self._fd_to_key.values():
229*cda5da8dSAndroid Build Coastguard Worker                if key.fileobj is fileobj:
230*cda5da8dSAndroid Build Coastguard Worker                    return key.fd
231*cda5da8dSAndroid Build Coastguard Worker            # Raise ValueError after all.
232*cda5da8dSAndroid Build Coastguard Worker            raise
233*cda5da8dSAndroid Build Coastguard Worker
234*cda5da8dSAndroid Build Coastguard Worker    def register(self, fileobj, events, data=None):
235*cda5da8dSAndroid Build Coastguard Worker        if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
236*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("Invalid events: {!r}".format(events))
237*cda5da8dSAndroid Build Coastguard Worker
238*cda5da8dSAndroid Build Coastguard Worker        key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
239*cda5da8dSAndroid Build Coastguard Worker
240*cda5da8dSAndroid Build Coastguard Worker        if key.fd in self._fd_to_key:
241*cda5da8dSAndroid Build Coastguard Worker            raise KeyError("{!r} (FD {}) is already registered"
242*cda5da8dSAndroid Build Coastguard Worker                           .format(fileobj, key.fd))
243*cda5da8dSAndroid Build Coastguard Worker
244*cda5da8dSAndroid Build Coastguard Worker        self._fd_to_key[key.fd] = key
245*cda5da8dSAndroid Build Coastguard Worker        return key
246*cda5da8dSAndroid Build Coastguard Worker
247*cda5da8dSAndroid Build Coastguard Worker    def unregister(self, fileobj):
248*cda5da8dSAndroid Build Coastguard Worker        try:
249*cda5da8dSAndroid Build Coastguard Worker            key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
250*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
251*cda5da8dSAndroid Build Coastguard Worker            raise KeyError("{!r} is not registered".format(fileobj)) from None
252*cda5da8dSAndroid Build Coastguard Worker        return key
253*cda5da8dSAndroid Build Coastguard Worker
254*cda5da8dSAndroid Build Coastguard Worker    def modify(self, fileobj, events, data=None):
255*cda5da8dSAndroid Build Coastguard Worker        try:
256*cda5da8dSAndroid Build Coastguard Worker            key = self._fd_to_key[self._fileobj_lookup(fileobj)]
257*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
258*cda5da8dSAndroid Build Coastguard Worker            raise KeyError("{!r} is not registered".format(fileobj)) from None
259*cda5da8dSAndroid Build Coastguard Worker        if events != key.events:
260*cda5da8dSAndroid Build Coastguard Worker            self.unregister(fileobj)
261*cda5da8dSAndroid Build Coastguard Worker            key = self.register(fileobj, events, data)
262*cda5da8dSAndroid Build Coastguard Worker        elif data != key.data:
263*cda5da8dSAndroid Build Coastguard Worker            # Use a shortcut to update the data.
264*cda5da8dSAndroid Build Coastguard Worker            key = key._replace(data=data)
265*cda5da8dSAndroid Build Coastguard Worker            self._fd_to_key[key.fd] = key
266*cda5da8dSAndroid Build Coastguard Worker        return key
267*cda5da8dSAndroid Build Coastguard Worker
268*cda5da8dSAndroid Build Coastguard Worker    def close(self):
269*cda5da8dSAndroid Build Coastguard Worker        self._fd_to_key.clear()
270*cda5da8dSAndroid Build Coastguard Worker        self._map = None
271*cda5da8dSAndroid Build Coastguard Worker
272*cda5da8dSAndroid Build Coastguard Worker    def get_map(self):
273*cda5da8dSAndroid Build Coastguard Worker        return self._map
274*cda5da8dSAndroid Build Coastguard Worker
275*cda5da8dSAndroid Build Coastguard Worker    def _key_from_fd(self, fd):
276*cda5da8dSAndroid Build Coastguard Worker        """Return the key associated to a given file descriptor.
277*cda5da8dSAndroid Build Coastguard Worker
278*cda5da8dSAndroid Build Coastguard Worker        Parameters:
279*cda5da8dSAndroid Build Coastguard Worker        fd -- file descriptor
280*cda5da8dSAndroid Build Coastguard Worker
281*cda5da8dSAndroid Build Coastguard Worker        Returns:
282*cda5da8dSAndroid Build Coastguard Worker        corresponding key, or None if not found
283*cda5da8dSAndroid Build Coastguard Worker        """
284*cda5da8dSAndroid Build Coastguard Worker        try:
285*cda5da8dSAndroid Build Coastguard Worker            return self._fd_to_key[fd]
286*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
287*cda5da8dSAndroid Build Coastguard Worker            return None
288*cda5da8dSAndroid Build Coastguard Worker
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Workerclass SelectSelector(_BaseSelectorImpl):
291*cda5da8dSAndroid Build Coastguard Worker    """Select-based selector."""
292*cda5da8dSAndroid Build Coastguard Worker
293*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
294*cda5da8dSAndroid Build Coastguard Worker        super().__init__()
295*cda5da8dSAndroid Build Coastguard Worker        self._readers = set()
296*cda5da8dSAndroid Build Coastguard Worker        self._writers = set()
297*cda5da8dSAndroid Build Coastguard Worker
298*cda5da8dSAndroid Build Coastguard Worker    def register(self, fileobj, events, data=None):
299*cda5da8dSAndroid Build Coastguard Worker        key = super().register(fileobj, events, data)
300*cda5da8dSAndroid Build Coastguard Worker        if events & EVENT_READ:
301*cda5da8dSAndroid Build Coastguard Worker            self._readers.add(key.fd)
302*cda5da8dSAndroid Build Coastguard Worker        if events & EVENT_WRITE:
303*cda5da8dSAndroid Build Coastguard Worker            self._writers.add(key.fd)
304*cda5da8dSAndroid Build Coastguard Worker        return key
305*cda5da8dSAndroid Build Coastguard Worker
306*cda5da8dSAndroid Build Coastguard Worker    def unregister(self, fileobj):
307*cda5da8dSAndroid Build Coastguard Worker        key = super().unregister(fileobj)
308*cda5da8dSAndroid Build Coastguard Worker        self._readers.discard(key.fd)
309*cda5da8dSAndroid Build Coastguard Worker        self._writers.discard(key.fd)
310*cda5da8dSAndroid Build Coastguard Worker        return key
311*cda5da8dSAndroid Build Coastguard Worker
312*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == 'win32':
313*cda5da8dSAndroid Build Coastguard Worker        def _select(self, r, w, _, timeout=None):
314*cda5da8dSAndroid Build Coastguard Worker            r, w, x = select.select(r, w, w, timeout)
315*cda5da8dSAndroid Build Coastguard Worker            return r, w + x, []
316*cda5da8dSAndroid Build Coastguard Worker    else:
317*cda5da8dSAndroid Build Coastguard Worker        _select = select.select
318*cda5da8dSAndroid Build Coastguard Worker
319*cda5da8dSAndroid Build Coastguard Worker    def select(self, timeout=None):
320*cda5da8dSAndroid Build Coastguard Worker        timeout = None if timeout is None else max(timeout, 0)
321*cda5da8dSAndroid Build Coastguard Worker        ready = []
322*cda5da8dSAndroid Build Coastguard Worker        try:
323*cda5da8dSAndroid Build Coastguard Worker            r, w, _ = self._select(self._readers, self._writers, [], timeout)
324*cda5da8dSAndroid Build Coastguard Worker        except InterruptedError:
325*cda5da8dSAndroid Build Coastguard Worker            return ready
326*cda5da8dSAndroid Build Coastguard Worker        r = set(r)
327*cda5da8dSAndroid Build Coastguard Worker        w = set(w)
328*cda5da8dSAndroid Build Coastguard Worker        for fd in r | w:
329*cda5da8dSAndroid Build Coastguard Worker            events = 0
330*cda5da8dSAndroid Build Coastguard Worker            if fd in r:
331*cda5da8dSAndroid Build Coastguard Worker                events |= EVENT_READ
332*cda5da8dSAndroid Build Coastguard Worker            if fd in w:
333*cda5da8dSAndroid Build Coastguard Worker                events |= EVENT_WRITE
334*cda5da8dSAndroid Build Coastguard Worker
335*cda5da8dSAndroid Build Coastguard Worker            key = self._key_from_fd(fd)
336*cda5da8dSAndroid Build Coastguard Worker            if key:
337*cda5da8dSAndroid Build Coastguard Worker                ready.append((key, events & key.events))
338*cda5da8dSAndroid Build Coastguard Worker        return ready
339*cda5da8dSAndroid Build Coastguard Worker
340*cda5da8dSAndroid Build Coastguard Worker
341*cda5da8dSAndroid Build Coastguard Workerclass _PollLikeSelector(_BaseSelectorImpl):
342*cda5da8dSAndroid Build Coastguard Worker    """Base class shared between poll, epoll and devpoll selectors."""
343*cda5da8dSAndroid Build Coastguard Worker    _selector_cls = None
344*cda5da8dSAndroid Build Coastguard Worker    _EVENT_READ = None
345*cda5da8dSAndroid Build Coastguard Worker    _EVENT_WRITE = None
346*cda5da8dSAndroid Build Coastguard Worker
347*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
348*cda5da8dSAndroid Build Coastguard Worker        super().__init__()
349*cda5da8dSAndroid Build Coastguard Worker        self._selector = self._selector_cls()
350*cda5da8dSAndroid Build Coastguard Worker
351*cda5da8dSAndroid Build Coastguard Worker    def register(self, fileobj, events, data=None):
352*cda5da8dSAndroid Build Coastguard Worker        key = super().register(fileobj, events, data)
353*cda5da8dSAndroid Build Coastguard Worker        poller_events = 0
354*cda5da8dSAndroid Build Coastguard Worker        if events & EVENT_READ:
355*cda5da8dSAndroid Build Coastguard Worker            poller_events |= self._EVENT_READ
356*cda5da8dSAndroid Build Coastguard Worker        if events & EVENT_WRITE:
357*cda5da8dSAndroid Build Coastguard Worker            poller_events |= self._EVENT_WRITE
358*cda5da8dSAndroid Build Coastguard Worker        try:
359*cda5da8dSAndroid Build Coastguard Worker            self._selector.register(key.fd, poller_events)
360*cda5da8dSAndroid Build Coastguard Worker        except:
361*cda5da8dSAndroid Build Coastguard Worker            super().unregister(fileobj)
362*cda5da8dSAndroid Build Coastguard Worker            raise
363*cda5da8dSAndroid Build Coastguard Worker        return key
364*cda5da8dSAndroid Build Coastguard Worker
365*cda5da8dSAndroid Build Coastguard Worker    def unregister(self, fileobj):
366*cda5da8dSAndroid Build Coastguard Worker        key = super().unregister(fileobj)
367*cda5da8dSAndroid Build Coastguard Worker        try:
368*cda5da8dSAndroid Build Coastguard Worker            self._selector.unregister(key.fd)
369*cda5da8dSAndroid Build Coastguard Worker        except OSError:
370*cda5da8dSAndroid Build Coastguard Worker            # This can happen if the FD was closed since it
371*cda5da8dSAndroid Build Coastguard Worker            # was registered.
372*cda5da8dSAndroid Build Coastguard Worker            pass
373*cda5da8dSAndroid Build Coastguard Worker        return key
374*cda5da8dSAndroid Build Coastguard Worker
375*cda5da8dSAndroid Build Coastguard Worker    def modify(self, fileobj, events, data=None):
376*cda5da8dSAndroid Build Coastguard Worker        try:
377*cda5da8dSAndroid Build Coastguard Worker            key = self._fd_to_key[self._fileobj_lookup(fileobj)]
378*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
379*cda5da8dSAndroid Build Coastguard Worker            raise KeyError(f"{fileobj!r} is not registered") from None
380*cda5da8dSAndroid Build Coastguard Worker
381*cda5da8dSAndroid Build Coastguard Worker        changed = False
382*cda5da8dSAndroid Build Coastguard Worker        if events != key.events:
383*cda5da8dSAndroid Build Coastguard Worker            selector_events = 0
384*cda5da8dSAndroid Build Coastguard Worker            if events & EVENT_READ:
385*cda5da8dSAndroid Build Coastguard Worker                selector_events |= self._EVENT_READ
386*cda5da8dSAndroid Build Coastguard Worker            if events & EVENT_WRITE:
387*cda5da8dSAndroid Build Coastguard Worker                selector_events |= self._EVENT_WRITE
388*cda5da8dSAndroid Build Coastguard Worker            try:
389*cda5da8dSAndroid Build Coastguard Worker                self._selector.modify(key.fd, selector_events)
390*cda5da8dSAndroid Build Coastguard Worker            except:
391*cda5da8dSAndroid Build Coastguard Worker                super().unregister(fileobj)
392*cda5da8dSAndroid Build Coastguard Worker                raise
393*cda5da8dSAndroid Build Coastguard Worker            changed = True
394*cda5da8dSAndroid Build Coastguard Worker        if data != key.data:
395*cda5da8dSAndroid Build Coastguard Worker            changed = True
396*cda5da8dSAndroid Build Coastguard Worker
397*cda5da8dSAndroid Build Coastguard Worker        if changed:
398*cda5da8dSAndroid Build Coastguard Worker            key = key._replace(events=events, data=data)
399*cda5da8dSAndroid Build Coastguard Worker            self._fd_to_key[key.fd] = key
400*cda5da8dSAndroid Build Coastguard Worker        return key
401*cda5da8dSAndroid Build Coastguard Worker
402*cda5da8dSAndroid Build Coastguard Worker    def select(self, timeout=None):
403*cda5da8dSAndroid Build Coastguard Worker        # This is shared between poll() and epoll().
404*cda5da8dSAndroid Build Coastguard Worker        # epoll() has a different signature and handling of timeout parameter.
405*cda5da8dSAndroid Build Coastguard Worker        if timeout is None:
406*cda5da8dSAndroid Build Coastguard Worker            timeout = None
407*cda5da8dSAndroid Build Coastguard Worker        elif timeout <= 0:
408*cda5da8dSAndroid Build Coastguard Worker            timeout = 0
409*cda5da8dSAndroid Build Coastguard Worker        else:
410*cda5da8dSAndroid Build Coastguard Worker            # poll() has a resolution of 1 millisecond, round away from
411*cda5da8dSAndroid Build Coastguard Worker            # zero to wait *at least* timeout seconds.
412*cda5da8dSAndroid Build Coastguard Worker            timeout = math.ceil(timeout * 1e3)
413*cda5da8dSAndroid Build Coastguard Worker        ready = []
414*cda5da8dSAndroid Build Coastguard Worker        try:
415*cda5da8dSAndroid Build Coastguard Worker            fd_event_list = self._selector.poll(timeout)
416*cda5da8dSAndroid Build Coastguard Worker        except InterruptedError:
417*cda5da8dSAndroid Build Coastguard Worker            return ready
418*cda5da8dSAndroid Build Coastguard Worker        for fd, event in fd_event_list:
419*cda5da8dSAndroid Build Coastguard Worker            events = 0
420*cda5da8dSAndroid Build Coastguard Worker            if event & ~self._EVENT_READ:
421*cda5da8dSAndroid Build Coastguard Worker                events |= EVENT_WRITE
422*cda5da8dSAndroid Build Coastguard Worker            if event & ~self._EVENT_WRITE:
423*cda5da8dSAndroid Build Coastguard Worker                events |= EVENT_READ
424*cda5da8dSAndroid Build Coastguard Worker
425*cda5da8dSAndroid Build Coastguard Worker            key = self._key_from_fd(fd)
426*cda5da8dSAndroid Build Coastguard Worker            if key:
427*cda5da8dSAndroid Build Coastguard Worker                ready.append((key, events & key.events))
428*cda5da8dSAndroid Build Coastguard Worker        return ready
429*cda5da8dSAndroid Build Coastguard Worker
430*cda5da8dSAndroid Build Coastguard Worker
431*cda5da8dSAndroid Build Coastguard Workerif hasattr(select, 'poll'):
432*cda5da8dSAndroid Build Coastguard Worker
433*cda5da8dSAndroid Build Coastguard Worker    class PollSelector(_PollLikeSelector):
434*cda5da8dSAndroid Build Coastguard Worker        """Poll-based selector."""
435*cda5da8dSAndroid Build Coastguard Worker        _selector_cls = select.poll
436*cda5da8dSAndroid Build Coastguard Worker        _EVENT_READ = select.POLLIN
437*cda5da8dSAndroid Build Coastguard Worker        _EVENT_WRITE = select.POLLOUT
438*cda5da8dSAndroid Build Coastguard Worker
439*cda5da8dSAndroid Build Coastguard Worker
440*cda5da8dSAndroid Build Coastguard Workerif hasattr(select, 'epoll'):
441*cda5da8dSAndroid Build Coastguard Worker
442*cda5da8dSAndroid Build Coastguard Worker    class EpollSelector(_PollLikeSelector):
443*cda5da8dSAndroid Build Coastguard Worker        """Epoll-based selector."""
444*cda5da8dSAndroid Build Coastguard Worker        _selector_cls = select.epoll
445*cda5da8dSAndroid Build Coastguard Worker        _EVENT_READ = select.EPOLLIN
446*cda5da8dSAndroid Build Coastguard Worker        _EVENT_WRITE = select.EPOLLOUT
447*cda5da8dSAndroid Build Coastguard Worker
448*cda5da8dSAndroid Build Coastguard Worker        def fileno(self):
449*cda5da8dSAndroid Build Coastguard Worker            return self._selector.fileno()
450*cda5da8dSAndroid Build Coastguard Worker
451*cda5da8dSAndroid Build Coastguard Worker        def select(self, timeout=None):
452*cda5da8dSAndroid Build Coastguard Worker            if timeout is None:
453*cda5da8dSAndroid Build Coastguard Worker                timeout = -1
454*cda5da8dSAndroid Build Coastguard Worker            elif timeout <= 0:
455*cda5da8dSAndroid Build Coastguard Worker                timeout = 0
456*cda5da8dSAndroid Build Coastguard Worker            else:
457*cda5da8dSAndroid Build Coastguard Worker                # epoll_wait() has a resolution of 1 millisecond, round away
458*cda5da8dSAndroid Build Coastguard Worker                # from zero to wait *at least* timeout seconds.
459*cda5da8dSAndroid Build Coastguard Worker                timeout = math.ceil(timeout * 1e3) * 1e-3
460*cda5da8dSAndroid Build Coastguard Worker
461*cda5da8dSAndroid Build Coastguard Worker            # epoll_wait() expects `maxevents` to be greater than zero;
462*cda5da8dSAndroid Build Coastguard Worker            # we want to make sure that `select()` can be called when no
463*cda5da8dSAndroid Build Coastguard Worker            # FD is registered.
464*cda5da8dSAndroid Build Coastguard Worker            max_ev = max(len(self._fd_to_key), 1)
465*cda5da8dSAndroid Build Coastguard Worker
466*cda5da8dSAndroid Build Coastguard Worker            ready = []
467*cda5da8dSAndroid Build Coastguard Worker            try:
468*cda5da8dSAndroid Build Coastguard Worker                fd_event_list = self._selector.poll(timeout, max_ev)
469*cda5da8dSAndroid Build Coastguard Worker            except InterruptedError:
470*cda5da8dSAndroid Build Coastguard Worker                return ready
471*cda5da8dSAndroid Build Coastguard Worker            for fd, event in fd_event_list:
472*cda5da8dSAndroid Build Coastguard Worker                events = 0
473*cda5da8dSAndroid Build Coastguard Worker                if event & ~select.EPOLLIN:
474*cda5da8dSAndroid Build Coastguard Worker                    events |= EVENT_WRITE
475*cda5da8dSAndroid Build Coastguard Worker                if event & ~select.EPOLLOUT:
476*cda5da8dSAndroid Build Coastguard Worker                    events |= EVENT_READ
477*cda5da8dSAndroid Build Coastguard Worker
478*cda5da8dSAndroid Build Coastguard Worker                key = self._key_from_fd(fd)
479*cda5da8dSAndroid Build Coastguard Worker                if key:
480*cda5da8dSAndroid Build Coastguard Worker                    ready.append((key, events & key.events))
481*cda5da8dSAndroid Build Coastguard Worker            return ready
482*cda5da8dSAndroid Build Coastguard Worker
483*cda5da8dSAndroid Build Coastguard Worker        def close(self):
484*cda5da8dSAndroid Build Coastguard Worker            self._selector.close()
485*cda5da8dSAndroid Build Coastguard Worker            super().close()
486*cda5da8dSAndroid Build Coastguard Worker
487*cda5da8dSAndroid Build Coastguard Worker
488*cda5da8dSAndroid Build Coastguard Workerif hasattr(select, 'devpoll'):
489*cda5da8dSAndroid Build Coastguard Worker
490*cda5da8dSAndroid Build Coastguard Worker    class DevpollSelector(_PollLikeSelector):
491*cda5da8dSAndroid Build Coastguard Worker        """Solaris /dev/poll selector."""
492*cda5da8dSAndroid Build Coastguard Worker        _selector_cls = select.devpoll
493*cda5da8dSAndroid Build Coastguard Worker        _EVENT_READ = select.POLLIN
494*cda5da8dSAndroid Build Coastguard Worker        _EVENT_WRITE = select.POLLOUT
495*cda5da8dSAndroid Build Coastguard Worker
496*cda5da8dSAndroid Build Coastguard Worker        def fileno(self):
497*cda5da8dSAndroid Build Coastguard Worker            return self._selector.fileno()
498*cda5da8dSAndroid Build Coastguard Worker
499*cda5da8dSAndroid Build Coastguard Worker        def close(self):
500*cda5da8dSAndroid Build Coastguard Worker            self._selector.close()
501*cda5da8dSAndroid Build Coastguard Worker            super().close()
502*cda5da8dSAndroid Build Coastguard Worker
503*cda5da8dSAndroid Build Coastguard Worker
504*cda5da8dSAndroid Build Coastguard Workerif hasattr(select, 'kqueue'):
505*cda5da8dSAndroid Build Coastguard Worker
506*cda5da8dSAndroid Build Coastguard Worker    class KqueueSelector(_BaseSelectorImpl):
507*cda5da8dSAndroid Build Coastguard Worker        """Kqueue-based selector."""
508*cda5da8dSAndroid Build Coastguard Worker
509*cda5da8dSAndroid Build Coastguard Worker        def __init__(self):
510*cda5da8dSAndroid Build Coastguard Worker            super().__init__()
511*cda5da8dSAndroid Build Coastguard Worker            self._selector = select.kqueue()
512*cda5da8dSAndroid Build Coastguard Worker
513*cda5da8dSAndroid Build Coastguard Worker        def fileno(self):
514*cda5da8dSAndroid Build Coastguard Worker            return self._selector.fileno()
515*cda5da8dSAndroid Build Coastguard Worker
516*cda5da8dSAndroid Build Coastguard Worker        def register(self, fileobj, events, data=None):
517*cda5da8dSAndroid Build Coastguard Worker            key = super().register(fileobj, events, data)
518*cda5da8dSAndroid Build Coastguard Worker            try:
519*cda5da8dSAndroid Build Coastguard Worker                if events & EVENT_READ:
520*cda5da8dSAndroid Build Coastguard Worker                    kev = select.kevent(key.fd, select.KQ_FILTER_READ,
521*cda5da8dSAndroid Build Coastguard Worker                                        select.KQ_EV_ADD)
522*cda5da8dSAndroid Build Coastguard Worker                    self._selector.control([kev], 0, 0)
523*cda5da8dSAndroid Build Coastguard Worker                if events & EVENT_WRITE:
524*cda5da8dSAndroid Build Coastguard Worker                    kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
525*cda5da8dSAndroid Build Coastguard Worker                                        select.KQ_EV_ADD)
526*cda5da8dSAndroid Build Coastguard Worker                    self._selector.control([kev], 0, 0)
527*cda5da8dSAndroid Build Coastguard Worker            except:
528*cda5da8dSAndroid Build Coastguard Worker                super().unregister(fileobj)
529*cda5da8dSAndroid Build Coastguard Worker                raise
530*cda5da8dSAndroid Build Coastguard Worker            return key
531*cda5da8dSAndroid Build Coastguard Worker
532*cda5da8dSAndroid Build Coastguard Worker        def unregister(self, fileobj):
533*cda5da8dSAndroid Build Coastguard Worker            key = super().unregister(fileobj)
534*cda5da8dSAndroid Build Coastguard Worker            if key.events & EVENT_READ:
535*cda5da8dSAndroid Build Coastguard Worker                kev = select.kevent(key.fd, select.KQ_FILTER_READ,
536*cda5da8dSAndroid Build Coastguard Worker                                    select.KQ_EV_DELETE)
537*cda5da8dSAndroid Build Coastguard Worker                try:
538*cda5da8dSAndroid Build Coastguard Worker                    self._selector.control([kev], 0, 0)
539*cda5da8dSAndroid Build Coastguard Worker                except OSError:
540*cda5da8dSAndroid Build Coastguard Worker                    # This can happen if the FD was closed since it
541*cda5da8dSAndroid Build Coastguard Worker                    # was registered.
542*cda5da8dSAndroid Build Coastguard Worker                    pass
543*cda5da8dSAndroid Build Coastguard Worker            if key.events & EVENT_WRITE:
544*cda5da8dSAndroid Build Coastguard Worker                kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
545*cda5da8dSAndroid Build Coastguard Worker                                    select.KQ_EV_DELETE)
546*cda5da8dSAndroid Build Coastguard Worker                try:
547*cda5da8dSAndroid Build Coastguard Worker                    self._selector.control([kev], 0, 0)
548*cda5da8dSAndroid Build Coastguard Worker                except OSError:
549*cda5da8dSAndroid Build Coastguard Worker                    # See comment above.
550*cda5da8dSAndroid Build Coastguard Worker                    pass
551*cda5da8dSAndroid Build Coastguard Worker            return key
552*cda5da8dSAndroid Build Coastguard Worker
553*cda5da8dSAndroid Build Coastguard Worker        def select(self, timeout=None):
554*cda5da8dSAndroid Build Coastguard Worker            timeout = None if timeout is None else max(timeout, 0)
555*cda5da8dSAndroid Build Coastguard Worker            # If max_ev is 0, kqueue will ignore the timeout. For consistent
556*cda5da8dSAndroid Build Coastguard Worker            # behavior with the other selector classes, we prevent that here
557*cda5da8dSAndroid Build Coastguard Worker            # (using max). See https://bugs.python.org/issue29255
558*cda5da8dSAndroid Build Coastguard Worker            max_ev = max(len(self._fd_to_key), 1)
559*cda5da8dSAndroid Build Coastguard Worker            ready = []
560*cda5da8dSAndroid Build Coastguard Worker            try:
561*cda5da8dSAndroid Build Coastguard Worker                kev_list = self._selector.control(None, max_ev, timeout)
562*cda5da8dSAndroid Build Coastguard Worker            except InterruptedError:
563*cda5da8dSAndroid Build Coastguard Worker                return ready
564*cda5da8dSAndroid Build Coastguard Worker            for kev in kev_list:
565*cda5da8dSAndroid Build Coastguard Worker                fd = kev.ident
566*cda5da8dSAndroid Build Coastguard Worker                flag = kev.filter
567*cda5da8dSAndroid Build Coastguard Worker                events = 0
568*cda5da8dSAndroid Build Coastguard Worker                if flag == select.KQ_FILTER_READ:
569*cda5da8dSAndroid Build Coastguard Worker                    events |= EVENT_READ
570*cda5da8dSAndroid Build Coastguard Worker                if flag == select.KQ_FILTER_WRITE:
571*cda5da8dSAndroid Build Coastguard Worker                    events |= EVENT_WRITE
572*cda5da8dSAndroid Build Coastguard Worker
573*cda5da8dSAndroid Build Coastguard Worker                key = self._key_from_fd(fd)
574*cda5da8dSAndroid Build Coastguard Worker                if key:
575*cda5da8dSAndroid Build Coastguard Worker                    ready.append((key, events & key.events))
576*cda5da8dSAndroid Build Coastguard Worker            return ready
577*cda5da8dSAndroid Build Coastguard Worker
578*cda5da8dSAndroid Build Coastguard Worker        def close(self):
579*cda5da8dSAndroid Build Coastguard Worker            self._selector.close()
580*cda5da8dSAndroid Build Coastguard Worker            super().close()
581*cda5da8dSAndroid Build Coastguard Worker
582*cda5da8dSAndroid Build Coastguard Worker
583*cda5da8dSAndroid Build Coastguard Workerdef _can_use(method):
584*cda5da8dSAndroid Build Coastguard Worker    """Check if we can use the selector depending upon the
585*cda5da8dSAndroid Build Coastguard Worker    operating system. """
586*cda5da8dSAndroid Build Coastguard Worker    # Implementation based upon https://github.com/sethmlarson/selectors2/blob/master/selectors2.py
587*cda5da8dSAndroid Build Coastguard Worker    selector = getattr(select, method, None)
588*cda5da8dSAndroid Build Coastguard Worker    if selector is None:
589*cda5da8dSAndroid Build Coastguard Worker        # select module does not implement method
590*cda5da8dSAndroid Build Coastguard Worker        return False
591*cda5da8dSAndroid Build Coastguard Worker    # check if the OS and Kernel actually support the method. Call may fail with
592*cda5da8dSAndroid Build Coastguard Worker    # OSError: [Errno 38] Function not implemented
593*cda5da8dSAndroid Build Coastguard Worker    try:
594*cda5da8dSAndroid Build Coastguard Worker        selector_obj = selector()
595*cda5da8dSAndroid Build Coastguard Worker        if method == 'poll':
596*cda5da8dSAndroid Build Coastguard Worker            # check that poll actually works
597*cda5da8dSAndroid Build Coastguard Worker            selector_obj.poll(0)
598*cda5da8dSAndroid Build Coastguard Worker        else:
599*cda5da8dSAndroid Build Coastguard Worker            # close epoll, kqueue, and devpoll fd
600*cda5da8dSAndroid Build Coastguard Worker            selector_obj.close()
601*cda5da8dSAndroid Build Coastguard Worker        return True
602*cda5da8dSAndroid Build Coastguard Worker    except OSError:
603*cda5da8dSAndroid Build Coastguard Worker        return False
604*cda5da8dSAndroid Build Coastguard Worker
605*cda5da8dSAndroid Build Coastguard Worker
606*cda5da8dSAndroid Build Coastguard Worker# Choose the best implementation, roughly:
607*cda5da8dSAndroid Build Coastguard Worker#    epoll|kqueue|devpoll > poll > select.
608*cda5da8dSAndroid Build Coastguard Worker# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
609*cda5da8dSAndroid Build Coastguard Workerif _can_use('kqueue'):
610*cda5da8dSAndroid Build Coastguard Worker    DefaultSelector = KqueueSelector
611*cda5da8dSAndroid Build Coastguard Workerelif _can_use('epoll'):
612*cda5da8dSAndroid Build Coastguard Worker    DefaultSelector = EpollSelector
613*cda5da8dSAndroid Build Coastguard Workerelif _can_use('devpoll'):
614*cda5da8dSAndroid Build Coastguard Worker    DefaultSelector = DevpollSelector
615*cda5da8dSAndroid Build Coastguard Workerelif _can_use('poll'):
616*cda5da8dSAndroid Build Coastguard Worker    DefaultSelector = PollSelector
617*cda5da8dSAndroid Build Coastguard Workerelse:
618*cda5da8dSAndroid Build Coastguard Worker    DefaultSelector = SelectSelector
619