turn/client/
periodic_timer.rs1#[cfg(test)]
2mod periodic_timer_test;
3
4use std::sync::Arc;
5
6use async_trait::async_trait;
7use tokio::sync::{mpsc, Mutex};
8use tokio::time::Duration;
9
10#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
11pub enum TimerIdRefresh {
12 #[default]
13 Alloc,
14 Perms,
15}
16
17#[async_trait]
19pub trait PeriodicTimerTimeoutHandler {
20 async fn on_timeout(&mut self, id: TimerIdRefresh);
21}
22
23#[derive(Default)]
25pub struct PeriodicTimer {
26 id: TimerIdRefresh,
27 interval: Duration,
28 close_tx: Mutex<Option<mpsc::Sender<()>>>,
29}
30
31impl PeriodicTimer {
32 pub fn new(id: TimerIdRefresh, interval: Duration) -> Self {
34 PeriodicTimer {
35 id,
36 interval,
37 close_tx: Mutex::new(None),
38 }
39 }
40
41 pub async fn start<T: 'static + PeriodicTimerTimeoutHandler + std::marker::Send>(
43 &self,
44 timeout_handler: Arc<Mutex<T>>,
45 ) -> bool {
46 {
48 let close_tx = self.close_tx.lock().await;
49 if close_tx.is_some() {
50 return false;
51 }
52 }
53
54 let (close_tx, mut close_rx) = mpsc::channel(1);
55 let interval = self.interval;
56 let id = self.id;
57
58 tokio::spawn(async move {
59 loop {
60 let timer = tokio::time::sleep(interval);
61 tokio::pin!(timer);
62
63 tokio::select! {
64 _ = timer.as_mut() => {
65 let mut handler = timeout_handler.lock().await;
66 handler.on_timeout(id).await;
67 }
68 _ = close_rx.recv() => break,
69 }
70 }
71 });
72
73 {
74 let mut close = self.close_tx.lock().await;
75 *close = Some(close_tx);
76 }
77
78 true
79 }
80
81 pub async fn stop(&self) {
83 let mut close_tx = self.close_tx.lock().await;
84 close_tx.take();
85 }
86
87 pub async fn is_running(&self) -> bool {
90 let close_tx = self.close_tx.lock().await;
91 close_tx.is_some()
92 }
93}