Select objects. Same than: ``select.select(inputs, [], [], remain)`` But also works on Windows, only on objects whose fileno() returns a Windows event. For simplicity, just use `ObjectPipe()` as a queue that you can select on whatever the platform is. If you want an object
(inputs, remain)
| 62 | |
| 63 | |
| 64 | def select_objects(inputs, remain): |
| 65 | # type: (Iterable[Any], Union[float, int, None]) -> List[Any] |
| 66 | """ |
| 67 | Select objects. Same than: |
| 68 | ``select.select(inputs, [], [], remain)`` |
| 69 | |
| 70 | But also works on Windows, only on objects whose fileno() returns |
| 71 | a Windows event. For simplicity, just use `ObjectPipe()` as a queue |
| 72 | that you can select on whatever the platform is. |
| 73 | |
| 74 | If you want an object to be always included in the output of |
| 75 | select_objects (i.e. it's not selectable), just make fileno() |
| 76 | return a strictly negative value. |
| 77 | |
| 78 | Example: |
| 79 | |
| 80 | >>> a, b = ObjectPipe("a"), ObjectPipe("b") |
| 81 | >>> b.send("test") |
| 82 | >>> select_objects([a, b], 1) |
| 83 | [b] |
| 84 | |
| 85 | :param inputs: objects to process |
| 86 | :param remain: timeout. If 0, poll. If None, block. |
| 87 | """ |
| 88 | if not WINDOWS: |
| 89 | return select.select(inputs, [], [], remain)[0] |
| 90 | inputs = list(inputs) |
| 91 | events = [] |
| 92 | created = [] |
| 93 | results = set() |
| 94 | for i in inputs: |
| 95 | if getattr(i, "__selectable_force_select__", False): |
| 96 | # Native socket.socket object. We would normally use select.select. |
| 97 | evt = ctypes.windll.ws2_32.WSACreateEvent() |
| 98 | created.append(evt) |
| 99 | res = ctypes.windll.ws2_32.WSAEventSelect( |
| 100 | ctypes.c_void_p(i.fileno()), |
| 101 | evt, |
| 102 | FD_READ |
| 103 | ) |
| 104 | if res == 0: |
| 105 | # Was a socket |
| 106 | events.append(evt) |
| 107 | else: |
| 108 | # Fallback to normal event |
| 109 | events.append(i.fileno()) |
| 110 | elif i.fileno() < 0: |
| 111 | # Special case: On Windows, we consider that an object that returns |
| 112 | # a negative fileno (impossible), is always readable. This is used |
| 113 | # in very few places but important (e.g. PcapReader), where we have |
| 114 | # no valid fileno (and will stop on EOFError). |
| 115 | results.add(i) |
| 116 | remain = 0 |
| 117 | else: |
| 118 | events.append(i.fileno()) |
| 119 | if events: |
| 120 | # 0xFFFFFFFF = INFINITE |
| 121 | remainms = int(remain * 1000 if remain is not None else 0xFFFFFFFF) |