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

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