1 use timer::Inner;
2 use {Deadline, Delay, Error, Interval, Timeout};
3 
4 use tokio_executor::Enter;
5 
6 use std::cell::RefCell;
7 use std::fmt;
8 use std::sync::{Arc, Weak};
9 use std::time::{Duration, Instant};
10 
11 /// Handle to timer instance.
12 ///
13 /// The `Handle` allows creating `Delay` instances that are driven by the
14 /// associated timer.
15 ///
16 /// A `Handle` is obtained by calling [`Timer::handle`], [`Handle::current`], or
17 /// [`Handle::default`].
18 ///
19 /// * [`Timer::handle`]: returns a handle associated with the specific timer.
20 ///   The handle will always reference the same timer.
21 ///
22 /// * [`Handle::current`]: returns a handle to the timer for the execution
23 ///   context **at the time the function is called**. This function must be
24 ///   called from a runtime that has an associated timer or it will panic.
25 ///   The handle will always reference the same timer.
26 ///
27 /// * [`Handle::default`]: returns a handle to the timer for the execution
28 ///   context **at the time the handle is used**. This function is safe to call
29 ///   at any time. The handle may reference different specific timer instances.
30 ///   Calling `Handle::default().delay(...)` is always equivalent to
31 ///   `Delay::new(...)`.
32 ///
33 /// [`Timer::handle`]: struct.Timer.html#method.handle
34 /// [`Handle::current`]: #method.current
35 /// [`Handle::default`]: #method.default
36 #[derive(Debug, Clone)]
37 pub struct Handle {
38     inner: Option<HandlePriv>,
39 }
40 
41 /// Like `Handle` but never `None`.
42 #[derive(Clone)]
43 pub(crate) struct HandlePriv {
44     inner: Weak<Inner>,
45 }
46 
47 /// A guard that resets the current timer to `None` when dropped.
48 #[derive(Debug)]
49 pub struct DefaultGuard {
50     _p: (),
51 }
52 
53 thread_local! {
54     /// Tracks the timer for the current execution context.
55     static CURRENT_TIMER: RefCell<Option<HandlePriv>> = RefCell::new(None)
56 }
57 
58 /// Set the default timer for the duration of the closure.
59 ///
60 /// From within the closure, [`Delay`] instances that are created via
61 /// [`Delay::new`] can be used.
62 ///
63 /// # Panics
64 ///
65 /// This function panics if there already is a default timer set.
66 ///
67 /// [`Delay`]: ../struct.Delay.html
68 /// [`Delay::new`]: ../struct.Delay.html#method.new
with_default<F, R>(handle: &Handle, enter: &mut Enter, f: F) -> R where F: FnOnce(&mut Enter) -> R,69 pub fn with_default<F, R>(handle: &Handle, enter: &mut Enter, f: F) -> R
70 where
71     F: FnOnce(&mut Enter) -> R,
72 {
73     let _guard = set_default(handle);
74     f(enter)
75 }
76 
77 /// Sets `handle` as the default timer, returning a guard that unsets it on drop.
78 ///
79 /// # Panics
80 ///
81 /// This function panics if there already is a default timer set.
set_default(handle: &Handle) -> DefaultGuard82 pub fn set_default(handle: &Handle) -> DefaultGuard {
83     CURRENT_TIMER.with(|current| {
84         let mut current = current.borrow_mut();
85 
86         assert!(
87             current.is_none(),
88             "default Tokio timer already set \
89              for execution context"
90         );
91 
92         let handle = handle
93             .as_priv()
94             .unwrap_or_else(|| panic!("`handle` does not reference a timer"));
95 
96         *current = Some(handle.clone());
97     });
98     DefaultGuard { _p: () }
99 }
100 
101 impl Handle {
new(inner: Weak<Inner>) -> Handle102     pub(crate) fn new(inner: Weak<Inner>) -> Handle {
103         let inner = HandlePriv { inner };
104         Handle { inner: Some(inner) }
105     }
106 
107     /// Returns a handle to the current timer.
108     ///
109     /// The current timer is the timer that is currently set as default using
110     /// [`with_default`].
111     ///
112     /// This function should only be called from within the context of
113     /// [`with_default`]. Calling this function from outside of this context
114     /// will return a `Handle` that does not reference a timer. `Delay`
115     /// instances created with this handle will error.
116     ///
117     /// See [type] level documentation for more ways to obtain a `Handle` value.
118     ///
119     /// [`with_default`]: ../fn.with_default.html
120     /// [type]: #
current() -> Handle121     pub fn current() -> Handle {
122         let private =
123             HandlePriv::try_current().unwrap_or_else(|_| HandlePriv { inner: Weak::new() });
124 
125         Handle {
126             inner: Some(private),
127         }
128     }
129 
130     /// Create a `Delay` driven by this handle's associated `Timer`.
delay(&self, deadline: Instant) -> Delay131     pub fn delay(&self, deadline: Instant) -> Delay {
132         match self.inner {
133             Some(ref handle_priv) => Delay::new_with_handle(deadline, handle_priv.clone()),
134             None => Delay::new(deadline),
135         }
136     }
137 
138     #[doc(hidden)]
139     #[deprecated(since = "0.2.11", note = "use timeout instead")]
deadline<T>(&self, future: T, deadline: Instant) -> Deadline<T>140     pub fn deadline<T>(&self, future: T, deadline: Instant) -> Deadline<T> {
141         Deadline::new_with_delay(future, self.delay(deadline))
142     }
143 
144     /// Create a `Timeout` driven by this handle's associated `Timer`.
timeout<T>(&self, value: T, deadline: Instant) -> Timeout<T>145     pub fn timeout<T>(&self, value: T, deadline: Instant) -> Timeout<T> {
146         Timeout::new_with_delay(value, self.delay(deadline))
147     }
148 
149     /// Create a new `Interval` that starts at `at` and yields every `duration`
150     /// interval after that.
interval(&self, at: Instant, duration: Duration) -> Interval151     pub fn interval(&self, at: Instant, duration: Duration) -> Interval {
152         Interval::new_with_delay(self.delay(at), duration)
153     }
154 
as_priv(&self) -> Option<&HandlePriv>155     fn as_priv(&self) -> Option<&HandlePriv> {
156         self.inner.as_ref()
157     }
158 }
159 
160 impl Default for Handle {
default() -> Handle161     fn default() -> Handle {
162         Handle { inner: None }
163     }
164 }
165 
166 impl HandlePriv {
167     /// Try to get a handle to the current timer.
168     ///
169     /// Returns `Err` if no handle is found.
try_current() -> Result<HandlePriv, Error>170     pub(crate) fn try_current() -> Result<HandlePriv, Error> {
171         CURRENT_TIMER.with(|current| match *current.borrow() {
172             Some(ref handle) => Ok(handle.clone()),
173             None => Err(Error::shutdown()),
174         })
175     }
176 
177     /// Try to return a strong ref to the inner
inner(&self) -> Option<Arc<Inner>>178     pub(crate) fn inner(&self) -> Option<Arc<Inner>> {
179         self.inner.upgrade()
180     }
181 
182     /// Consume the handle, returning the weak Inner ref.
into_inner(self) -> Weak<Inner>183     pub(crate) fn into_inner(self) -> Weak<Inner> {
184         self.inner
185     }
186 }
187 
188 impl fmt::Debug for HandlePriv {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result189     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190         write!(f, "HandlePriv")
191     }
192 }
193 
194 impl Drop for DefaultGuard {
drop(&mut self)195     fn drop(&mut self) {
196         let _ = CURRENT_TIMER.try_with(|current| {
197             let mut current = current.borrow_mut();
198             *current = None;
199         });
200     }
201 }
202