1-- Time: a monotonic clock and sleeping on it, and a wall clock, two
2-- concepts beside core/io's and outside `world`, so a provider without
3-- a clock, and a firmware image that never asks for the time, carries
4-- none of them. Time is counted in nanoseconds in a `u64`: no floating
5-- point, the same arithmetic on every target, and room for 584 years.
6
7duration_value: type = distinct u64
8instant_value: type = distinct u64
9
10--- A span of time, a whole number of nanoseconds from zero to 2^64 - 1,
11--- about 584 years. `u64(span)` is the count and `io.duration(n)` makes
12--- one, as `nanoseconds` does; `milliseconds` and the others make one from
13--- a coarser count and trap when it would not fit. Two spans compare with
14--- `==`, `<>`, `<`, `<=`, `>` and `>=`, as their counts do; the type has
15--- no arithmetic of its own, so an instant is never added to an instant.
16public duration: type = duration_value
17
18--- A reading of a monotonic clock: nanoseconds since a start the provider
19--- fixes, which is the system's boot on Linux. Only the difference
20--- between two readings of one provider means anything, `elapsed`; the
21--- count is `u64(at)`. Two instants compare with `==`, `<>`, `<`, `<=`,
22--- `>` and `>=`, as their counts do.
23public instant: type = instant_value
24
25--- A reading of the wall clock: UTC seconds since 1970-01-01T00:00:00,
26--- negative before it, and the nanoseconds after them, from 0 to
27--- 999,999,999. Leap seconds are not counted, as POSIX counts none.
28--- Calendars, time zones and formatting a date are not this library's.
29public wall_time: type = struct
30 seconds: i64
31 nanoseconds: u32
32end wall_time
33
34--- A monotonic clock and sleeping on it. `now` never goes back: a later
35--- reading of one provider is never less than an earlier one, whatever
36--- the wall clock does. `sleep` returns once at least `span` has passed
37--- on this clock, measured from when it was called; it may return later,
38--- as late as the system schedules it, and never sooner.
39public clock: type = concept (provider: type)
40 --- The clock's reading now.
41 now: (self: provider) -> (at: instant)
42 --- Wait until at least `span` has passed on this clock.
43 sleep: (self: provider, span: duration) -> none
44end clock
45
46--- The wall clock: what time it is in UTC, as the system keeps it. It is
47--- a concept of its own because a firmware image may count time without
48--- knowing the date, and because the system may set this clock, so two
49--- readings may go back; time a task with `clock`, never with this.
50public wall_clock: type = concept (provider: type)
51 --- The wall clock's reading now.
52 wall_now: (self: provider) -> (at: wall_time)
53end wall_clock
54
55--- The reading of a monotonic clock now, through `clock` evidence.
56public now: (provider: type is clock, host: provider) -> (at: instant) =
57 at = provider.now(host)
58end now
59
60--- Wait until at least `span` has passed on the provider's monotonic
61--- clock. A sleep a signal interrupts on a hosted system sleeps on for
62--- what is left; a sleep of zero returns at once.
63public sleep: (provider: type is clock, host: provider, span: duration)
64 -> none =
65 provider.sleep(host, span)
66end sleep
67
68--- The wall clock's reading now, through `wall_clock` evidence.
69public wall_now: (provider: type is wall_clock, host: provider)
70 -> (at: wall_time) =
71 at = provider.wall_now(host)
72end wall_now
73
74--- A span of `count` nanoseconds.
75public nanoseconds: (count: u64) -> (span: duration) =
76 span = duration_value(count)
77end nanoseconds
78
79--- A span of `count` microseconds; it traps beyond 584 years.
80public microseconds: (count: u64) -> (span: duration) =
81 span = duration_value(count * 1000)
82end microseconds
83
84--- A span of `count` milliseconds; it traps beyond 584 years.
85public milliseconds: (count: u64) -> (span: duration) =
86 span = duration_value(count * 1000000)
87end milliseconds
88
89--- A span of `count` seconds; it traps beyond 584 years.
90public seconds: (count: u64) -> (span: duration) =
91 span = duration_value(count * 1000000000)
92end seconds
93
94--- The span from `earlier` to `later`, two readings of one clock taken in
95--- that order. It traps when `later` is the earlier of the two, which
96--- two readings of one monotonic clock taken in order never are.
97public elapsed: (earlier: instant, later: instant) -> (span: duration) =
98 span = duration_value(u64(later) - u64(earlier))
99end elapsed
100
101--- The instant `span` after `at`, a deadline; it traps past the clock's
102--- last instant, 584 years after its start.
103public later: (at: instant, span: duration) -> (result: instant) =
104 result = instant_value(u64(at) + u64(span))
105end later
106
107--- The whole milliseconds in `span`, rounded down.
108public in_milliseconds: (span: duration) -> (count: u64) =
109 count = u64(span) / 1000000
110end in_milliseconds