tokio_timer/timer/handle.rs
1use timer::Inner;
2use {Deadline, Delay, Error, Interval, Timeout};
3
4use tokio_executor::Enter;
5
6use std::cell::RefCell;
7use std::fmt;
8use std::sync::{Arc, Weak};
9use 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)]
37pub struct Handle {
38 inner: Option<HandlePriv>,
39}
40
41/// Like `Handle` but never `None`.
42#[derive(Clone)]
43pub(crate) struct HandlePriv {
44 inner: Weak<Inner>,
45}
46
47/// A guard that resets the current timer to `None` when dropped.
48#[derive(Debug)]
49pub struct DefaultGuard {
50 _p: (),
51}
52
53thread_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
69pub fn with_default<F, R>(handle: &Handle, enter: &mut Enter, f: F) -> R
70where
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.
82pub 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
101impl Handle {
102 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]: #
121 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`.
131 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")]
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`.
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.
151 pub fn interval(&self, at: Instant, duration: Duration) -> Interval {
152 Interval::new_with_delay(self.delay(at), duration)
153 }
154
155 fn as_priv(&self) -> Option<&HandlePriv> {
156 self.inner.as_ref()
157 }
158}
159
160impl Default for Handle {
161 fn default() -> Handle {
162 Handle { inner: None }
163 }
164}
165
166impl HandlePriv {
167 /// Try to get a handle to the current timer.
168 ///
169 /// Returns `Err` if no handle is found.
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
178 pub(crate) fn inner(&self) -> Option<Arc<Inner>> {
179 self.inner.upgrade()
180 }
181
182 /// Consume the handle, returning the weak Inner ref.
183 pub(crate) fn into_inner(self) -> Weak<Inner> {
184 self.inner
185 }
186}
187
188impl fmt::Debug for HandlePriv {
189 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190 write!(f, "HandlePriv")
191 }
192}
193
194impl Drop for DefaultGuard {
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}