1 use clock::Now;
2 use timer;
3 
4 use tokio_executor::Enter;
5 
6 use std::cell::Cell;
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<Now>>,
21 }
22 
23 thread_local! {
24     /// Thread-local tracking the current clock
25     static CLOCK: Cell<Option<*const Clock>> = Cell::new(None)
26 }
27 
28 /// Returns an `Instant` corresponding to "now".
29 ///
30 /// This function delegates to the source of time configured for the current
31 /// execution context. By default, this is `Instant::now()`.
32 ///
33 /// Note that, because the source of time is configurable, it is possible to
34 /// observe non-monotonic behavior when calling `now` from different
35 /// executors.
36 ///
37 /// See [module](index.html) level documentation for more details.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// # use tokio_timer::clock;
43 /// let now = clock::now();
44 /// ```
now() -> Instant45 pub fn now() -> Instant {
46     CLOCK.with(|current| match current.get() {
47         Some(ptr) => unsafe { (*ptr).now() },
48         None => Instant::now(),
49     })
50 }
51 
52 impl Clock {
53     /// Return a new `Clock` instance that uses the current execution context's
54     /// source of time.
new() -> Clock55     pub fn new() -> Clock {
56         CLOCK.with(|current| match current.get() {
57             Some(ptr) => unsafe { (*ptr).clone() },
58             None => Clock::system(),
59         })
60     }
61 
62     /// Return a new `Clock` instance that uses `now` as the source of time.
new_with_now<T: Now>(now: T) -> Clock63     pub fn new_with_now<T: Now>(now: T) -> Clock {
64         Clock {
65             now: Some(Arc::new(now)),
66         }
67     }
68 
69     /// Return a new `Clock` instance that uses [`Instant::now`] as the source
70     /// of time.
71     ///
72     /// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
system() -> Clock73     pub fn system() -> Clock {
74         Clock { now: None }
75     }
76 
77     /// Returns an instant corresponding to "now" by using the instance's source
78     /// of time.
now(&self) -> Instant79     pub fn now(&self) -> Instant {
80         match self.now {
81             Some(ref now) => now.now(),
82             None => Instant::now(),
83         }
84     }
85 }
86 
87 #[allow(deprecated)]
88 impl timer::Now for Clock {
now(&mut self) -> Instant89     fn now(&mut self) -> Instant {
90         Clock::now(self)
91     }
92 }
93 
94 impl fmt::Debug for Clock {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result95     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
96         fmt.debug_struct("Clock")
97             .field("now", {
98                 if self.now.is_some() {
99                     &"Some(Arc<Now>)"
100                 } else {
101                     &"None"
102                 }
103             })
104             .finish()
105     }
106 }
107 
108 /// Set the default clock for the duration of the closure.
109 ///
110 /// # Panics
111 ///
112 /// 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,113 pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R
114 where
115     F: FnOnce(&mut Enter) -> R,
116 {
117     CLOCK.with(|cell| {
118         assert!(
119             cell.get().is_none(),
120             "default clock already set for execution context"
121         );
122 
123         // Ensure that the clock is removed from the thread-local context
124         // when leaving the scope. This handles cases that involve panicking.
125         struct Reset<'a>(&'a Cell<Option<*const Clock>>);
126 
127         impl<'a> Drop for Reset<'a> {
128             fn drop(&mut self) {
129                 self.0.set(None);
130             }
131         }
132 
133         let _reset = Reset(cell);
134 
135         cell.set(Some(clock as *const Clock));
136 
137         f(enter)
138     })
139 }
140