github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/lib/select_.py (about) 1 # Copyright 2016 Google Inc. All Rights Reserved. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 from '__go__/syscall' import ( 16 FD_SETSIZE as _FD_SETSIZE, 17 Select as _Select, 18 FdSet as _FdSet, 19 Timeval as _Timeval 20 ) 21 import _syscall 22 import math 23 24 25 class error(Exception): 26 pass 27 28 29 def select(rlist, wlist, xlist, timeout=None): 30 rlist_norm = _normalize_fd_list(rlist) 31 wlist_norm = _normalize_fd_list(wlist) 32 xlist_norm = _normalize_fd_list(xlist) 33 all_fds = rlist_norm + wlist_norm + xlist_norm 34 if not all_fds: 35 nfd = 0 36 else: 37 nfd = max(all_fds) + 1 38 39 rfds = _make_fdset(rlist_norm) 40 wfds = _make_fdset(wlist_norm) 41 xfds = _make_fdset(xlist_norm) 42 43 if timeout is None: 44 timeval = None 45 else: 46 timeval = _Timeval.new() 47 frac, integer = math.modf(timeout) 48 timeval.Sec = int(integer) 49 timeval.Usec = int(frac * 1000000.0) 50 _syscall.invoke(_Select, nfd, rfds, wfds, xfds, timeval) 51 return ([rlist[i] for i, fd in enumerate(rlist_norm) if _fdset_isset(fd, rfds)], 52 [wlist[i] for i, fd in enumerate(wlist_norm) if _fdset_isset(fd, wfds)], 53 [xlist[i] for i, fd in enumerate(xlist_norm) if _fdset_isset(fd, xfds)]) 54 55 56 def _fdset_set(fd, fds): 57 idx = fd / (_FD_SETSIZE / len(fds.Bits)) % len(fds.Bits) 58 pos = fd % (_FD_SETSIZE / len(fds.Bits)) 59 fds.Bits[idx] |= 1 << pos 60 61 62 def _fdset_isset(fd, fds): 63 idx = fd / (_FD_SETSIZE / len(fds.Bits)) % len(fds.Bits) 64 pos = fd % (_FD_SETSIZE / len(fds.Bits)) 65 return bool(fds.Bits[idx] & (1 << pos)) 66 67 68 def _make_fdset(fd_list): 69 fds = _FdSet.new() 70 for fd in fd_list: 71 _fdset_set(fd, fds) 72 return fds 73 74 75 def _normalize_fd_list(fds): 76 result = [] 77 # Python permits mutating the select fds list during fileno calls so we can't 78 # just use simple iteration over the list. See test_select_mutated in 79 # test_select.py 80 i = 0 81 while i < len(fds): 82 fd = fds[i] 83 if hasattr(fd, 'fileno'): 84 fd = fd.fileno() 85 result.append(fd) 86 i += 1 87 return result