@@ -204,8 +204,8 @@ def start_clock(self) -> None:
204204 def current_time (self ) -> float :
205205 return self .offset + perf_counter ()
206206
207- def deadline_to_sleep_time (self , deadline : float ) -> float :
208- return deadline - self . current_time ()
207+ def deadline_to_sleep_time (self , timeout : float ) -> float :
208+ return timeout
209209
210210
211211class IdlePrimedTypes (enum .Enum ):
@@ -2739,36 +2739,38 @@ def unrolled_run(
27392739 # You know how people talk about "event loops"? This 'while' loop right
27402740 # here is our event loop:
27412741 while runner .tasks :
2742+ now = runner .clock .current_time ()
2743+
27422744 if runner .runq :
2743- timeout : float = 0
2745+ virtual_timeout : float = 0
27442746 else :
27452747 deadline = runner .deadlines .next_deadline ()
2746- timeout = runner .clock .deadline_to_sleep_time (deadline )
2747- timeout = min (max (0 , timeout ), _MAX_TIMEOUT )
2748+ virtual_timeout = max (0 , deadline - now )
27482749
27492750 idle_primed = None
27502751 if runner .waiting_for_idle :
27512752 cushion , _ = runner .waiting_for_idle .keys ()[0 ]
2752- if cushion < timeout :
2753- timeout = cushion
2753+ if cushion < virtual_timeout :
2754+ virtual_timeout = cushion
27542755 idle_primed = IdlePrimedTypes .WAITING_FOR_IDLE
2755- # We use 'elif' here because if there are tasks in
2756- # wait_all_tasks_blocked, then those tasks will wake up without
2757- # jumping the clock, so we don't need to autojump.
2758- elif runner .clock .autojump_threshold < timeout :
2759- timeout = runner .clock .autojump_threshold
2760- idle_primed = IdlePrimedTypes .AUTOJUMP_CLOCK
2756+
2757+ virtual_timeout = min (max (0 , virtual_timeout ), _MAX_TIMEOUT )
2758+ real_timeout = runner .clock .deadline_to_sleep_time (virtual_timeout )
27612759
27622760 if "before_io_wait" in runner .instruments :
2763- runner .instruments .call ("before_io_wait" , timeout )
2761+ runner .instruments .call ("before_io_wait" , real_timeout )
27642762
27652763 # Driver will call io_manager.get_events(timeout) and pass it back
27662764 # in through the yield
2767- events = yield timeout
2765+ events = yield real_timeout
2766+
2767+ new_now = runner .clock .current_time ()
2768+ runner .clock .propagate (new_now - now , virtual_timeout )
2769+
27682770 runner .io_manager .process_events (events )
27692771
27702772 if "after_io_wait" in runner .instruments :
2771- runner .instruments .call ("after_io_wait" , timeout )
2773+ runner .instruments .call ("after_io_wait" , real_timeout )
27722774
27732775 # Process cancellations due to deadline expiry
27742776 now = runner .clock .current_time ()
@@ -2805,9 +2807,6 @@ def unrolled_run(
28052807 runner .reschedule (task )
28062808 else :
28072809 break
2808- else :
2809- assert idle_primed is IdlePrimedTypes .AUTOJUMP_CLOCK
2810- runner .clock .autojump ()
28112810
28122811 # Process all runnable tasks, but only the ones that are already
28132812 # runnable now. Anything that becomes runnable during this cycle
0 commit comments