Skip to content

Commit

Permalink
simplify virtual timer and improve compatibility
Browse files Browse the repository at this point in the history
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 <csaba.kiraly@gmail.com>
  • Loading branch information
cskiraly committed Jul 11, 2023
1 parent 5b9ec08 commit f6e221b
Showing 1 changed file with 31 additions and 11 deletions.
42 changes: 31 additions & 11 deletions chronos/asyncloop.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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 on 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}
Expand All @@ -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..<count:
let fd = loop.keys[i].fd
let events = loop.keys[i].events
Expand Down Expand Up @@ -827,10 +851,6 @@ elif unixPlatform:
# All callbacks done, skip `processCallbacks` at start.
loop.callbacks.addFirst(SentinelCallback)

# Advance virtual time in simulation if nothing expected in curTimeout millisec
when asyncTimer == "virtual":
Moment.advance(curTimeout.milliseconds)

else:
proc initAPI() = discard
proc globalInit() = discard
Expand Down

0 comments on commit f6e221b

Please sign in to comment.