1 // Copyright 2020 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::sync::Arc; 6 use std::time::Duration; 7 use std::time::Instant; 8 9 use sync::Mutex; 10 11 use super::Event; 12 use super::EventWaitResult; 13 use super::FakeClock; 14 use super::RawDescriptor; 15 use super::Result; 16 use crate::descriptor::AsRawDescriptor; 17 use crate::descriptor::FromRawDescriptor; 18 use crate::descriptor::IntoRawDescriptor; 19 use crate::descriptor::SafeDescriptor; 20 21 /// A trait for timer objects that delivers timer expiration 22 /// notifications to an underlying descriptor. 23 pub trait TimerTrait: AsRawDescriptor + IntoRawDescriptor + Send { 24 /// Sets the timer to expire after `dur` without repeating. Cancels any existing timer. reset_oneshot(&mut self, dur: Duration) -> Result<()>25 fn reset_oneshot(&mut self, dur: Duration) -> Result<()>; 26 27 /// Sets the timer to fire repeatedly at `dur` intervals. Cancels any existing timer. reset_repeating(&mut self, dur: Duration) -> Result<()>28 fn reset_repeating(&mut self, dur: Duration) -> Result<()>; 29 30 /// Waits until the timer expires. wait(&mut self) -> Result<()>31 fn wait(&mut self) -> Result<()>; 32 33 /// After a timer is triggered from an EventContext, mark the timer as having been waited for. 34 /// If a timer is not marked waited, it will immediately trigger the event context again. This 35 /// does not need to be called after calling Timer::wait. 36 /// 37 /// Returns true if the timer has been adjusted since the EventContext was triggered by this 38 /// timer. mark_waited(&mut self) -> Result<bool>39 fn mark_waited(&mut self) -> Result<bool>; 40 41 /// Disarms the timer. clear(&mut self) -> Result<()>42 fn clear(&mut self) -> Result<()>; 43 44 /// Returns the resolution of timers on the host. resolution(&self) -> Result<Duration>45 fn resolution(&self) -> Result<Duration>; 46 } 47 48 pub struct Timer { 49 pub(crate) handle: SafeDescriptor, 50 pub(crate) interval: Option<Duration>, 51 } 52 53 impl Timer { 54 /// Creates a new `Timer` instance that shares the same underlying `SafeDescriptor` as the 55 /// existing `Timer` instance. try_clone(&self) -> std::result::Result<Timer, std::io::Error>56 pub fn try_clone(&self) -> std::result::Result<Timer, std::io::Error> { 57 self.handle 58 .try_clone() 59 .map(|handle| Timer { 60 handle, 61 interval: self.interval, 62 }) 63 .map_err(|err| std::io::Error::from_raw_os_error(err.errno())) 64 } 65 } 66 67 // This enum represents those two different retrun values from a "wait" call. Either the 68 // timer will "expire", meaning it has reached it's duration, or the caller will time out 69 // waiting for the timer to expire. If no timeout option is provieded to the wait call 70 // then it can only return WaitResult::Expired or an error. 71 #[derive(PartialEq, Eq, Debug)] 72 enum WaitResult { 73 Expired, 74 Timeout, 75 } 76 77 impl AsRawDescriptor for Timer { as_raw_descriptor(&self) -> RawDescriptor78 fn as_raw_descriptor(&self) -> RawDescriptor { 79 self.handle.as_raw_descriptor() 80 } 81 } 82 83 impl FromRawDescriptor for Timer { from_raw_descriptor(handle: RawDescriptor) -> Self84 unsafe fn from_raw_descriptor(handle: RawDescriptor) -> Self { 85 Timer { 86 handle: SafeDescriptor::from_raw_descriptor(handle), 87 interval: None, 88 } 89 } 90 } 91 92 impl IntoRawDescriptor for Timer { into_raw_descriptor(self) -> RawDescriptor93 fn into_raw_descriptor(self) -> RawDescriptor { 94 self.handle.into_raw_descriptor() 95 } 96 } 97 98 /// FakeTimer: For use in tests. 99 pub struct FakeTimer { 100 clock: Arc<Mutex<FakeClock>>, 101 deadline_ns: Option<u64>, 102 interval: Option<Duration>, 103 event: Event, 104 } 105 106 impl FakeTimer { 107 /// Creates a new fake Timer. The timer is initally disarmed and must be armed by calling 108 /// `reset`. new(clock: Arc<Mutex<FakeClock>>) -> Self109 pub fn new(clock: Arc<Mutex<FakeClock>>) -> Self { 110 FakeTimer { 111 clock, 112 deadline_ns: None, 113 interval: None, 114 event: Event::new().unwrap(), 115 } 116 } 117 reset(&mut self, dur: Duration) -> Result<()>118 fn reset(&mut self, dur: Duration) -> Result<()> { 119 let mut guard = self.clock.lock(); 120 let deadline = guard.nanos() + dur.as_nanos() as u64; 121 self.deadline_ns = Some(deadline); 122 guard.add_event(deadline, self.event.try_clone()?); 123 Ok(()) 124 } 125 126 /// Waits until the timer expires or an optional wait timeout expires, whichever happens first. 127 /// 128 /// # Returns 129 /// 130 /// - `WaitResult::Expired` if the timer expired. 131 /// - `WaitResult::Timeout` if `timeout` was not `None` and the timer did not expire within the 132 /// specified timeout period. wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult>133 fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> { 134 let wait_start = Instant::now(); 135 loop { 136 if let Some(timeout) = timeout { 137 let elapsed = Instant::now() - wait_start; 138 if let Some(remaining) = elapsed.checked_sub(timeout) { 139 if let EventWaitResult::TimedOut = self.event.wait_timeout(remaining)? { 140 return Ok(WaitResult::Timeout); 141 } 142 } else { 143 return Ok(WaitResult::Timeout); 144 } 145 } else { 146 self.event.wait()?; 147 } 148 149 if let Some(deadline_ns) = &mut self.deadline_ns { 150 let mut guard = self.clock.lock(); 151 let now = guard.nanos(); 152 if now >= *deadline_ns { 153 let mut expirys = 0; 154 if let Some(interval) = self.interval { 155 let interval_ns = interval.as_nanos() as u64; 156 if interval_ns > 0 { 157 expirys += (now - *deadline_ns) / interval_ns; 158 *deadline_ns += (expirys + 1) * interval_ns; 159 guard.add_event(*deadline_ns, self.event.try_clone()?); 160 } 161 } 162 return Ok(WaitResult::Expired); 163 } 164 } 165 } 166 } 167 } 168 169 impl TimerTrait for FakeTimer { reset_oneshot(&mut self, dur: Duration) -> Result<()>170 fn reset_oneshot(&mut self, dur: Duration) -> Result<()> { 171 self.interval = None; 172 self.reset(dur) 173 } 174 reset_repeating(&mut self, dur: Duration) -> Result<()>175 fn reset_repeating(&mut self, dur: Duration) -> Result<()> { 176 self.interval = Some(dur); 177 self.reset(dur) 178 } 179 wait(&mut self) -> Result<()>180 fn wait(&mut self) -> Result<()> { 181 self.wait_for(None).map(|_| ()) 182 } 183 mark_waited(&mut self) -> Result<bool>184 fn mark_waited(&mut self) -> Result<bool> { 185 // Just do a self.wait with a timeout of 0. If it times out then the timer has been 186 // adjusted. 187 if let WaitResult::Timeout = self.wait_for(Some(Duration::from_secs(0)))? { 188 Ok(true) 189 } else { 190 Ok(false) 191 } 192 } 193 clear(&mut self) -> Result<()>194 fn clear(&mut self) -> Result<()> { 195 self.deadline_ns = None; 196 self.interval = None; 197 Ok(()) 198 } 199 resolution(&self) -> Result<Duration>200 fn resolution(&self) -> Result<Duration> { 201 Ok(Duration::from_nanos(1)) 202 } 203 } 204 205 impl AsRawDescriptor for FakeTimer { as_raw_descriptor(&self) -> RawDescriptor206 fn as_raw_descriptor(&self) -> RawDescriptor { 207 self.event.as_raw_descriptor() 208 } 209 } 210 impl IntoRawDescriptor for FakeTimer { into_raw_descriptor(self) -> RawDescriptor211 fn into_raw_descriptor(self) -> RawDescriptor { 212 self.event.into_raw_descriptor() 213 } 214 } 215 216 #[cfg(test)] 217 mod tests { 218 use std::time::Duration; 219 use std::time::Instant; 220 221 use super::*; 222 use crate::EventToken; 223 use crate::WaitContext; 224 225 #[test] one_shot()226 fn one_shot() { 227 let mut tfd = Timer::new().expect("failed to create Timer"); 228 229 let dur = Duration::from_millis(10); 230 let now = Instant::now(); 231 tfd.reset_oneshot(dur).expect("failed to arm timer"); 232 tfd.wait().expect("unable to wait for timer"); 233 let elapsed = now.elapsed(); 234 assert!(elapsed >= dur, "expected {:?} >= {:?}", elapsed, dur); 235 } 236 237 /// Similar to one_shot, except this one waits for a clone of the timer. 238 #[test] one_shot_cloned()239 fn one_shot_cloned() { 240 let mut tfd = Timer::new().expect("failed to create Timer"); 241 let mut cloned_tfd = tfd.try_clone().expect("failed to clone timer"); 242 243 let dur = Duration::from_millis(10); 244 let now = Instant::now(); 245 tfd.reset_oneshot(dur).expect("failed to arm timer"); 246 cloned_tfd.wait().expect("unable to wait for timer"); 247 let elapsed = now.elapsed(); 248 assert!(elapsed >= dur, "expected {:?} >= {:?}", elapsed, dur); 249 } 250 251 #[test] repeating()252 fn repeating() { 253 let mut tfd = Timer::new().expect("failed to create Timer"); 254 255 let interval = Duration::from_millis(10); 256 let now = Instant::now(); 257 tfd.reset_repeating(interval).expect("failed to arm timer"); 258 259 tfd.wait().expect("unable to wait for timer"); 260 // should take `interval` duration for the first wait 261 assert!(now.elapsed() >= interval); 262 tfd.wait().expect("unable to wait for timer"); 263 // subsequent waits should take "interval" duration 264 assert!(now.elapsed() >= interval * 2); 265 tfd.wait().expect("unable to wait for timer"); 266 assert!(now.elapsed() >= interval * 3); 267 } 268 269 #[test] mark_waited_inactive()270 fn mark_waited_inactive() { 271 let mut tfd = Timer::new().expect("failed to create Timer"); 272 // This ought to return true, but Windows always returns false, so we can't assert it here. 273 tfd.mark_waited().expect("mark_waited failed"); 274 } 275 276 #[test] mark_waited_active()277 fn mark_waited_active() { 278 let mut tfd = Timer::new().expect("failed to create Timer"); 279 tfd.reset_oneshot(Duration::from_nanos(1)) 280 .expect("failed to arm timer"); 281 282 // Use a WaitContext to block until the timer has fired. 283 #[derive(EventToken)] 284 enum Token { 285 Timer, 286 } 287 let wait_ctx: WaitContext<Token> = 288 WaitContext::build_with(&[(&tfd, Token::Timer)]).unwrap(); 289 let _events = wait_ctx.wait().unwrap(); 290 291 assert!( 292 !tfd.mark_waited().expect("mark_waited failed"), 293 "expected mark_waited to return false", 294 ); 295 } 296 297 #[test] fake_one_shot()298 fn fake_one_shot() { 299 let clock = Arc::new(Mutex::new(FakeClock::new())); 300 let mut tfd = FakeTimer::new(clock.clone()); 301 302 let dur = Duration::from_nanos(200); 303 tfd.reset_oneshot(dur).expect("failed to arm timer"); 304 305 clock.lock().add_ns(200); 306 307 assert_eq!(tfd.wait().is_ok(), true); 308 } 309 310 #[test] fake_one_shot_timeout()311 fn fake_one_shot_timeout() { 312 let clock = Arc::new(Mutex::new(FakeClock::new())); 313 let mut tfd = FakeTimer::new(clock.clone()); 314 315 let dur = Duration::from_nanos(200); 316 tfd.reset_oneshot(dur).expect("failed to arm timer"); 317 318 clock.lock().add_ns(100); 319 let result = tfd 320 .wait_for(Some(Duration::from_millis(0))) 321 .expect("unable to wait for timer"); 322 assert_eq!(result, WaitResult::Timeout); 323 let result = tfd 324 .wait_for(Some(Duration::from_millis(1))) 325 .expect("unable to wait for timer"); 326 assert_eq!(result, WaitResult::Timeout); 327 328 clock.lock().add_ns(100); 329 let result = tfd 330 .wait_for(Some(Duration::from_millis(0))) 331 .expect("unable to wait for timer"); 332 assert_eq!(result, WaitResult::Expired); 333 } 334 335 #[test] fake_repeating()336 fn fake_repeating() { 337 let clock = Arc::new(Mutex::new(FakeClock::new())); 338 let mut tfd = FakeTimer::new(clock.clone()); 339 340 let interval = Duration::from_nanos(100); 341 tfd.reset_repeating(interval).expect("failed to arm timer"); 342 343 clock.lock().add_ns(150); 344 345 // An expiration from the initial expiry and from 1 repeat. 346 assert_eq!(tfd.wait().is_ok(), true); 347 348 clock.lock().add_ns(100); 349 assert_eq!(tfd.wait().is_ok(), true); 350 } 351 } 352