Skip to content

Commit f6e221b

Browse files
committed
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 <[email protected]>
1 parent 5b9ec08 commit f6e221b

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

chronos/asyncloop.nim

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,36 @@ elif unixPlatform:
769769
var curTime = Moment.now()
770770
var curTimeout = 0
771771

772+
when asyncTimer == "virtual":
773+
# Execute all queued callbacks and at most one timer event at a time.
774+
# This is the closest to the one network event at a time semantics we have in other modalities.
775+
# Enforcing one timer each poll is useful to make it compatible with original semantics when
776+
# network events are replaced by timers for simulation.
777+
778+
# Execute queued callbacks on order.
779+
while loop.callbacks.len > 0:
780+
let cb = loop.callbacks.popFirst()
781+
if not isSentinel(cb):
782+
cb.function(cb.udata)
783+
784+
# Fill callbacks as needed, consuming at most one timer.
785+
if loop.timers.len > 0:
786+
let
787+
timer = loop.timers.pop()
788+
finish = timer.finishAt
789+
callable = timer.function
790+
791+
if not(isNil(callable.function)):
792+
loop.callbacks.addFirst(callable)
793+
794+
# Advance virtual time in simulation until next timer.
795+
Moment.advance(finish - Moment.now())
796+
797+
# Handle idlers here, closest we can get to original definition.
798+
else:
799+
loop.processIdlers()
800+
return
801+
772802
when ioselSupportedPlatform:
773803
let customSet = {Event.Timer, Event.Signal, Event.Process,
774804
Event.Vnode}
@@ -781,14 +811,8 @@ elif unixPlatform:
781811
# Moving expired timers to `loop.callbacks` and calculate timeout.
782812
loop.processTimersGetTimeout(curTimeout)
783813

784-
let timeout =
785-
when asyncTimer == "virtual":
786-
0
787-
else:
788-
curTimeout
789-
790814
# Processing IO descriptors and all hardware events.
791-
let count = loop.selector.selectInto(timeout, loop.keys)
815+
let count = loop.selector.selectInto(curTimeout, loop.keys)
792816
for i in 0..<count:
793817
let fd = loop.keys[i].fd
794818
let events = loop.keys[i].events
@@ -827,10 +851,6 @@ elif unixPlatform:
827851
# All callbacks done, skip `processCallbacks` at start.
828852
loop.callbacks.addFirst(SentinelCallback)
829853

830-
# Advance virtual time in simulation if nothing expected in curTimeout millisec
831-
when asyncTimer == "virtual":
832-
Moment.advance(curTimeout.milliseconds)
833-
834854
else:
835855
proc initAPI() = discard
836856
proc globalInit() = discard

0 commit comments

Comments
 (0)