mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-15 00:00:15 +02:00
rt: move time driver into runtime module (#4983)
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.
This commit is contained in:
+2
-3
@@ -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;
|
||||
|
||||
@@ -98,10 +98,10 @@ cfg_not_process_driver! {
|
||||
// ===== time driver =====
|
||||
|
||||
cfg_time! {
|
||||
type TimeDriver = crate::park::either::Either<crate::time::driver::Driver<IoStack>, IoStack>;
|
||||
type TimeDriver = crate::park::either::Either<crate::runtime::time::Driver<IoStack>, IoStack>;
|
||||
|
||||
pub(crate) type Clock = crate::time::Clock;
|
||||
pub(crate) type TimeHandle = Option<crate::time::driver::Handle>;
|
||||
pub(crate) type TimeHandle = Option<crate::runtime::time::Handle>;
|
||||
|
||||
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))
|
||||
|
||||
@@ -181,6 +181,10 @@ cfg_io_driver_impl! {
|
||||
pub(crate) mod io;
|
||||
}
|
||||
|
||||
cfg_time! {
|
||||
pub(crate) mod time;
|
||||
}
|
||||
|
||||
cfg_rt! {
|
||||
pub(crate) mod enter;
|
||||
|
||||
|
||||
@@ -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,
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<P: Park + 'static> {
|
||||
|
||||
/// 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(()))
|
||||
},
|
||||
}
|
||||
@@ -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<T>(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<Inner>) {
|
||||
for _ in 0..OPS {
|
||||
inner.increment().expect("increment should not have failed");
|
||||
thread::yield_now();
|
||||
}
|
||||
}
|
||||
|
||||
fn decr(inner: Arc<Inner>) {
|
||||
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);
|
||||
})
|
||||
}
|
||||
*/
|
||||
@@ -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};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::time::driver::{TimerHandle, TimerShared};
|
||||
use crate::runtime::time::{TimerHandle, TimerShared};
|
||||
use crate::time::error::InsertError;
|
||||
|
||||
mod level;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
mod test_sleep;
|
||||
|
||||
use crate::time::{self, Instant};
|
||||
use std::time::Duration;
|
||||
|
||||
fn assert_send<T: Send>() {}
|
||||
fn assert_sync<T: Sync>() {}
|
||||
|
||||
#[test]
|
||||
fn registration_is_send_and_sync() {
|
||||
use crate::time::Sleep;
|
||||
|
||||
assert_send::<Sleep>();
|
||||
assert_sync::<Sleep>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn sleep_is_eager() {
|
||||
let when = Instant::now() + Duration::from_millis(100);
|
||||
let _ = time::sleep_until(when);
|
||||
}
|
||||
@@ -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<MockPark>, 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> {
|
||||
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)
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user