use crate::{BufferGet, EventBuffer, MixedEventBuffer, State};
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::time::Duration;
pub struct EventDebouncer<T> {
mutex: Arc<Mutex<EventBuffer<T>>>,
thread: JoinHandle<()>,
}
fn spawn<B, F, T>(mutex: &Arc<Mutex<B>>, f: F) -> JoinHandle<()>
where
B: BufferGet<T> + Send + 'static,
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
let mutex = mutex.clone();
thread::spawn(move || loop {
let state = { mutex.lock().unwrap().get() };
match state {
State::Empty => thread::park(),
State::Wait(duration) => thread::sleep(duration),
State::Ready(data) => f(data),
}
})
}
impl<T: PartialEq> EventDebouncer<T> {
pub fn new<F>(delay: Duration, f: F) -> Self
where
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
let mutex = Arc::new(Mutex::new(EventBuffer::new(delay)));
let thread = spawn(&mutex, f);
Self { mutex, thread }
}
pub fn put(&self, data: T) {
self.mutex.lock().unwrap().put(data);
self.thread.thread().unpark();
}
}
pub struct MixedEventDebouncer<T> {
mutex: Arc<Mutex<MixedEventBuffer<T>>>,
thread: JoinHandle<()>,
}
impl<T: Eq> MixedEventDebouncer<T> {
pub fn new<F>(f: F) -> Self
where
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
let mutex = Arc::new(Mutex::new(MixedEventBuffer::new()));
let thread = spawn(&mutex, f);
Self { mutex, thread }
}
pub fn put(&self, data: T, delay: Duration) {
self.mutex.lock().unwrap().put(data, delay);
self.thread.thread().unpark();
}
}