1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! Monotonic time source seam for cycle telemetry (`REQ_0101`, `REQ_0105`,
//! `REQ_0106`).
//!
//! `std::time::Instant` is **opaque** — it cannot be constructed from a
//! duration — so it is impossible to feed scripted instants to the telemetry
//! math in a test. The timing path that produces `took` / jitter / lateness
//! therefore reads time through this `u64`-nanosecond abstraction instead of
//! calling [`Instant::now`](std::time::Instant::now) directly.
//!
//! * Production wires in [`SystemClock`] (a thin wrapper over a monotonic
//! [`Instant`](std::time::Instant) epoch), so behaviour is unchanged.
//! * Tests wire in [`MockClock`] via [`ExecutorBuilder::clock`] and advance it
//! by hand — typically from inside a task body — so jitter, lateness and
//! min/max can be asserted to the *exact* nanosecond with no real sleeps and
//! no dependence on the CI scheduler.
//!
//! Only the telemetry path uses this clock. Scheduling (the iceoryx2 `WaitSet`
//! interval triggers), run-mode deadlines, fault `since_ms`, and the
//! [`ExecutionMonitor`](crate::ExecutionMonitor) callbacks continue to use the
//! real [`Instant`](std::time::Instant) clock, so a mock clock can never alter
//! dispatch or fault behaviour.
//!
//! [`ExecutorBuilder::clock`]: crate::ExecutorBuilder::clock
use Arc;
use ;
use Instant;
/// A monotonic nanosecond time source for cycle telemetry.
///
/// Implementations return nanoseconds elapsed since an arbitrary fixed epoch.
/// The value must be monotonic non-decreasing within one clock instance; the
/// epoch itself is unspecified (telemetry only ever takes differences).
/// Production clock: monotonic nanoseconds since the clock was constructed
/// (typically executor `build()` time).
/// Test clock: a manually-advanced nanosecond counter.
///
/// `MockClock` is a cloneable handle over a shared counter — clone it, hand one
/// clone to [`ExecutorBuilder::clock`](crate::ExecutorBuilder::clock) and keep
/// the other to drive time from the test (or from inside a task body). Both
/// clones observe the same counter.
///
/// Advancing the clock from inside a cyclic task body is the idiomatic pattern:
/// the body "spends" a precise number of nanoseconds, which the telemetry fold
/// then reads back as the cycle's `took` (and, across cycles, as the measured
/// period feeding jitter and lateness).