suiron/
time_out.rs

1//! Functions for limiting execution time.
2//!
3//! This module contains a global variable, SUIRON_STOP_QUERY,
4//! and therefore has 'unsafe' code.
5
6use std::time::Duration;
7use thread_timer::ThreadTimer;
8
9use super::logic_var::*;
10
11static mut SUIRON_STOP_QUERY: bool = false;
12
13/// Create a timer with a timeout in milliseconds.
14///
15/// When the timer times out, it sets the SUIRON_STOP_QUERY
16/// flag to true, effectively halting a query.
17///
18/// # Arguments
19/// * timeout in milliseconds
20/// # Return
21/// * ThreadTimer
22/// # Usage
23/// ```
24/// use suiron::*;
25///
26/// let timer = start_query_timer(300);
27/// ```
28pub fn start_query_timer(milliseconds: u64) -> ThreadTimer {
29    unsafe { SUIRON_STOP_QUERY = false; }
30    let timer = ThreadTimer::new();
31    timer.start(Duration::from_millis(milliseconds),
32                move || { stop_query(); }).unwrap();
33    return timer;
34} // start_query_timer()
35
36/// Cancels query timer. Ignores any issues.
37///
38/// # Argument
39/// * ThreadTimer
40/// # Usage
41/// ```
42/// use suiron::*;
43///
44/// let timer = start_query_timer(30);
45/// cancel_timer(timer);
46/// ```
47pub fn cancel_timer(timer: ThreadTimer) {
48    match timer.cancel() {
49        Ok(_) => {},
50        Err(_) => {},
51    }
52} // cancel_timer()
53
54/// Sets the SUIRON_STOP_QUERY flag to false and LOGIC_VAR_ID to 0.
55///
56/// The SUIRON_STOP_QUERY is checked in count_rules(), in knowledgebase.rs.
57/// Setting it true effectively stops the search for a solution.
58///
59/// In order to keep the substitution set small, the LOGIC_VAR_ID is
60/// reset to 0 at the start of every query.
61pub fn start_query() {
62    unsafe { SUIRON_STOP_QUERY = false; }
63    clear_id();
64}
65
66/// Sets the SUIRON_STOP_QUERY flag to true.
67///
68/// The SUIRON_STOP_QUERY is checked in count_rules(), in knowledgebase.rs.
69/// Setting it `true` effectively stops the search for a solution.
70pub fn stop_query() {
71    unsafe { SUIRON_STOP_QUERY = true; }
72}
73
74/// Returns value of SUIRON_STOP_QUERY.
75///
76/// If the SUIRON_STOP_QUERY is true, it means that the query timed out.
77/// # Return
78/// * true/false
79pub fn query_stopped() -> bool {
80    unsafe { SUIRON_STOP_QUERY }
81}
82
83#[cfg(test)]
84mod test {
85
86    use super::*;
87    use std::thread;
88    use std::time::Duration;
89    use serial_test::serial;
90
91    // Test timer.
92    // The function sleeps for 40 milliseconds, but the
93    // timer times out after 30 milliseconds.
94    #[test]
95    #[serial]
96    fn test_query_timer() {
97        let timer = start_query_timer(30);
98        let flag = query_stopped();
99        assert_eq!(false, flag, "SUIRON_STOP_QUERY should be false.");
100        let delay = Duration::from_millis(40);
101        thread::sleep(delay); // Rust does sleep, Neil Young.
102        cancel_timer(timer);
103        let flag = query_stopped();
104        assert_eq!(true, flag, "SUIRON_STOP_QUERY should be true.");
105    } // test_query_timer()
106
107} // test