Skip to content

Commit 5b9ec08

Browse files
committed
introduce the virtual clock for simulations
This allows running code written for Chronos using `-d:asyncTimer=virtual` , turning it into a simple event-based simulation. Signed-off-by: Csaba Kiraly <[email protected]>
1 parent 6525f4c commit 5b9ec08

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

chronos/asyncloop.nim

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,14 @@ elif unixPlatform:
781781
# Moving expired timers to `loop.callbacks` and calculate timeout.
782782
loop.processTimersGetTimeout(curTimeout)
783783
784+
let timeout =
785+
when asyncTimer == "virtual":
786+
0
787+
else:
788+
curTimeout
789+
784790
# Processing IO descriptors and all hardware events.
785-
let count = loop.selector.selectInto(curTimeout, loop.keys)
791+
let count = loop.selector.selectInto(timeout, loop.keys)
786792
for i in 0..<count:
787793
let fd = loop.keys[i].fd
788794
let events = loop.keys[i].events
@@ -821,6 +827,10 @@ elif unixPlatform:
821827
# All callbacks done, skip `processCallbacks` at start.
822828
loop.callbacks.addFirst(SentinelCallback)
823829
830+
# Advance virtual time in simulation if nothing expected in curTimeout millisec
831+
when asyncTimer == "virtual":
832+
Moment.advance(curTimeout.milliseconds)
833+
824834
else:
825835
proc initAPI() = discard
826836
proc globalInit() = discard

chronos/timer.nim

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@
1111
## This module implements cross-platform system timer with
1212
## milliseconds resolution.
1313
##
14-
## Timer supports two types of clocks:
14+
## Timer supports three types of clocks:
1515
## ``system`` uses the most fast OS primitive to obtain wall clock time.
1616
## ``mono`` uses monotonic clock time (default).
17+
## ``virtual`` is for event-based simulations only.
1718
##
1819
## ``system`` clock is affected by discontinuous jumps in the system time. This
1920
## clock is significantly faster then ``mono`` clock in most of the cases.
2021
##
2122
## ``mono`` clock is not affected by discontinuous jumps in the system time.
2223
## This clock is slower then ``system`` clock.
2324
##
24-
## You can specify which timer you want to use ``-d:asyncTimer=<system/mono>``.
25+
## ``virtual`` clock is not related to wall clock or system time. It simply
26+
## jumps through the event queue in time order, counting execution time.
27+
##
28+
## You can specify which timer you want to use ``-d:asyncTimer=<system/mono/virtual>``.
2529
import stew/base10
2630

2731
const asyncTimer* {.strdefine.} = "mono"
@@ -31,7 +35,18 @@ when (NimMajor, NimMinor) < (1, 4):
3135
else:
3236
{.push raises: [].}
3337

34-
when defined(windows):
38+
when asyncTimer == "virtual":
39+
var curTime: uint64 = 0
40+
proc fastEpochTime*(): uint64 {.
41+
inline, deprecated: "Use Moment.now()".} =
42+
## Procedure's resolution is millisecond.
43+
curTime div 1_000_000
44+
45+
proc fastEpochTimeNano(): uint64 {.inline.} =
46+
## Procedure's resolution is nanosecond.
47+
curTime
48+
49+
elif defined(windows):
3550
when asyncTimer == "system":
3651
from winlean import getSystemTimeAsFileTime, FILETIME
3752

@@ -503,3 +518,8 @@ when defined(posix):
503518
tv_sec: Time(a.value div Second.value),
504519
tv_nsec: int(a.value mod Second.value)
505520
)
521+
522+
when asyncTimer == "virtual":
523+
proc advance*(t: typedesc[Moment], a: Duration) =
524+
## # Advance virtual time by given duration
525+
curTime += a.nanoseconds.uint64

0 commit comments

Comments
 (0)