summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio-timer/src/clock/clock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/tokio-timer/src/clock/clock.rs')
-rw-r--r--third_party/rust/tokio-timer/src/clock/clock.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/third_party/rust/tokio-timer/src/clock/clock.rs b/third_party/rust/tokio-timer/src/clock/clock.rs
new file mode 100644
index 0000000000..9b9de89ef9
--- /dev/null
+++ b/third_party/rust/tokio-timer/src/clock/clock.rs
@@ -0,0 +1,139 @@
+use clock::Now;
+use timer;
+
+use tokio_executor::Enter;
+
+use std::cell::Cell;
+use std::fmt;
+use std::sync::Arc;
+use std::time::Instant;
+
+/// A handle to a source of time.
+///
+/// `Clock` instances return [`Instant`] values corresponding to "now". The source
+/// of these values is configurable. The default source is [`Instant::now`].
+///
+/// [`Instant`]: https://doc.rust-lang.org/std/time/struct.Instant.html
+/// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
+#[derive(Default, Clone)]
+pub struct Clock {
+ now: Option<Arc<Now>>,
+}
+
+thread_local! {
+ /// Thread-local tracking the current clock
+ static CLOCK: Cell<Option<*const Clock>> = Cell::new(None)
+}
+
+/// Returns an `Instant` corresponding to "now".
+///
+/// This function delegates to the source of time configured for the current
+/// execution context. By default, this is `Instant::now()`.
+///
+/// Note that, because the source of time is configurable, it is possible to
+/// observe non-monotonic behavior when calling `now` from different
+/// executors.
+///
+/// See [module](index.html) level documentation for more details.
+///
+/// # Examples
+///
+/// ```
+/// # use tokio_timer::clock;
+/// let now = clock::now();
+/// ```
+pub fn now() -> Instant {
+ CLOCK.with(|current| match current.get() {
+ Some(ptr) => unsafe { (*ptr).now() },
+ None => Instant::now(),
+ })
+}
+
+impl Clock {
+ /// Return a new `Clock` instance that uses the current execution context's
+ /// source of time.
+ pub fn new() -> Clock {
+ CLOCK.with(|current| match current.get() {
+ Some(ptr) => unsafe { (*ptr).clone() },
+ None => Clock::system(),
+ })
+ }
+
+ /// Return a new `Clock` instance that uses `now` as the source of time.
+ pub fn new_with_now<T: Now>(now: T) -> Clock {
+ Clock {
+ now: Some(Arc::new(now)),
+ }
+ }
+
+ /// Return a new `Clock` instance that uses [`Instant::now`] as the source
+ /// of time.
+ ///
+ /// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
+ pub fn system() -> Clock {
+ Clock { now: None }
+ }
+
+ /// Returns an instant corresponding to "now" by using the instance's source
+ /// of time.
+ pub fn now(&self) -> Instant {
+ match self.now {
+ Some(ref now) => now.now(),
+ None => Instant::now(),
+ }
+ }
+}
+
+#[allow(deprecated)]
+impl timer::Now for Clock {
+ fn now(&mut self) -> Instant {
+ Clock::now(self)
+ }
+}
+
+impl fmt::Debug for Clock {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Clock")
+ .field("now", {
+ if self.now.is_some() {
+ &"Some(Arc<Now>)"
+ } else {
+ &"None"
+ }
+ })
+ .finish()
+ }
+}
+
+/// Set the default clock for the duration of the closure.
+///
+/// # Panics
+///
+/// This function panics if there already is a default clock set.
+pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R
+where
+ F: FnOnce(&mut Enter) -> R,
+{
+ CLOCK.with(|cell| {
+ assert!(
+ cell.get().is_none(),
+ "default clock already set for execution context"
+ );
+
+ // Ensure that the clock is removed from the thread-local context
+ // when leaving the scope. This handles cases that involve panicking.
+ struct Reset<'a>(&'a Cell<Option<*const Clock>>);
+
+ impl<'a> Drop for Reset<'a> {
+ fn drop(&mut self) {
+ self.0.set(None);
+ }
+ }
+
+ let _reset = Reset(cell);
+
+ cell.set(Some(clock as *const Clock));
+
+ f(enter)
+ })
+}