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 thread_local! {
48 /// Tracks the timer for the current execution context.
49 static CURRENT_TIMER: RefCell<Option<HandlePriv>> = RefCell::new(None)
50 }
51
52 /// Set the default timer for the duration of the closure.
53 ///
54 /// From within the closure, [`Delay`] instances that are created via
55 /// [`Delay::new`] can be used.
56 ///
57 /// # Panics
58 ///
59 /// This function panics if there already is a default timer set.
60 ///
61 /// [`Delay`]: ../struct.Delay.html
62 /// [`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,63 pub fn with_default<F, R>(handle: &Handle, enter: &mut Enter, f: F) -> R
64 where
65 F: FnOnce(&mut Enter) -> R,
66 {
67 // Ensure that the timer is removed from the thread-local context
68 // when leaving the scope. This handles cases that involve panicking.
69 struct Reset;
70
71 impl Drop for Reset {
72 fn drop(&mut self) {
73 CURRENT_TIMER.with(|current| {
74 let mut current = current.borrow_mut();
75 *current = None;
76 });
77 }
78 }
79
80 // This ensures the value for the current timer gets reset even if there is
81 // a panic.
82 let _r = Reset;
83
84 CURRENT_TIMER.with(|current| {
85 {
86 let mut current = current.borrow_mut();
87
88 assert!(
89 current.is_none(),
90 "default Tokio timer already set \
91 for execution context"
92 );
93
94 let handle = handle
95 .as_priv()
96 .unwrap_or_else(|| panic!("`handle` does not reference a timer"));
97
98 *current = Some(handle.clone());
99 }
100
101 f(enter)
102 })
103 }
104
105 impl Handle {
new(inner: Weak<Inner>) -> Handle106 pub(crate) fn new(inner: Weak<Inner>) -> Handle {
107 let inner = HandlePriv { inner };
108 Handle { inner: Some(inner) }
109 }
110
111 /// Returns a handle to the current timer.
112 ///
113 /// The current timer is the timer that is currently set as default using
114 /// [`with_default`].
115 ///
116 /// This function should only be called from within the context of
117 /// [`with_default`]. Calling this function from outside of this context
118 /// will return a `Handle` that does not reference a timer. `Delay`
119 /// instances created with this handle will error.
120 ///
121 /// See [type] level documentation for more ways to obtain a `Handle` value.
122 ///
123 /// [`with_default`]: ../fn.with_default.html
124 /// [type]: #
current() -> Handle125 pub fn current() -> Handle {
126 let private =
127 HandlePriv::try_current().unwrap_or_else(|_| HandlePriv { inner: Weak::new() });
128
129 Handle {
130 inner: Some(private),
131 }
132 }
133
134 /// Create a `Delay` driven by this handle's associated `Timer`.
delay(&self, deadline: Instant) -> Delay135 pub fn delay(&self, deadline: Instant) -> Delay {
136 match self.inner {
137 Some(ref handle_priv) => Delay::new_with_handle(deadline, handle_priv.clone()),
138 None => Delay::new(deadline),
139 }
140 }
141
142 #[doc(hidden)]
143 #[deprecated(since = "0.2.11", note = "use timeout instead")]
deadline<T>(&self, future: T, deadline: Instant) -> Deadline<T>144 pub fn deadline<T>(&self, future: T, deadline: Instant) -> Deadline<T> {
145 Deadline::new_with_delay(future, self.delay(deadline))
146 }
147
148 /// Create a `Timeout` driven by this handle's associated `Timer`.
timeout<T>(&self, value: T, deadline: Instant) -> Timeout<T>149 pub fn timeout<T>(&self, value: T, deadline: Instant) -> Timeout<T> {
150 Timeout::new_with_delay(value, self.delay(deadline))
151 }
152
153 /// Create a new `Interval` that starts at `at` and yields every `duration`
154 /// interval after that.
interval(&self, at: Instant, duration: Duration) -> Interval155 pub fn interval(&self, at: Instant, duration: Duration) -> Interval {
156 Interval::new_with_delay(self.delay(at), duration)
157 }
158
as_priv(&self) -> Option<&HandlePriv>159 fn as_priv(&self) -> Option<&HandlePriv> {
160 self.inner.as_ref()
161 }
162 }
163
164 impl Default for Handle {
default() -> Handle165 fn default() -> Handle {
166 Handle { inner: None }
167 }
168 }
169
170 impl HandlePriv {
171 /// Try to get a handle to the current timer.
172 ///
173 /// Returns `Err` if no handle is found.
try_current() -> Result<HandlePriv, Error>174 pub(crate) fn try_current() -> Result<HandlePriv, Error> {
175 CURRENT_TIMER.with(|current| match *current.borrow() {
176 Some(ref handle) => Ok(handle.clone()),
177 None => Err(Error::shutdown()),
178 })
179 }
180
181 /// Try to return a strong ref to the inner
inner(&self) -> Option<Arc<Inner>>182 pub(crate) fn inner(&self) -> Option<Arc<Inner>> {
183 self.inner.upgrade()
184 }
185
186 /// Consume the handle, returning the weak Inner ref.
into_inner(self) -> Weak<Inner>187 pub(crate) fn into_inner(self) -> Weak<Inner> {
188 self.inner
189 }
190 }
191
192 impl fmt::Debug for HandlePriv {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result193 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 write!(f, "HandlePriv")
195 }
196 }
197