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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::thread;
use std::time::Duration;
use std::time::SystemTime;
use std::sync::{Arc,Mutex};

///将一个需要执行的函数当作闭包传递到子线程中循环执行,
/// 
/// Pass a function that needs to be executed as a closure to a child thread for loop execution,
///
/// 循环的同时有一个时间循环的线程配套,
/// 
/// At the same time as the loop, there is a time loop thread matching,
/// 
/// 需要执行的函数每执行一次,会更新一次执行时间
/// 
/// The execution time of the function that needs to be executed is updated every time it is executed
/// 
/// 时间循环函数一次sleep时间为time_check,执行时间距离上次执行时间大于四倍time_check则退出循环 
/// 
/// The time loop function has a sleep time of time_ Check, the execution time is greater than four times the last execution time_ Check to exit the loop
/// 
/// 注意如果执行的函数中有阻塞(例如io输入),会发生时间循环子线程退出,函数执行循环子线程一直在等待直到有IO输入或者main函数退出 
/// 
/// Note that if there is a block in the executed function (such as IO input), a time loop sub thread will exit, and the function execution loop sub thread will wait until there is IO input or the main function exits
/// # Example
/// 
/// ```
/// use std::thread;
/// use std::time::Duration;
/// //需要循环一次的函数
/// //Functions that need to be iterated once
///fn text_fn(i:u64) {
///    let mut buffer = String::new();
///    std::io::stdin().read_line(&mut buffer).unwrap();
///    println!("text is {}",buffer);
///    thread::sleep(Duration::from_secs(i));
///    }
///fn main() {   
///    let time_check = 5;//单位为秒  Unit in seconds
///      thread::spawn ( 
///         move|| {
///              time_check_loop::loop_time_check(move || {text_fn(1);},time_check); 
///         }
///     );
///     loop{
///     thread::sleep(Duration::new(5,0));
///     };
///}
///```
pub fn loop_time_check<F>(job:F,time_check:u64) 
    
    where
    F:FnOnce() + Send + 'static+ Copy,
    {
    let time_loop = time_check; //设置循环检测时间 Set cycle detection time
    let send_time = 2*time_loop;  //设置心跳时间(暂时没用的),本来是给物联网这类留的,为了模块化删除了物联网部分 Setting the heartbeat time (temporarily useless) was originally reserved for the Internet of Things, but the IoT section was removed for modularity
    let exit_time = 4*time_loop; //设置超时时间 Set timeout time

    let time_first = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

    let time_out = Arc::new(Mutex::new(time_first));
    let time_in = Arc::clone(&time_out);

    let (tx, rx) = std::sync::mpsc::channel();
    let time_in = time_in.clone();
    thread::spawn(move || {
        loop{
            job();
            let in_now_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
            //向外部传递了时间
            *time_in.lock().unwrap()= in_now_time;
            match rx.try_recv() {
                Ok(some) => {
                    match some {
                        "exit" => {
                            eprintln!("the action thread receive meg {})",some);
                            break;
                        }
                        "are you here" => {
                            eprintln!("the action thread receive meg {}",some);
                            //心跳处理
                        }
                        _ => {
                            eprintln!("the action thread receive meg {} is unknow)",some);
                            break;
                        }
                    }
                }
                Err(_err) => {
                    eprintln!("the action thread haven't receive meg still run)");
                }
            }
        }
    });
    eprintln!("start time loop");
    loop {
        let out_now_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
        let dif_time = out_now_time - *time_out.lock().unwrap();
        println!("time loop differences time is {} ", dif_time.as_secs());
        
        //大于超时时间就退出,大于心跳时间发送心跳 Set the timeout time to exit if it is greater than the timeout time, and send a heartbeat if it is greater than the heartbeat time
        if dif_time.as_secs() > send_time {
            if dif_time.as_secs() > exit_time {
                tx.send("exit").unwrap();
                eprintln!("time loop exit");
                break
            }
            //If there is no corresponding heartbeat processing set, there is no need to send meg (after sending meg, the execution function can only consume one meg every time it executes a loop)
            //没有设置相应心跳处理,就不用send meg (send meg后执行函数每执行一次循环,才能消费一个meg)
            //tx.send("are you here").unwrap(); 
            eprintln!("time loop send meg");
        }
        thread::sleep(Duration::from_secs(time_loop));
    }
}