From 8b9be5b2fc706546a717052da2b5627337d1a431 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 6 Sep 2022 12:57:26 -0700 Subject: [PATCH] rt: move time driver into `runtime` module This patch moves the time driver into the runtime module. The time driver is a runtime concern and is only used by the runtime. Moving the drivers is the first step to cleaning up some Tokio internals. There will be follow-up patches that integrate the drivers and other runtime concerns more closely. This is an internal refactor and should not impact any public APIs. --- tokio/src/lib.rs | 5 +- tokio/src/runtime/driver.rs | 6 +- tokio/src/runtime/mod.rs | 4 + .../{time/driver => runtime/time}/entry.rs | 2 +- .../{time/driver => runtime/time}/handle.rs | 4 +- .../src/{time/driver => runtime/time}/mod.rs | 15 +- .../driver => runtime/time}/tests/mod.rs | 55 +-- .../driver => runtime/time}/wheel/level.rs | 4 +- .../driver => runtime/time}/wheel/mod.rs | 2 +- tokio/src/time/mod.rs | 13 +- tokio/src/time/{driver => }/sleep.rs | 4 +- tokio/src/time/tests/mod.rs | 22 - tokio/src/time/tests/test_sleep.rs | 443 ------------------ 13 files changed, 33 insertions(+), 546 deletions(-) rename tokio/src/{time/driver => runtime/time}/entry.rs (99%) rename tokio/src/{time/driver => runtime/time}/handle.rs (97%) rename tokio/src/{time/driver => runtime/time}/mod.rs (97%) rename tokio/src/{time/driver => runtime/time}/tests/mod.rs (82%) rename tokio/src/{time/driver => runtime/time}/wheel/level.rs (98%) rename tokio/src/{time/driver => runtime/time}/wheel/mod.rs (99%) rename tokio/src/time/{driver => }/sleep.rs (99%) delete mode 100644 tokio/src/time/tests/mod.rs delete mode 100644 tokio/src/time/tests/test_sleep.rs diff --git a/tokio/src/lib.rs b/tokio/src/lib.rs index 3de3d21ef7e..b4c7b43f06f 100644 --- a/tokio/src/lib.rs +++ b/tokio/src/lib.rs @@ -497,9 +497,8 @@ cfg_rt! { pub mod runtime; } cfg_not_rt! { - cfg_io_driver_impl! { - pub(crate) mod runtime; - } + // The `runtime` module is used when the IO or time driver is needed. + pub(crate) mod runtime; } pub(crate) mod coop; diff --git a/tokio/src/runtime/driver.rs b/tokio/src/runtime/driver.rs index 916e1bfbdc6..74ee772506e 100644 --- a/tokio/src/runtime/driver.rs +++ b/tokio/src/runtime/driver.rs @@ -98,10 +98,10 @@ cfg_not_process_driver! { // ===== time driver ===== cfg_time! { - type TimeDriver = crate::park::either::Either, IoStack>; + type TimeDriver = crate::park::either::Either, IoStack>; pub(crate) type Clock = crate::time::Clock; - pub(crate) type TimeHandle = Option; + pub(crate) type TimeHandle = Option; fn create_clock(enable_pausing: bool, start_paused: bool) -> Clock { crate::time::Clock::new(enable_pausing, start_paused) @@ -115,7 +115,7 @@ cfg_time! { use crate::park::either::Either; if enable { - let driver = crate::time::driver::Driver::new(io_stack, clock); + let driver = crate::runtime::time::Driver::new(io_stack, clock); let handle = driver.handle(); (Either::A(driver), Some(handle)) diff --git a/tokio/src/runtime/mod.rs b/tokio/src/runtime/mod.rs index 5b1bc2ac376..36238e376cd 100644 --- a/tokio/src/runtime/mod.rs +++ b/tokio/src/runtime/mod.rs @@ -181,6 +181,10 @@ cfg_io_driver_impl! { pub(crate) mod io; } +cfg_time! { + pub(crate) mod time; +} + cfg_rt! { pub(crate) mod enter; diff --git a/tokio/src/time/driver/entry.rs b/tokio/src/runtime/time/entry.rs similarity index 99% rename from tokio/src/time/driver/entry.rs rename to tokio/src/runtime/time/entry.rs index 48856bf3223..1a301d0e9c2 100644 --- a/tokio/src/time/driver/entry.rs +++ b/tokio/src/runtime/time/entry.rs @@ -283,7 +283,7 @@ impl StateCell { /// timer. As this participates in intrusive data structures, it must be pinned /// before polling. #[derive(Debug)] -pub(super) struct TimerEntry { +pub(crate) struct TimerEntry { /// Arc reference to the driver. We can only free the driver after /// deregistering everything from their respective timer wheels. driver: Handle, diff --git a/tokio/src/time/driver/handle.rs b/tokio/src/runtime/time/handle.rs similarity index 97% rename from tokio/src/time/driver/handle.rs rename to tokio/src/runtime/time/handle.rs index 136919d9e78..f6878674761 100644 --- a/tokio/src/time/driver/handle.rs +++ b/tokio/src/runtime/time/handle.rs @@ -1,5 +1,5 @@ use crate::loom::sync::Arc; -use crate::time::driver::ClockTime; +use crate::runtime::time::ClockTime; use std::fmt; /// Handle to time driver instance. @@ -17,7 +17,7 @@ impl Handle { } /// Returns the time source associated with this handle. - pub(super) fn time_source(&self) -> &ClockTime { + pub(crate) fn time_source(&self) -> &ClockTime { &self.time_source } diff --git a/tokio/src/time/driver/mod.rs b/tokio/src/runtime/time/mod.rs similarity index 97% rename from tokio/src/time/driver/mod.rs rename to tokio/src/runtime/time/mod.rs index 99718774793..b5cad2ee0a7 100644 --- a/tokio/src/time/driver/mod.rs +++ b/tokio/src/runtime/time/mod.rs @@ -7,15 +7,14 @@ //! Time driver. mod entry; -pub(self) use self::entry::{EntryList, TimerEntry, TimerHandle, TimerShared}; +pub(crate) use entry::TimerEntry; +use entry::{EntryList, TimerHandle, TimerShared}; mod handle; pub(crate) use self::handle::Handle; mod wheel; -pub(super) mod sleep; - use crate::loom::sync::atomic::{AtomicBool, Ordering}; use crate::loom::sync::{Arc, Mutex}; use crate::park::{Park, Unpark}; @@ -104,8 +103,8 @@ pub(crate) struct Driver { /// A structure which handles conversion from Instants to u64 timestamps. #[derive(Debug, Clone)] -pub(self) struct ClockTime { - clock: super::clock::Clock, +pub(crate) struct ClockTime { + clock: crate::time::Clock, start_time: Instant, } @@ -117,7 +116,7 @@ impl ClockTime { } } - pub(self) fn deadline_to_tick(&self, t: Instant) -> u64 { + pub(crate) fn deadline_to_tick(&self, t: Instant) -> u64 { // Round up to the end of a ms self.instant_to_tick(t + Duration::from_nanos(999_999)) } @@ -136,7 +135,7 @@ impl ClockTime { Duration::from_millis(t) } - pub(self) fn now(&self) -> u64 { + pub(crate) fn now(&self) -> u64 { self.instant_to_tick(self.clock.now()) } } @@ -403,7 +402,7 @@ impl Handle { None } - Err((entry, super::error::InsertError::Elapsed)) => unsafe { + Err((entry, crate::time::error::InsertError::Elapsed)) => unsafe { entry.fire(Ok(())) }, } diff --git a/tokio/src/time/driver/tests/mod.rs b/tokio/src/runtime/time/tests/mod.rs similarity index 82% rename from tokio/src/time/driver/tests/mod.rs rename to tokio/src/runtime/time/tests/mod.rs index efccd57253a..541e78256e6 100644 --- a/tokio/src/time/driver/tests/mod.rs +++ b/tokio/src/runtime/time/tests/mod.rs @@ -48,7 +48,7 @@ fn model(f: impl Fn() + Send + Sync + 'static) { #[test] fn single_timer() { model(|| { - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); let time_source = super::ClockTime::new(clock.clone()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); @@ -79,7 +79,7 @@ fn single_timer() { #[test] fn drop_timer() { model(|| { - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); let time_source = super::ClockTime::new(clock.clone()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); @@ -110,7 +110,7 @@ fn drop_timer() { #[test] fn change_waker() { model(|| { - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); let time_source = super::ClockTime::new(clock.clone()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); @@ -145,7 +145,7 @@ fn reset_future() { model(|| { let finished_early = Arc::new(AtomicBool::new(false)); - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); let time_source = super::ClockTime::new(clock.clone()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); @@ -201,7 +201,7 @@ fn normal_or_miri(normal: T, miri: T) -> T { #[test] #[cfg(not(loom))] fn poll_process_levels() { - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); clock.pause(); let time_source = super::ClockTime::new(clock.clone()); @@ -242,7 +242,7 @@ fn poll_process_levels() { fn poll_process_levels_targeted() { let mut context = Context::from_waker(noop_waker_ref()); - let clock = crate::time::clock::Clock::new(true, false); + let clock = crate::time::Clock::new(true, false); clock.pause(); let time_source = super::ClockTime::new(clock.clone()); @@ -258,46 +258,3 @@ fn poll_process_levels_targeted() { handle.process_at_time(192); handle.process_at_time(192); } - -/* -#[test] -fn balanced_incr_and_decr() { - const OPS: usize = 5; - - fn incr(inner: Arc) { - for _ in 0..OPS { - inner.increment().expect("increment should not have failed"); - thread::yield_now(); - } - } - - fn decr(inner: Arc) { - let mut ops_performed = 0; - while ops_performed < OPS { - if inner.num(Ordering::Relaxed) > 0 { - ops_performed += 1; - inner.decrement(); - } - thread::yield_now(); - } - } - - loom::model(|| { - let unpark = Box::new(MockUnpark); - let instant = Instant::now(); - - let inner = Arc::new(Inner::new(instant, unpark)); - - let incr_inner = inner.clone(); - let decr_inner = inner.clone(); - - let incr_handle = thread::spawn(move || incr(incr_inner)); - let decr_handle = thread::spawn(move || decr(decr_inner)); - - incr_handle.join().expect("should never fail"); - decr_handle.join().expect("should never fail"); - - assert_eq!(inner.num(Ordering::SeqCst), 0); - }) -} -*/ diff --git a/tokio/src/time/driver/wheel/level.rs b/tokio/src/runtime/time/wheel/level.rs similarity index 98% rename from tokio/src/time/driver/wheel/level.rs rename to tokio/src/runtime/time/wheel/level.rs index 878754177b9..7e48ff5c57d 100644 --- a/tokio/src/time/driver/wheel/level.rs +++ b/tokio/src/runtime/time/wheel/level.rs @@ -1,6 +1,4 @@ -use crate::time::driver::TimerHandle; - -use crate::time::driver::{EntryList, TimerShared}; +use crate::runtime::time::{EntryList, TimerHandle, TimerShared}; use std::{fmt, ptr::NonNull}; diff --git a/tokio/src/time/driver/wheel/mod.rs b/tokio/src/runtime/time/wheel/mod.rs similarity index 99% rename from tokio/src/time/driver/wheel/mod.rs rename to tokio/src/runtime/time/wheel/mod.rs index f088f2cfd66..c3ba3643305 100644 --- a/tokio/src/time/driver/wheel/mod.rs +++ b/tokio/src/runtime/time/wheel/mod.rs @@ -1,4 +1,4 @@ -use crate::time::driver::{TimerHandle, TimerShared}; +use crate::runtime::time::{TimerHandle, TimerShared}; use crate::time::error::InsertError; mod level; diff --git a/tokio/src/time/mod.rs b/tokio/src/time/mod.rs index 281990ef9ac..a1f27b839e9 100644 --- a/tokio/src/time/mod.rs +++ b/tokio/src/time/mod.rs @@ -82,17 +82,13 @@ //! ``` //! //! [`interval`]: crate::time::interval() +//! [`sleep`]: sleep() mod clock; pub(crate) use self::clock::Clock; #[cfg(feature = "test-util")] pub use clock::{advance, pause, resume}; -pub(crate) mod driver; - -#[doc(inline)] -pub use driver::sleep::{sleep, sleep_until, Sleep}; - pub mod error; mod instant; @@ -101,14 +97,13 @@ pub use self::instant::Instant; mod interval; pub use interval::{interval, interval_at, Interval, MissedTickBehavior}; +mod sleep; +pub use sleep::{sleep, sleep_until, Sleep}; + mod timeout; #[doc(inline)] pub use timeout::{timeout, timeout_at, Timeout}; -#[cfg(test)] -#[cfg(not(loom))] -mod tests; - // Re-export for convenience #[doc(no_inline)] pub use std::time::Duration; diff --git a/tokio/src/time/driver/sleep.rs b/tokio/src/time/sleep.rs similarity index 99% rename from tokio/src/time/driver/sleep.rs rename to tokio/src/time/sleep.rs index 2ff6ad592b2..29db2fbeeab 100644 --- a/tokio/src/time/driver/sleep.rs +++ b/tokio/src/time/sleep.rs @@ -1,6 +1,6 @@ #[cfg(all(tokio_unstable, feature = "tracing"))] -use crate::time::driver::ClockTime; -use crate::time::driver::{Handle, TimerEntry}; +use crate::runtime::time::ClockTime; +use crate::runtime::time::{Handle, TimerEntry}; use crate::time::{error::Error, Duration, Instant}; use crate::util::trace; diff --git a/tokio/src/time/tests/mod.rs b/tokio/src/time/tests/mod.rs deleted file mode 100644 index 35e1060aca0..00000000000 --- a/tokio/src/time/tests/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -mod test_sleep; - -use crate::time::{self, Instant}; -use std::time::Duration; - -fn assert_send() {} -fn assert_sync() {} - -#[test] -fn registration_is_send_and_sync() { - use crate::time::Sleep; - - assert_send::(); - assert_sync::(); -} - -#[test] -#[should_panic] -fn sleep_is_eager() { - let when = Instant::now() + Duration::from_millis(100); - let _ = time::sleep_until(when); -} diff --git a/tokio/src/time/tests/test_sleep.rs b/tokio/src/time/tests/test_sleep.rs deleted file mode 100644 index 77ca07e319e..00000000000 --- a/tokio/src/time/tests/test_sleep.rs +++ /dev/null @@ -1,443 +0,0 @@ -//use crate::time::driver::{Driver, Entry, Handle}; - -/* -macro_rules! poll { - ($e:expr) => { - $e.enter(|cx, e| e.poll_elapsed(cx)) - }; -} - -#[test] -fn frozen_utility_returns_correct_advanced_duration() { - let clock = Clock::new(); - clock.pause(); - let start = clock.now(); - - clock.advance(ms(10)); - assert_eq!(clock.now() - start, ms(10)); -} - -#[test] -fn immediate_sleep() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - let when = clock.now(); - let mut e = task::spawn(sleep_until(&handle, when)); - - assert_ready_ok!(poll!(e)); - - assert_ok!(driver.park_timeout(Duration::from_millis(1000))); - - // The time has not advanced. The `turn` completed immediately. - assert_eq!(clock.now() - start, ms(1000)); -} - -#[test] -fn delayed_sleep_level_0() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - for &i in &[1, 10, 60] { - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, start + ms(i))); - - // The sleep instance has not elapsed. - assert_pending!(poll!(e)); - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(i)); - - assert_ready_ok!(poll!(e)); - } -} - -#[test] -fn sub_ms_delayed_sleep() { - let (mut driver, clock, handle) = setup(); - - for _ in 0..5 { - let deadline = clock.now() + ms(1) + Duration::new(0, 1); - - let mut e = task::spawn(sleep_until(&handle, deadline)); - - assert_pending!(poll!(e)); - - assert_ok!(driver.park()); - assert_ready_ok!(poll!(e)); - - assert!(clock.now() >= deadline); - - clock.advance(Duration::new(0, 1)); - } -} - -#[test] -fn delayed_sleep_wrapping_level_0() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - assert_ok!(driver.park_timeout(ms(5))); - assert_eq!(clock.now() - start, ms(5)); - - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(60))); - - assert_pending!(poll!(e)); - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(64)); - assert_pending!(poll!(e)); - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(65)); - - assert_ready_ok!(poll!(e)); -} - -#[test] -fn timer_wrapping_with_higher_levels() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Set sleep to hit level 1 - let mut e1 = task::spawn(sleep_until(&handle, clock.now() + ms(64))); - assert_pending!(poll!(e1)); - - // Turn a bit - assert_ok!(driver.park_timeout(ms(5))); - - // Set timeout such that it will hit level 0, but wrap - let mut e2 = task::spawn(sleep_until(&handle, clock.now() + ms(60))); - assert_pending!(poll!(e2)); - - // This should result in s1 firing - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(64)); - - assert_ready_ok!(poll!(e1)); - assert_pending!(poll!(e2)); - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(65)); - - assert_ready_ok!(poll!(e1)); -} - -#[test] -fn sleep_with_deadline_in_past() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create `Sleep` that elapsed immediately. - let mut e = task::spawn(sleep_until(&handle, clock.now() - ms(100))); - - // Even though the `Sleep` expires in the past, it is not ready yet - // because the timer must observe it. - assert_ready_ok!(poll!(e)); - - // Turn the timer, it runs for the elapsed time - assert_ok!(driver.park_timeout(ms(1000))); - - // The time has not advanced. The `turn` completed immediately. - assert_eq!(clock.now() - start, ms(1000)); -} - -#[test] -fn delayed_sleep_level_1() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(234))); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - // Turn the timer, this will wake up to cascade the timer down. - assert_ok!(driver.park_timeout(ms(1000))); - assert_eq!(clock.now() - start, ms(192)); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - // Turn the timer again - assert_ok!(driver.park_timeout(ms(1000))); - assert_eq!(clock.now() - start, ms(234)); - - // The sleep has elapsed. - assert_ready_ok!(poll!(e)); - - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(234))); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - // Turn the timer with a smaller timeout than the cascade. - assert_ok!(driver.park_timeout(ms(100))); - assert_eq!(clock.now() - start, ms(100)); - - assert_pending!(poll!(e)); - - // Turn the timer, this will wake up to cascade the timer down. - assert_ok!(driver.park_timeout(ms(1000))); - assert_eq!(clock.now() - start, ms(192)); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - // Turn the timer again - assert_ok!(driver.park_timeout(ms(1000))); - assert_eq!(clock.now() - start, ms(234)); - - // The sleep has elapsed. - assert_ready_ok!(poll!(e)); -} - -#[test] -fn concurrently_set_two_timers_second_one_shorter() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - let mut e1 = task::spawn(sleep_until(&handle, clock.now() + ms(500))); - let mut e2 = task::spawn(sleep_until(&handle, clock.now() + ms(200))); - - // The sleep has not elapsed - assert_pending!(poll!(e1)); - assert_pending!(poll!(e2)); - - // Sleep until a cascade - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(192)); - - // Sleep until the second timer. - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(200)); - - // The shorter sleep fires - assert_ready_ok!(poll!(e2)); - assert_pending!(poll!(e1)); - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(448)); - - assert_pending!(poll!(e1)); - - // Turn again, this time the time will advance to the second sleep - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(500)); - - assert_ready_ok!(poll!(e1)); -} - -#[test] -fn short_sleep() { - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(1))); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - // Turn the timer, but not enough time will go by. - assert_ok!(driver.park()); - - // The sleep has elapsed. - assert_ready_ok!(poll!(e)); - - // The time has advanced to the point of the sleep elapsing. - assert_eq!(clock.now() - start, ms(1)); -} - -#[test] -fn sorta_long_sleep_until() { - const MIN_5: u64 = 5 * 60 * 1000; - - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(MIN_5))); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - let cascades = &[262_144, 262_144 + 9 * 4096, 262_144 + 9 * 4096 + 15 * 64]; - - for &elapsed in cascades { - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(elapsed)); - - assert_pending!(poll!(e)); - } - - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(MIN_5)); - - // The sleep has elapsed. - assert_ready_ok!(poll!(e)); -} - -#[test] -fn very_long_sleep() { - const MO_5: u64 = 5 * 30 * 24 * 60 * 60 * 1000; - - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - // Create a `Sleep` that elapses in the future - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(MO_5))); - - // The sleep has not elapsed. - assert_pending!(poll!(e)); - - let cascades = &[ - 12_884_901_888, - 12_952_010_752, - 12_959_875_072, - 12_959_997_952, - ]; - - for &elapsed in cascades { - assert_ok!(driver.park()); - assert_eq!(clock.now() - start, ms(elapsed)); - - assert_pending!(poll!(e)); - } - - // Turn the timer, but not enough time will go by. - assert_ok!(driver.park()); - - // The time has advanced to the point of the sleep elapsing. - assert_eq!(clock.now() - start, ms(MO_5)); - - // The sleep has elapsed. - assert_ready_ok!(poll!(e)); -} - -#[test] -fn unpark_is_delayed() { - // A special park that will take much longer than the requested duration - struct MockPark(Clock); - - struct MockUnpark; - - impl Park for MockPark { - type Unpark = MockUnpark; - type Error = (); - - fn unpark(&self) -> Self::Unpark { - MockUnpark - } - - fn park(&mut self) -> Result<(), Self::Error> { - panic!("parking forever"); - } - - fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> { - assert_eq!(duration, ms(0)); - self.0.advance(ms(436)); - Ok(()) - } - - fn shutdown(&mut self) {} - } - - impl Unpark for MockUnpark { - fn unpark(&self) {} - } - - let clock = Clock::new(); - clock.pause(); - let start = clock.now(); - let mut driver = Driver::new(MockPark(clock.clone()), clock.clone()); - let handle = driver.handle(); - - let mut e1 = task::spawn(sleep_until(&handle, clock.now() + ms(100))); - let mut e2 = task::spawn(sleep_until(&handle, clock.now() + ms(101))); - let mut e3 = task::spawn(sleep_until(&handle, clock.now() + ms(200))); - - assert_pending!(poll!(e1)); - assert_pending!(poll!(e2)); - assert_pending!(poll!(e3)); - - assert_ok!(driver.park()); - - assert_eq!(clock.now() - start, ms(500)); - - assert_ready_ok!(poll!(e1)); - assert_ready_ok!(poll!(e2)); - assert_ready_ok!(poll!(e3)); -} - -#[test] -fn set_timeout_at_deadline_greater_than_max_timer() { - const YR_1: u64 = 365 * 24 * 60 * 60 * 1000; - const YR_5: u64 = 5 * YR_1; - - let (mut driver, clock, handle) = setup(); - let start = clock.now(); - - for _ in 0..5 { - assert_ok!(driver.park_timeout(ms(YR_1))); - } - - let mut e = task::spawn(sleep_until(&handle, clock.now() + ms(1))); - assert_pending!(poll!(e)); - - assert_ok!(driver.park_timeout(ms(1000))); - assert_eq!(clock.now() - start, ms(YR_5) + ms(1)); - - assert_ready_ok!(poll!(e)); -} - -fn setup() -> (Driver, Clock, Handle) { - let clock = Clock::new(); - clock.pause(); - let driver = Driver::new(MockPark(clock.clone()), clock.clone()); - let handle = driver.handle(); - - (driver, clock, handle) -} - -fn sleep_until(handle: &Handle, when: Instant) -> Arc { - Entry::new(&handle, when, ms(0)) -} - -struct MockPark(Clock); - -struct MockUnpark; - -impl Park for MockPark { - type Unpark = MockUnpark; - type Error = (); - - fn unpark(&self) -> Self::Unpark { - MockUnpark - } - - fn park(&mut self) -> Result<(), Self::Error> { - panic!("parking forever"); - } - - fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> { - self.0.advance(duration); - Ok(()) - } - - fn shutdown(&mut self) {} -} - -impl Unpark for MockUnpark { - fn unpark(&self) {} -} - -fn ms(n: u64) -> Duration { - Duration::from_millis(n) -} -*/