1 use clock::Now;
2 use timer;
3 
4 use tokio_executor::Enter;
5 
6 use std::cell::RefCell;
7 use std::fmt;
8 use std::sync::Arc;
9 use 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)]
19 pub 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)]
25 pub struct DefaultGuard {
26     _p: (),
27 }
28 
29 thread_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 /// ```
now() -> Instant51 pub fn now() -> Instant {
52     CLOCK.with(|current| match current.borrow().as_ref() {
53         Some(c) => c.now(),
54         None => Instant::now(),
55     })
56 }
57 
58 impl Clock {
59     /// Return a new `Clock` instance that uses the current execution context's
60     /// source of time.
new() -> Clock61     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.
new_with_now<T: Now>(now: T) -> Clock69     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
system() -> Clock79     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.
now(&self) -> Instant85     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)]
94 impl timer::Now for Clock {
now(&mut self) -> Instant95     fn now(&mut self) -> Instant {
96         Clock::now(self)
97     }
98 }
99 
100 impl fmt::Debug for Clock {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result101     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.
with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R where F: FnOnce(&mut Enter) -> R,119 pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R
120 where
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.
set_default(clock: &Clock) -> DefaultGuard133 pub 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 
146 impl Drop for DefaultGuard {
drop(&mut self)147     fn drop(&mut self) {
148         let _ = CLOCK.try_with(|cell| cell.borrow_mut().take());
149     }
150 }
151