1
//!
2
//! A utility function to easily print progress information for procedures that
3
//! take a fixed number of steps. In particular, avoids writing too many
4
//! progress indications.
5
//!
6

            
7
use std::cell::RefCell;
8
use std::marker::PhantomData;
9
use std::time::Duration;
10
use std::time::Instant;
11

            
12
/// A time-based progress tracker that prints messages at regular intervals.
13
pub struct TimeProgress<T> {
14
    interval: Duration,
15
    last_update: RefCell<Instant>,
16
    message: Box<dyn Fn(T)>,
17
    _marker: PhantomData<T>,
18
}
19

            
20
impl<T> TimeProgress<T> {
21
    /// Create a new time-based progress tracker with a given interval in seconds.
22
1511
    pub fn new(message: impl Fn(T) + 'static, interval_seconds: u64) -> TimeProgress<T> {
23
1511
        TimeProgress {
24
1511
            message: Box::new(message),
25
1511
            interval: Duration::from_secs(interval_seconds),
26
1511
            last_update: RefCell::new(Instant::now()),
27
1511
            _marker: PhantomData,
28
1511
        }
29
1511
    }
30

            
31
    /// Increase the progress with the given amount, prints periodic progress
32
    /// messages based on time intervals.
33
429941
    pub fn print(&self, object: T) {
34
429941
        let now = Instant::now();
35
429941
        let should_print = {
36
429941
            let last = *self.last_update.borrow();
37
429941
            now.duration_since(last) >= self.interval
38
        };
39
429941
        if should_print {
40
            (self.message)(object);
41
            *self.last_update.borrow_mut() = now;
42
429941
        }
43
429941
    }
44
}