def _poll(self): if self._current_iocp: if not self._tasks or self._queue: if self._timers: ms = max(10, (self._timers[0][0] - self.time()) * 1000) else: ms = 10 # Need a 100ms minimum timeout probably, this can be changed else: ms = 10 while True: status = _overlapped.GetQueuedCompletionStatus( self._port, ms) # See if anything is ready (LIFO) if status is None: # While we have things to process, keep going break ms = 0 err, transferred, key, address = status try: future = self._current_iocp.pop(address) future.set_result(transferred) except KeyError: if key not in (0, _overlapped.INVALID_HANDLE_VALUE): CloseHandle( key ) # If we get a handle that doesn't exist or got deleted: Close it continue else: if self._timers: self.sleep(max(0, self._timers[0][0] - self.time()))
def _poll(self, timeout=None): if timeout is None: ms = INFINITE elif timeout < 0: raise ValueError("negative timeout") else: # GetQueuedCompletionStatus() has a resolution of 1 millisecond, # round away from zero to wait *at least* timeout seconds. ms = math.ceil(timeout * 1e3) if ms >= INFINITE: raise ValueError("timeout too big") while True: status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) if status is None: break ms = 0 err, transferred, key, address = status try: f, ov, obj, callback = self._cache.pop(address) except KeyError: if self._loop.get_debug(): self._loop.call_exception_handler({ 'message': ('GetQueuedCompletionStatus() returned an ' 'unexpected event'), 'status': ('err=%s transferred=%s key=%#x address=%#x' % (err, transferred, key, address)), }) # key is either zero, or it is used to return a pipe # handle which should be closed to avoid a leak. if key not in (0, _overlapped.INVALID_HANDLE_VALUE): _winapi.CloseHandle(key) continue if obj in self._stopped_serving: f.cancel() # Don't call the callback if _register() already read the result or # if the overlapped has been cancelled elif not f.done(): try: value = callback(transferred, key, ov) except OSError as e: f.set_exception(e) self._results.append(f) else: f.set_result(value) self._results.append(f) # Remove unregistered futures for ov in self._unregistered: self._cache.pop(ov.address, None) self._unregistered.clear()
def _poll(self, timeout=None): """Override in order to handle events in a threadsafe manner.""" if timeout is None: ms = UINT32_MAX # wait for eternity elif timeout < 0: raise ValueError("negative timeout") else: # GetQueuedCompletionStatus() has a resolution of 1 millisecond, # round away from zero to wait *at least* timeout seconds. ms = math.ceil(timeout * 1e3) if ms >= UINT32_MAX: raise ValueError("timeout too big") with QtCore.QMutexLocker(self._lock): while True: # self._logger.debug('Polling IOCP with timeout {} ms in thread {}...'.format( # ms, threading.get_ident())) status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) if status is None: break err, transferred, key, address = status try: f, ov, obj, callback = self._cache.pop(address) except KeyError: # key is either zero, or it is used to return a pipe # handle which should be closed to avoid a leak. if key not in (0, _overlapped.INVALID_HANDLE_VALUE): _winapi.CloseHandle(key) ms = 0 continue if obj in self._stopped_serving: f.cancel() # Futures might already be resolved or cancelled elif not f.done(): self.__events.append((f, callback, transferred, key, ov)) ms = 0