tokio_timer/clock/
clock.rs

1use clock::Now;
2use timer;
3
4use tokio_executor::Enter;
5
6use std::cell::RefCell;
7use std::fmt;
8use std::sync::Arc;
9use std::time::Instant;
10
11/// A handle to a source of time.
12///
13/// `Clock` instances return [`Instant`] values corresponding to "now". The source
14/// of these values is configurable. The default source is [`Instant::now`].
15///
16/// [`Instant`]: https://doc.rust-lang.org/std/time/struct.Instant.html
17/// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
18#[derive(Default, Clone)]
19pub struct Clock {
20    now: Option<Arc<dyn Now>>,
21}
22
23/// A guard that resets the current `Clock` to `None` when dropped.
24#[derive(Debug)]
25pub struct DefaultGuard {
26    _p: (),
27}
28
29thread_local! {
30    /// Thread-local tracking the current clock
31    static CLOCK: RefCell<Option<Clock>> = RefCell::new(None)
32}
33
34/// Returns an `Instant` corresponding to "now".
35///
36/// This function delegates to the source of time configured for the current
37/// execution context. By default, this is `Instant::now()`.
38///
39/// Note that, because the source of time is configurable, it is possible to
40/// observe non-monotonic behavior when calling `now` from different
41/// executors.
42///
43/// See [module](index.html) level documentation for more details.
44///
45/// # Examples
46///
47/// ```
48/// # use tokio_timer::clock;
49/// let now = clock::now();
50/// ```
51pub fn now() -> Instant {
52    CLOCK.with(|current| match current.borrow().as_ref() {
53        Some(c) => c.now(),
54        None => Instant::now(),
55    })
56}
57
58impl Clock {
59    /// Return a new `Clock` instance that uses the current execution context's
60    /// source of time.
61    pub fn new() -> Clock {
62        CLOCK.with(|current| match current.borrow().as_ref() {
63            Some(c) => c.clone(),
64            None => Clock::system(),
65        })
66    }
67
68    /// Return a new `Clock` instance that uses `now` as the source of time.
69    pub fn new_with_now<T: Now>(now: T) -> Clock {
70        Clock {
71            now: Some(Arc::new(now)),
72        }
73    }
74
75    /// Return a new `Clock` instance that uses [`Instant::now`] as the source
76    /// of time.
77    ///
78    /// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
79    pub fn system() -> Clock {
80        Clock { now: None }
81    }
82
83    /// Returns an instant corresponding to "now" by using the instance's source
84    /// of time.
85    pub fn now(&self) -> Instant {
86        match self.now {
87            Some(ref now) => now.now(),
88            None => Instant::now(),
89        }
90    }
91}
92
93#[allow(deprecated)]
94impl timer::Now for Clock {
95    fn now(&mut self) -> Instant {
96        Clock::now(self)
97    }
98}
99
100impl fmt::Debug for Clock {
101    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
102        fmt.debug_struct("Clock")
103            .field("now", {
104                if self.now.is_some() {
105                    &"Some(Arc<Now>)"
106                } else {
107                    &"None"
108                }
109            })
110            .finish()
111    }
112}
113
114/// Set the default clock for the duration of the closure.
115///
116/// # Panics
117///
118/// This function panics if there already is a default clock set.
119pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R
120where
121    F: FnOnce(&mut Enter) -> R,
122{
123    let _guard = set_default(clock);
124
125    f(enter)
126}
127
128/// Sets `clock` as the default clock, returning a guard that unsets it on drop.
129///
130/// # Panics
131///
132/// This function panics if there already is a default clock set.
133pub fn set_default(clock: &Clock) -> DefaultGuard {
134    CLOCK.with(|cell| {
135        assert!(
136            cell.borrow().is_none(),
137            "default clock already set for execution context"
138        );
139
140        *cell.borrow_mut() = Some(clock.clone());
141
142        DefaultGuard { _p: () }
143    })
144}
145
146impl Drop for DefaultGuard {
147    fn drop(&mut self) {
148        let _ = CLOCK.try_with(|cell| cell.borrow_mut().take());
149    }
150}