     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83

    use crate::loom::sync::{Arc, Mutex};
    use crate::time::driver::ClockTime;
    use std::fmt;

    /// Handle to time driver instance.
    #[derive(Clone)]
    pub(crate) struct Handle {
        time_source: ClockTime,
        inner: Arc<Mutex<super::Inner>>,
    }

    impl Handle {
        /// Creates a new timer `Handle` from a shared `Inner` timer state.
        pub(super) fn new(inner: Arc<Mutex<super::Inner>>) -> Self {
            let time_source = inner.lock().time_source.clone();
            Handle { time_source, inner }
        }

        /// Returns the time source associated with this handle
        pub(super) fn time_source(&self) -> &ClockTime {
            &self.time_source
        }

        /// Locks the driver's inner structure
        pub(super) fn lock(&self) -> crate::loom::sync::MutexGuard<'_, super::Inner> {
            self.inner.lock()
        }
    }

    cfg_rt! {
        impl Handle {
            /// Tries to get a handle to the current timer.
            ///
            /// # Panics
            ///
            /// This function panics if there is no current timer set.
            ///
            /// It can be triggered when `Builder::enable_time()` or
            /// `Builder::enable_all()` are not included in the builder.
            ///
            /// It can also panic whenever a timer is created outside of a
            /// Tokio runtime. That is why `rt.block_on(delay_for(...))` will panic,
            /// since the function is executed outside of the runtime.
            /// Whereas `rt.block_on(async {delay_for(...).await})` doesn't panic.
            /// And this is because wrapping the function on an async makes it lazy,
            /// and so gets executed inside the runtime successfuly without
            /// panicking.
            pub(crate) fn current() -> Self {
                crate::runtime::context::time_handle()
                    .expect("A Tokio 1.x context was found, but timers are disabled. Call `enable_time` on the runtime builder to enable timers.")
            }
        }
    }

    cfg_not_rt! {
        impl Handle {
            /// Tries to get a handle to the current timer.
            ///
            /// # Panics
            ///
            /// This function panics if there is no current timer set.
            ///
            /// It can be triggered when `Builder::enable_time()` or
            /// `Builder::enable_all()` are not included in the builder.
            ///
            /// It can also panic whenever a timer is created outside of a Tokio
            /// runtime. That is why `rt.block_on(delay_for(...))` will panic,
            /// since the function is executed outside of the runtime.
            /// Whereas `rt.block_on(async {delay_for(...).await})` doesn't
            /// panic. And this is because wrapping the function on an async makes it
            /// lazy, and so outside executed inside the runtime successfuly without
            /// panicking.
            pub(crate) fn current() -> Self {
                panic!(crate::util::error::CONTEXT_MISSING_ERROR)
            }
        }
    }

    impl fmt::Debug for Handle {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(f, "Handle")
        }
    }