|
1 | 1 | use std::pin::Pin; |
2 | 2 | use std::task::{Context, Poll}; |
3 | | -use std::time::{Duration, Instant}; |
| 3 | +use std::time::Duration; |
4 | 4 |
|
5 | 5 | use crate::future::Future; |
6 | 6 | use crate::stream::Stream; |
@@ -71,125 +71,8 @@ impl Stream for Interval { |
71 | 71 | if Pin::new(&mut self.delay).poll(cx).is_pending() { |
72 | 72 | return Poll::Pending; |
73 | 73 | } |
74 | | - let when = Instant::now(); |
75 | | - let next = next_interval(when, Instant::now(), self.interval); |
76 | | - self.delay.reset(next); |
| 74 | + let interval = self.interval; |
| 75 | + self.delay.reset(interval); |
77 | 76 | Poll::Ready(Some(())) |
78 | 77 | } |
79 | 78 | } |
80 | | - |
81 | | -/// Converts Duration object to raw nanoseconds if possible |
82 | | -/// |
83 | | -/// This is useful to divide intervals. |
84 | | -/// |
85 | | -/// While technically for large duration it's impossible to represent any |
86 | | -/// duration as nanoseconds, the largest duration we can represent is about |
87 | | -/// 427_000 years. Large enough for any interval we would use or calculate in |
88 | | -/// async-std. |
89 | | -fn duration_to_nanos(dur: Duration) -> Option<u64> { |
90 | | - dur.as_secs() |
91 | | - .checked_mul(1_000_000_000) |
92 | | - .and_then(|v| v.checked_add(u64::from(dur.subsec_nanos()))) |
93 | | -} |
94 | | - |
95 | | -fn next_interval(prev: Instant, now: Instant, interval: Duration) -> Instant { |
96 | | - let new = prev + interval; |
97 | | - if new > now { |
98 | | - return new; |
99 | | - } |
100 | | - |
101 | | - let spent_ns = duration_to_nanos(now.duration_since(prev)).expect("interval should be expired"); |
102 | | - let interval_ns = |
103 | | - duration_to_nanos(interval).expect("interval is less that 427 thousand years"); |
104 | | - let mult = spent_ns / interval_ns + 1; |
105 | | - assert!( |
106 | | - mult < (1 << 32), |
107 | | - "can't skip more than 4 billion intervals of {:?} \ |
108 | | - (trying to skip {})", |
109 | | - interval, |
110 | | - mult |
111 | | - ); |
112 | | - prev + interval * (mult as u32) |
113 | | -} |
114 | | - |
115 | | -#[cfg(test)] |
116 | | -mod test { |
117 | | - use super::next_interval; |
118 | | - use std::cmp::Ordering; |
119 | | - use std::time::{Duration, Instant}; |
120 | | - |
121 | | - struct Timeline(Instant); |
122 | | - |
123 | | - impl Timeline { |
124 | | - fn new() -> Timeline { |
125 | | - Timeline(Instant::now()) |
126 | | - } |
127 | | - fn at(&self, millis: u64) -> Instant { |
128 | | - self.0 + Duration::from_millis(millis) |
129 | | - } |
130 | | - fn at_ns(&self, sec: u64, nanos: u32) -> Instant { |
131 | | - self.0 + Duration::new(sec, nanos) |
132 | | - } |
133 | | - } |
134 | | - |
135 | | - fn dur(millis: u64) -> Duration { |
136 | | - Duration::from_millis(millis) |
137 | | - } |
138 | | - |
139 | | - // The math around Instant/Duration isn't 100% precise due to rounding |
140 | | - // errors, see #249 for more info |
141 | | - fn almost_eq(a: Instant, b: Instant) -> bool { |
142 | | - match a.cmp(&b) { |
143 | | - Ordering::Equal => true, |
144 | | - Ordering::Greater => a - b < Duration::from_millis(1), |
145 | | - Ordering::Less => b - a < Duration::from_millis(1), |
146 | | - } |
147 | | - } |
148 | | - |
149 | | - #[test] |
150 | | - fn norm_next() { |
151 | | - let tm = Timeline::new(); |
152 | | - assert!(almost_eq( |
153 | | - next_interval(tm.at(1), tm.at(2), dur(10)), |
154 | | - tm.at(11) |
155 | | - )); |
156 | | - assert!(almost_eq( |
157 | | - next_interval(tm.at(7777), tm.at(7788), dur(100)), |
158 | | - tm.at(7877) |
159 | | - )); |
160 | | - assert!(almost_eq( |
161 | | - next_interval(tm.at(1), tm.at(1000), dur(2100)), |
162 | | - tm.at(2101) |
163 | | - )); |
164 | | - } |
165 | | - |
166 | | - #[test] |
167 | | - fn fast_forward() { |
168 | | - let tm = Timeline::new(); |
169 | | - assert!(almost_eq( |
170 | | - next_interval(tm.at(1), tm.at(1000), dur(10)), |
171 | | - tm.at(1001) |
172 | | - )); |
173 | | - assert!(almost_eq( |
174 | | - next_interval(tm.at(7777), tm.at(8888), dur(100)), |
175 | | - tm.at(8977) |
176 | | - )); |
177 | | - assert!(almost_eq( |
178 | | - next_interval(tm.at(1), tm.at(10000), dur(2100)), |
179 | | - tm.at(10501) |
180 | | - )); |
181 | | - } |
182 | | - |
183 | | - /// TODO: this test actually should be successful, but since we can't |
184 | | - /// multiply Duration on anything larger than u32 easily we decided |
185 | | - /// to allow it to fail for now |
186 | | - #[test] |
187 | | - #[should_panic(expected = "can't skip more than 4 billion intervals")] |
188 | | - fn large_skip() { |
189 | | - let tm = Timeline::new(); |
190 | | - assert_eq!( |
191 | | - next_interval(tm.at_ns(0, 1), tm.at_ns(25, 0), Duration::new(0, 2)), |
192 | | - tm.at_ns(25, 1) |
193 | | - ); |
194 | | - } |
195 | | -} |
0 commit comments