use super::TimerSignal;
use crate::{utils::get_time_range, Result};
use std::{
sync::{
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
},
thread::{self, JoinHandle},
time::Duration,
};
const LOG_TAG: &str = "Pyroscope::Timer";
#[derive(Debug, Default)]
pub struct Timer {
txs: Arc<Mutex<Vec<Sender<TimerSignal>>>>,
pub handle: Option<JoinHandle<Result<()>>>,
}
impl Timer {
pub fn initialize(cycle: Duration) -> Result<Self> {
log::info!(target: LOG_TAG, "Initializing Timer");
let txs = Arc::new(Mutex::new(Vec::new()));
let (tx, _rx): (Sender<TimerSignal>, Receiver<TimerSignal>) = channel();
txs.lock()?.push(tx);
let handle = Some({
let txs = txs.clone();
thread::spawn(move || {
let rem = get_time_range(0)?.rem;
thread::sleep(Duration::from_secs(rem));
loop {
if txs.lock()?.len() == 0 {
log::info!(target: LOG_TAG, "Timer thread terminated");
return Ok(());
}
let from = TimerSignal::NextSnapshot(get_time_range(0)?.from);
log::trace!(target: LOG_TAG, "Timer fired @ {}", from);
txs.lock()?.iter().for_each(|tx| {
match tx.send(from) {
Ok(_) => {
log::trace!(target: LOG_TAG, "Sent event to listener @ {:?}", &tx)
}
Err(_e) => {} }
});
thread::sleep(cycle);
}
})
});
Ok(Self { handle, txs })
}
pub fn attach_listener(&mut self, tx: Sender<TimerSignal>) -> Result<()> {
let txs = Arc::clone(&self.txs);
txs.lock()?.push(tx);
Ok(())
}
pub fn drop_listeners(&mut self) -> Result<()> {
let txs = Arc::clone(&self.txs);
txs.lock()?.clear();
Ok(())
}
}