Landin library reference discuss source

hosted/blocking/time.ldn

1--  The blocking provider's `time.clock`: the monotonic clock, and sleeping
2--  on it, which blocks the thread.  Written once over platform/posix; the
3--  wall clock is the system's, in delegated.ldn.
4
5import core/time
6import platform/posix
7
8--  A second in nanoseconds.
9second: u64 = 1000000000
10
11--  The longest one request to sleep asks for, about eleven days.
12longest: u64 = 1000000 * second
13
14--  The clock `clock` read now.  Every hosted system has both clocks, and
15--  reading one fails only when the process is given a bad address, which
16--  no call here gives, so a failure ends the program.
17read: (clock: posix.clock_kind) -> (sample: posix.time_value) =
18    sample = posix.clock_time(clock) else (problem)
19        _ = problem
20        compiler.unreachable()
21    end
22end read
23
24--  The monotonic clock in nanoseconds since the system started, which no
25--  hosted system counts as negative.
26reading: () -> (at: u64) =
27    sample: posix.time_value = read(posix.monotonic_clock)
28    at = u64(sample.seconds) * second + u64(sample.nanoseconds)
29end reading
30
31blocking_now: (self: host) -> (at: time.instant) =
32    _ = self.services
33    at = time.instant(reading())
34end blocking_now
35
36--  The sleep is measured on the clock `now` reads, whatever clock the
37--  system sleeps on: the deadline is taken first, and the system is asked
38--  again for what is left until the clock has reached it, so a sleep a
39--  signal interrupts, or the system ends early, sleeps on for the rest.
40--  A deadline past the clock's last instant is that instant.  A system
41--  that refused every sleep would leave this loop reading the clock until
42--  the deadline, which is still never early; none of them does.
43blocking_sleep: (self: host, span: time.duration) -> none =
44    _ = self.services
45    start: u64 = reading()
46    room: u64 = (0 -% 1) - start
47    deadline: u64 = if u64(span) > room then 0 -% 1
48                    else start + u64(span) end if
49    loop do
50        now: u64 = reading()
51        return when now >= deadline
52        --  No more than a million seconds at once, within what every
53        --  system's sleep takes; the loop sleeps again for the rest.
54        mut left: u64 = deadline - now
55        if left > longest then left = longest end if
56        whole: u64 = left / second
57        posix.sleep((seconds: i64(whole),
58                     nanoseconds: u32(left - whole * second))) else (problem)
59            --  Interrupted, or refused: the clock says what is left.
60            _ = problem
61        end
62    end loop
63end blocking_sleep
64
65host is time.clock (now: blocking_now, sleep: blocking_sleep)