@@ -20,6 +20,32 @@ enum InstantKind {
2020 Virtual { nanoseconds : u64 } ,
2121}
2222
23+ impl Instant {
24+ pub fn checked_add ( & self , duration : Duration ) -> Option < Instant > {
25+ match self . kind {
26+ InstantKind :: Host ( instant) =>
27+ instant. checked_add ( duration) . map ( |i| Instant { kind : InstantKind :: Host ( i) } ) ,
28+ InstantKind :: Virtual { nanoseconds } =>
29+ u128:: from ( nanoseconds)
30+ . checked_add ( duration. as_nanos ( ) )
31+ . and_then ( |n| u64:: try_from ( n) . ok ( ) )
32+ . map ( |nanoseconds| Instant { kind : InstantKind :: Virtual { nanoseconds } } ) ,
33+ }
34+ }
35+
36+ pub fn duration_since ( & self , earlier : Instant ) -> Duration {
37+ match ( & self . kind , earlier. kind ) {
38+ ( InstantKind :: Host ( instant) , InstantKind :: Host ( earlier) ) =>
39+ instant. duration_since ( earlier) ,
40+ (
41+ InstantKind :: Virtual { nanoseconds } ,
42+ InstantKind :: Virtual { nanoseconds : earlier } ,
43+ ) => Duration :: from_nanos ( nanoseconds. saturating_sub ( earlier) ) ,
44+ _ => panic ! ( "all `Instant` must be of the same kind" ) ,
45+ }
46+ }
47+ }
48+
2349/// A monotone clock used for `Instant` simulation.
2450#[ derive( Debug ) ]
2551pub struct Clock {
@@ -50,24 +76,14 @@ impl Clock {
5076 Self { kind }
5177 }
5278
53- /// Get the current time relative to this clock.
54- pub fn get ( & self ) -> Duration {
55- match & self . kind {
56- ClockKind :: Host { time_anchor } =>
57- StdInstant :: now ( ) . saturating_duration_since ( * time_anchor) ,
58- ClockKind :: Virtual { nanoseconds } =>
59- Duration :: from_nanos ( nanoseconds. load ( Ordering :: Relaxed ) ) ,
60- }
61- }
62-
6379 /// Let the time pass for a small interval.
6480 pub fn tick ( & self ) {
6581 match & self . kind {
6682 ClockKind :: Host { .. } => {
6783 // Time will pass without us doing anything.
6884 }
6985 ClockKind :: Virtual { nanoseconds } => {
70- nanoseconds. fetch_add ( NANOSECOND_PER_BASIC_BLOCK , Ordering :: Relaxed ) ;
86+ nanoseconds. fetch_add ( NANOSECOND_PER_BASIC_BLOCK , Ordering :: SeqCst ) ;
7187 }
7288 }
7389 }
@@ -78,54 +94,26 @@ impl Clock {
7894 ClockKind :: Host { .. } => std:: thread:: sleep ( duration) ,
7995 ClockKind :: Virtual { nanoseconds } => {
8096 // Just pretend that we have slept for some time.
81- nanoseconds. fetch_add ( duration. as_nanos ( ) . try_into ( ) . unwrap ( ) , Ordering :: Relaxed ) ;
97+ nanoseconds. fetch_add ( duration. as_nanos ( ) . try_into ( ) . unwrap ( ) , Ordering :: SeqCst ) ;
8298 }
8399 }
84100 }
85101
86- /// Compute `now + duration` relative to this clock .
87- pub fn get_time_relative ( & self , duration : Duration ) -> Option < Instant > {
102+ /// Return the `anchor` instant, to convert between monotone instants and durations relative to the anchor .
103+ pub fn anchor ( & self ) -> Instant {
88104 match & self . kind {
89- ClockKind :: Host { .. } =>
90- StdInstant :: now ( )
91- . checked_add ( duration)
92- . map ( |instant| Instant { kind : InstantKind :: Host ( instant) } ) ,
93- ClockKind :: Virtual { nanoseconds } =>
94- nanoseconds
95- . load ( Ordering :: Relaxed )
96- . checked_add ( duration. as_nanos ( ) . try_into ( ) . unwrap ( ) )
97- . map ( |nanoseconds| Instant { kind : InstantKind :: Virtual { nanoseconds } } ) ,
105+ ClockKind :: Host { time_anchor } => Instant { kind : InstantKind :: Host ( * time_anchor) } ,
106+ ClockKind :: Virtual { .. } => Instant { kind : InstantKind :: Virtual { nanoseconds : 0 } } ,
98107 }
99108 }
100109
101- /// Compute `start + duration` relative to this clock where `start` is the instant of time when
102- /// this clock was created.
103- pub fn get_time_absolute ( & self , duration : Duration ) -> Option < Instant > {
110+ pub fn now ( & self ) -> Instant {
104111 match & self . kind {
105- ClockKind :: Host { time_anchor } =>
106- time_anchor
107- . checked_add ( duration)
108- . map ( |instant| Instant { kind : InstantKind :: Host ( instant) } ) ,
109- ClockKind :: Virtual { .. } =>
110- Some ( Instant {
111- kind : InstantKind :: Virtual {
112- nanoseconds : duration. as_nanos ( ) . try_into ( ) . unwrap ( ) ,
113- } ,
114- } ) ,
115- }
116- }
117-
118- /// Returns the duration until the given instant.
119- pub fn duration_until ( & self , instant : & Instant ) -> Duration {
120- match ( & instant. kind , & self . kind ) {
121- ( InstantKind :: Host ( instant) , ClockKind :: Host { .. } ) =>
122- instant. saturating_duration_since ( StdInstant :: now ( ) ) ,
123- (
124- InstantKind :: Virtual { nanoseconds } ,
125- ClockKind :: Virtual { nanoseconds : current_ns } ,
126- ) =>
127- Duration :: from_nanos ( nanoseconds. saturating_sub ( current_ns. load ( Ordering :: Relaxed ) ) ) ,
128- _ => panic ! ( ) ,
112+ ClockKind :: Host { .. } => Instant { kind : InstantKind :: Host ( StdInstant :: now ( ) ) } ,
113+ ClockKind :: Virtual { nanoseconds } =>
114+ Instant {
115+ kind : InstantKind :: Virtual { nanoseconds : nanoseconds. load ( Ordering :: SeqCst ) } ,
116+ } ,
129117 }
130118 }
131119}
0 commit comments