rt: minor time driver refactors (#4989)

This patch makes some minor refactors. It renames `ClockTime` to
`TimeSource` since that is how all variables refer to it. It also moves
the type into a new file.

Finally, it moves the `unpark` handle out of the mutex as it does not
need to be there. Note, the call to `unpark` is still called while the
mutex is held, so there is no functional change. Moving it out of the
mutex is in preparation for moving the unpark handle completely out of
the time driver.
This commit is contained in:
Carl Lerche
2022-09-07 13:24:02 -07:00
committed by GitHub
parent 291fce8de3
commit 2ad347465e
5 changed files with 67 additions and 62 deletions
+4 -4
View File
@@ -1,12 +1,12 @@
use crate::loom::sync::Arc; use crate::loom::sync::Arc;
use crate::runtime::time::ClockTime; use crate::runtime::time::TimeSource;
use std::fmt; use std::fmt;
/// Handle to time driver instance. /// Handle to time driver instance.
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct Handle { pub(crate) struct Handle {
time_source: ClockTime, time_source: TimeSource,
inner: Arc<super::Inner>, pub(super) inner: Arc<super::Inner>,
} }
impl Handle { impl Handle {
@@ -17,7 +17,7 @@ impl Handle {
} }
/// Returns the time source associated with this handle. /// Returns the time source associated with this handle.
pub(crate) fn time_source(&self) -> &ClockTime { pub(crate) fn time_source(&self) -> &TimeSource {
&self.time_source &self.time_source
} }
+13 -50
View File
@@ -13,15 +13,17 @@ use entry::{EntryList, TimerHandle, TimerShared};
mod handle; mod handle;
pub(crate) use self::handle::Handle; pub(crate) use self::handle::Handle;
mod source;
pub(crate) use source::TimeSource;
mod wheel; mod wheel;
use crate::loom::sync::atomic::{AtomicBool, Ordering}; use crate::loom::sync::atomic::{AtomicBool, Ordering};
use crate::loom::sync::{Arc, Mutex}; use crate::loom::sync::{Arc, Mutex};
use crate::park::{Park, Unpark}; use crate::park::{Park, Unpark};
use crate::time::error::Error; use crate::time::error::Error;
use crate::time::{Clock, Duration, Instant}; use crate::time::{Clock, Duration};
use std::convert::TryInto;
use std::fmt; use std::fmt;
use std::{num::NonZeroU64, ptr::NonNull, task::Waker}; use std::{num::NonZeroU64, ptr::NonNull, task::Waker};
@@ -83,7 +85,7 @@ use std::{num::NonZeroU64, ptr::NonNull, task::Waker};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Driver<P: Park + 'static> { pub(crate) struct Driver<P: Park + 'static> {
/// Timing backend in use. /// Timing backend in use.
time_source: ClockTime, time_source: TimeSource,
/// Shared state. /// Shared state.
handle: Handle, handle: Handle,
@@ -101,45 +103,6 @@ pub(crate) struct Driver<P: Park + 'static> {
did_wake: Arc<AtomicBool>, did_wake: Arc<AtomicBool>,
} }
/// A structure which handles conversion from Instants to u64 timestamps.
#[derive(Debug, Clone)]
pub(crate) struct ClockTime {
clock: crate::time::Clock,
start_time: Instant,
}
impl ClockTime {
pub(self) fn new(clock: Clock) -> Self {
Self {
start_time: clock.now(),
clock,
}
}
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))
}
pub(self) fn instant_to_tick(&self, t: Instant) -> u64 {
// round up
let dur: Duration = t
.checked_duration_since(self.start_time)
.unwrap_or_else(|| Duration::from_secs(0));
let ms = dur.as_millis();
ms.try_into().unwrap_or(u64::MAX)
}
pub(self) fn tick_to_duration(&self, t: u64) -> Duration {
Duration::from_millis(t)
}
pub(crate) fn now(&self) -> u64 {
self.instant_to_tick(self.clock.now())
}
}
/// Timer state shared between `Driver`, `Handle`, and `Registration`. /// Timer state shared between `Driver`, `Handle`, and `Registration`.
struct Inner { struct Inner {
// The state is split like this so `Handle` can access `is_shutdown` without locking the mutex // The state is split like this so `Handle` can access `is_shutdown` without locking the mutex
@@ -147,12 +110,15 @@ struct Inner {
/// True if the driver is being shutdown. /// True if the driver is being shutdown.
pub(super) is_shutdown: AtomicBool, pub(super) is_shutdown: AtomicBool,
/// Unparker that can be used to wake the time driver.
unpark: Box<dyn Unpark>,
} }
/// Time state shared which must be protected by a `Mutex` /// Time state shared which must be protected by a `Mutex`
struct InnerState { struct InnerState {
/// Timing backend in use. /// Timing backend in use.
time_source: ClockTime, time_source: TimeSource,
/// The last published timer `elapsed` value. /// The last published timer `elapsed` value.
elapsed: u64, elapsed: u64,
@@ -162,9 +128,6 @@ struct InnerState {
/// Timer wheel. /// Timer wheel.
wheel: wheel::Wheel, wheel: wheel::Wheel,
/// Unparker that can be used to wake the time driver.
unpark: Box<dyn Unpark>,
} }
// ===== impl Driver ===== // ===== impl Driver =====
@@ -178,7 +141,7 @@ where
/// ///
/// Specifying the source of time is useful when testing. /// Specifying the source of time is useful when testing.
pub(crate) fn new(park: P, clock: Clock) -> Driver<P> { pub(crate) fn new(park: P, clock: Clock) -> Driver<P> {
let time_source = ClockTime::new(clock); let time_source = TimeSource::new(clock);
let inner = Inner::new(time_source.clone(), Box::new(park.unpark())); let inner = Inner::new(time_source.clone(), Box::new(park.unpark()));
@@ -397,7 +360,7 @@ impl Handle {
.map(|next_wake| when < next_wake.get()) .map(|next_wake| when < next_wake.get())
.unwrap_or(true) .unwrap_or(true)
{ {
lock.unpark.unpark(); self.inner.unpark.unpark();
} }
None None
@@ -493,15 +456,15 @@ impl<P: Park + 'static> Unpark for TimerUnpark<P> {
// ===== impl Inner ===== // ===== impl Inner =====
impl Inner { impl Inner {
pub(self) fn new(time_source: ClockTime, unpark: Box<dyn Unpark>) -> Self { pub(self) fn new(time_source: TimeSource, unpark: Box<dyn Unpark>) -> Self {
Inner { Inner {
state: Mutex::new(InnerState { state: Mutex::new(InnerState {
time_source, time_source,
elapsed: 0, elapsed: 0,
next_wake: None, next_wake: None,
unpark,
wheel: wheel::Wheel::new(), wheel: wheel::Wheel::new(),
}), }),
unpark,
is_shutdown: AtomicBool::new(false), is_shutdown: AtomicBool::new(false),
} }
} }
+42
View File
@@ -0,0 +1,42 @@
use crate::time::{Clock, Duration, Instant};
use std::convert::TryInto;
/// A structure which handles conversion from Instants to u64 timestamps.
#[derive(Debug, Clone)]
pub(crate) struct TimeSource {
pub(crate) clock: Clock,
start_time: Instant,
}
impl TimeSource {
pub(crate) fn new(clock: Clock) -> Self {
Self {
start_time: clock.now(),
clock,
}
}
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))
}
pub(crate) fn instant_to_tick(&self, t: Instant) -> u64 {
// round up
let dur: Duration = t
.checked_duration_since(self.start_time)
.unwrap_or_else(|| Duration::from_secs(0));
let ms = dur.as_millis();
ms.try_into().unwrap_or(u64::MAX)
}
pub(crate) fn tick_to_duration(&self, t: u64) -> Duration {
Duration::from_millis(t)
}
pub(crate) fn now(&self) -> u64 {
self.instant_to_tick(self.clock.now())
}
}
+6 -6
View File
@@ -49,7 +49,7 @@ fn model(f: impl Fn() + Send + Sync + 'static) {
fn single_timer() { fn single_timer() {
model(|| { model(|| {
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
@@ -80,7 +80,7 @@ fn single_timer() {
fn drop_timer() { fn drop_timer() {
model(|| { model(|| {
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
@@ -111,7 +111,7 @@ fn drop_timer() {
fn change_waker() { fn change_waker() {
model(|| { model(|| {
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
@@ -146,7 +146,7 @@ fn reset_future() {
let finished_early = Arc::new(AtomicBool::new(false)); let finished_early = Arc::new(AtomicBool::new(false));
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source.clone(), MockUnpark::mock()); let inner = super::Inner::new(time_source.clone(), MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
@@ -204,7 +204,7 @@ fn poll_process_levels() {
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
clock.pause(); clock.pause();
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source, MockUnpark::mock()); let inner = super::Inner::new(time_source, MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
@@ -245,7 +245,7 @@ fn poll_process_levels_targeted() {
let clock = crate::time::Clock::new(true, false); let clock = crate::time::Clock::new(true, false);
clock.pause(); clock.pause();
let time_source = super::ClockTime::new(clock.clone()); let time_source = super::TimeSource::new(clock.clone());
let inner = super::Inner::new(time_source, MockUnpark::mock()); let inner = super::Inner::new(time_source, MockUnpark::mock());
let handle = Handle::new(Arc::new(inner)); let handle = Handle::new(Arc::new(inner));
+2 -2
View File
@@ -1,5 +1,5 @@
#[cfg(all(tokio_unstable, feature = "tracing"))] #[cfg(all(tokio_unstable, feature = "tracing"))]
use crate::runtime::time::ClockTime; use crate::runtime::time::TimeSource;
use crate::runtime::time::{Handle, TimerEntry}; use crate::runtime::time::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant}; use crate::time::{error::Error, Duration, Instant};
use crate::util::trace; use crate::util::trace;
@@ -239,7 +239,7 @@ cfg_trace! {
struct Inner { struct Inner {
deadline: Instant, deadline: Instant,
ctx: trace::AsyncOpTracingCtx, ctx: trace::AsyncOpTracingCtx,
time_source: ClockTime, time_source: TimeSource,
} }
} }