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
2572
    pub fn new(message: impl Fn(T) + 'static, interval_seconds: u64) -> TimeProgress<T> {
23
2572
        TimeProgress {
24
2572
            message: Box::new(message),
25
2572
            interval: Duration::from_secs(interval_seconds),
26
2572
            last_update: RefCell::new(Instant::now()),
27
2572
            _marker: PhantomData,
28
2572
        }
29
2572
    }
30

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