From bb3057ffed5753f1fb9a44206f07b86013485e27 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 8 Apr 2017 01:34:57 +0300 Subject: [PATCH] uasyncio.core: Fix scheduling in the presense of I/O completion callbacks. wait() may finish prematurely due to I/O completion, and schedule new, earlier than before tasks to run. So, after call to wait(), we need to check current time and time of head task, and continue to wait if needed. Recently introduced provisional utimeq.peektime() is used to optimize querying time of a head task. --- uasyncio.core/uasyncio/core.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/uasyncio.core/uasyncio/core.py b/uasyncio.core/uasyncio/core.py index 02d6da95..580f8c8a 100644 --- a/uasyncio.core/uasyncio/core.py +++ b/uasyncio.core/uasyncio/core.py @@ -55,6 +55,16 @@ class EventLoop: cur_task = [0, 0, 0] while True: if self.q: + # wait() may finish prematurely due to I/O completion, + # and schedule new, earlier than before tasks to run. + while 1: + t = self.q.peektime() + tnow = self.time() + delay = time.ticks_diff(t, tnow) + if delay <= 0: + break + self.wait(delay) + self.q.pop(cur_task) t = cur_task[0] cb = cur_task[1] @@ -62,10 +72,6 @@ class EventLoop: if __debug__ and DEBUG: log.debug("Next coroutine to run: %s", (t, cb, args)) # __main__.mem_info() - tnow = self.time() - delay = time.ticks_diff(t, tnow) - if delay > 0: - self.wait(delay) else: self.wait(-1) # Assuming IO completion scheduled some tasks