dprint 0.14.0

Binary for dprint code formatter—a pluggable and configurable code formatting platform.
use super::ManualResetEvent;
use std::time::Duration;

/// Provides a way to signal to a thread that it should exit
/// along with providing a way for the thread to sleep and be
/// signaled for exit while sleeping.
pub struct ThreadExitSignal {
    is_complete: ManualResetEvent,
}

impl ThreadExitSignal {
    pub fn new() -> Self {
        ThreadExitSignal {
            is_complete: ManualResetEvent::new(false),
        }
    }

    /// Sleeps the thread, exiting when the signal is given or the duration has passed.
    ///
    /// Returns `true` when it has slept for the duration of the timeout.
    pub fn sleep_with_cancellation(&self, duration: Duration) -> bool {
        !self.is_complete.wait_with_timeout(duration)
    }

    /// Signal that the thread should exit.
    pub fn signal_exit(&self) {
        self.is_complete.set();
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::ManualResetEvent;
    use std::sync::Arc;
    use std::time::Duration;

    #[test]
    fn it_should_signal_a_thread_to_stop_sleeping() {
        let exit_signal = Arc::new(ThreadExitSignal::new());
        let has_thread_exited = Arc::new(ManualResetEvent::new(false));

        // should sleep and not be cancelled
        assert_eq!(exit_signal.sleep_with_cancellation(Duration::from_millis(1)), true);

        std::thread::spawn({
            let exit_signal = exit_signal.clone();
            let has_thread_exited = has_thread_exited.clone();
            move || {
                assert_eq!(exit_signal.sleep_with_cancellation(Duration::from_secs(5)), false);
                has_thread_exited.set();
            }
        });

        // give the thread some time to start
        std::thread::sleep(Duration::from_millis(100));

        // now tell it to exit
        exit_signal.signal_exit();

        // ensure the thread exits before the timeout
        assert_eq!(has_thread_exited.wait_with_timeout(Duration::from_secs(5)), true);
    }
}