From 8580b50ae1dbaa5c61c7d51d66d1c15696c058a8 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Tue, 11 Jul 2023 11:09:27 +0200 Subject: [PATCH] simplify virtual timer and improve compatibility Previous version of virtual timer used minimal modifications. This one instead implements poll() directly, simplifying execution. It also enforces one timer each poll, which makes it compatible with one network even per poll cycle when network events are replaced by timers for simulation. Signed-off-by: Csaba Kiraly --- chronos/asyncloop.nim | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/chronos/asyncloop.nim b/chronos/asyncloop.nim index 56d901a23..6df9cc6d3 100644 --- a/chronos/asyncloop.nim +++ b/chronos/asyncloop.nim @@ -769,6 +769,36 @@ elif unixPlatform: var curTime = Moment.now() var curTimeout = 0 + when asyncTimer == "virtual": + # Execute all queued callbacks and at most one timer event at a time. + # This is the closest to the one network event at a time semantics we have in other modalities. + # Enforcing one timer each poll is useful to make it compatible with original semantics when + # network events are replaced by timers for simulation. + + # Execute queued callbacks in order. + while loop.callbacks.len > 0: + let cb = loop.callbacks.popFirst() + if not isSentinel(cb): + cb.function(cb.udata) + + # Fill callbacks as needed, consuming at most one timer. + if loop.timers.len > 0: + let + timer = loop.timers.pop() + finish = timer.finishAt + callable = timer.function + + if not(isNil(callable.function)): + loop.callbacks.addFirst(callable) + + # Advance virtual time in simulation until next timer. + Moment.advance(finish - Moment.now()) + + # Handle idlers here, closest we can get to original definition. + else: + loop.processIdlers() + return + when ioselSupportedPlatform: let customSet = {Event.Timer, Event.Signal, Event.Process, Event.Vnode} @@ -781,14 +811,8 @@ elif unixPlatform: # Moving expired timers to `loop.callbacks` and calculate timeout. loop.processTimersGetTimeout(curTimeout) - let timeout = - when asyncTimer == "virtual": - 0 - else: - curTimeout - # Processing IO descriptors and all hardware events. - let count = loop.selector.selectInto(timeout, loop.keys) + let count = loop.selector.selectInto(curTimeout, loop.keys) for i in 0..