parent
5afae607ab
commit
4b3316a19e
63
src/lib.rs
63
src/lib.rs
|
@ -150,45 +150,36 @@ impl<T: Eq + Clone + Hash> TimerHeap<T> {
|
||||||
self.active.remove(&key).is_some()
|
self.active.remove(&key).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the amount of time remaining (in ms) for the earliest expiring timer
|
/// Return the amount of time remaining for the earliest expiring timer.
|
||||||
/// Return `None` if there are no timers in the heap
|
/// Return `None` if there are no timers in the heap.
|
||||||
pub fn time_remaining(&self) -> Option<u64> {
|
pub fn time_remaining(&self) -> Option<Duration> {
|
||||||
self._time_remaining(Instant::now())
|
self._time_remaining(Instant::now())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A deterministically testable version of `time_remaining()`
|
/// A deterministically testable version of `time_remaining()`
|
||||||
fn _time_remaining(&self, now: Instant) -> Option<u64> {
|
fn _time_remaining(&self, now: Instant) -> Option<Duration> {
|
||||||
self.timers.iter().find(|e| {
|
self.timers
|
||||||
self.active.get(&e.key) == Some(&e.counter)
|
.iter()
|
||||||
}).map(|e| {
|
.find(|e| self.active.get(&e.key) == Some(&e.counter))
|
||||||
if now > e.expires_at {
|
.map(|e| {
|
||||||
return 0;
|
if now > e.expires_at {
|
||||||
}
|
return Duration::new(0, 0);
|
||||||
let duration = e.expires_at - now;
|
}
|
||||||
// We add a millisecond if there is a fractional ms milliseconds in
|
e.expires_at - now
|
||||||
// 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
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the earliest timeout based on a user timeout and the least remaining time in the
|
/// Return the earliest timeout based on a user timeout and the least remaining time in the
|
||||||
/// next timer to fire.
|
/// 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 let Some(remaining) = self.time_remaining() {
|
||||||
if user_timeout_ms < remaining as usize {
|
if user_timeout < remaining {
|
||||||
user_timeout_ms
|
user_timeout
|
||||||
} else {
|
} else {
|
||||||
remaining as usize
|
remaining
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user_timeout_ms
|
user_timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,14 +263,20 @@ mod tests {
|
||||||
let mut heap = TimerHeap::new();
|
let mut heap = TimerHeap::new();
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let duration = Duration::from_millis(500);
|
let duration = Duration::from_millis(500);
|
||||||
heap._insert(1u64, duration, TimerType::Oneshot, now).unwrap();
|
heap._insert(1u64, duration, TimerType::Oneshot, now)
|
||||||
assert_matches!(heap._time_remaining(now), Some(500));
|
.unwrap();
|
||||||
assert_matches!(heap._time_remaining(now + duration), Some(0));
|
assert_eq!(heap._time_remaining(now), Some(Duration::from_millis(500)));
|
||||||
assert_matches!(heap._time_remaining(now + duration + Duration::from_millis(100)),
|
assert_eq!(
|
||||||
Some(0));
|
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_eq!(heap.remove(2), false);
|
||||||
assert!(heap.remove(1));
|
assert!(heap.remove(1));
|
||||||
assert_matches!(heap._time_remaining(now), None);
|
assert_eq!(heap._time_remaining(now), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue