From 4b3316a19ef4886d2f83b65a3ca1784b7715c3a0 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 22 Feb 2018 13:35:31 -0500 Subject: [PATCH] Expose fine-grained time remaining Fixes #6 --- src/lib.rs | 63 ++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 90f53d9..54fa891 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,45 +150,36 @@ impl TimerHeap { self.active.remove(&key).is_some() } - /// Return the amount of time remaining (in ms) for the earliest expiring timer - /// Return `None` if there are no timers in the heap - pub fn time_remaining(&self) -> Option { + /// Return the amount of time remaining for the earliest expiring timer. + /// Return `None` if there are no timers in the heap. + pub fn time_remaining(&self) -> Option { self._time_remaining(Instant::now()) } /// A deterministically testable version of `time_remaining()` - fn _time_remaining(&self, now: Instant) -> Option { - self.timers.iter().find(|e| { - self.active.get(&e.key) == Some(&e.counter) - }).map(|e| { - if now > e.expires_at { - return 0; - } - let duration = e.expires_at - now; - // We add a millisecond if there is a fractional ms milliseconds in - // duration.subsec_nanos() / 1000000 so that we never fire early. - let nanos = duration.subsec_nanos() as u64; - // TODO: This can almost certainly be done faster - let subsec_ms = nanos / 1000000; - let mut remaining = duration.as_secs()*1000 + subsec_ms; - if subsec_ms * 1000000 < nanos { - remaining += 1; - } - remaining - }) + fn _time_remaining(&self, now: Instant) -> Option { + self.timers + .iter() + .find(|e| self.active.get(&e.key) == Some(&e.counter)) + .map(|e| { + if now > e.expires_at { + return Duration::new(0, 0); + } + e.expires_at - now + }) } /// Return the earliest timeout based on a user timeout and the least remaining time in the /// next timer to fire. - pub fn earliest_timeout(&self, user_timeout_ms: usize) -> usize { + pub fn earliest_timeout(&self, user_timeout: Duration) -> Duration { if let Some(remaining) = self.time_remaining() { - if user_timeout_ms < remaining as usize { - user_timeout_ms + if user_timeout < remaining { + user_timeout } else { - remaining as usize + remaining } } else { - user_timeout_ms + user_timeout } } @@ -272,14 +263,20 @@ mod tests { let mut heap = TimerHeap::new(); let now = Instant::now(); let duration = Duration::from_millis(500); - heap._insert(1u64, duration, TimerType::Oneshot, now).unwrap(); - assert_matches!(heap._time_remaining(now), Some(500)); - assert_matches!(heap._time_remaining(now + duration), Some(0)); - assert_matches!(heap._time_remaining(now + duration + Duration::from_millis(100)), - Some(0)); + heap._insert(1u64, duration, TimerType::Oneshot, now) + .unwrap(); + assert_eq!(heap._time_remaining(now), Some(Duration::from_millis(500))); + assert_eq!( + heap._time_remaining(now + duration), + Some(Duration::new(0, 0)) + ); + assert_eq!( + heap._time_remaining(now + duration + Duration::from_millis(100)), + Some(Duration::new(0, 0)) + ); assert_eq!(heap.remove(2), false); assert!(heap.remove(1)); - assert_matches!(heap._time_remaining(now), None); + assert_eq!(heap._time_remaining(now), None); } #[test]