1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::buffer::{BufferGet, EventBuffer, MixedEventBuffer, State};
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::time::Duration;
struct DebouncerThread<B> {
mutex: Arc<Mutex<B>>,
thread: JoinHandle<()>,
}
impl<B> DebouncerThread<B> {
fn new<F, T>(buffer: B, f: F) -> Self
where
B: BufferGet<T> + Send + 'static,
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
let mutex = Arc::new(Mutex::new(buffer));
let mutex_clone = mutex.clone();
let thread = thread::spawn(move || loop {
let state = mutex_clone.lock().unwrap().get();
match state {
State::Empty => thread::park(),
State::Wait(duration) => thread::sleep(duration),
State::Ready(data) => f(data),
}
});
Self { mutex, thread }
}
}
pub struct EventDebouncer<T>(DebouncerThread<EventBuffer<T>>);
impl<T: PartialEq> EventDebouncer<T> {
pub fn new<F>(delay: Duration, f: F) -> Self
where
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
Self(DebouncerThread::new(EventBuffer::new(delay), f))
}
pub fn put(&self, data: T) {
self.0.mutex.lock().unwrap().put(data);
self.0.thread.thread().unpark();
}
}
pub struct MixedEventDebouncer<T>(DebouncerThread<MixedEventBuffer<T>>);
impl<T: Eq> MixedEventDebouncer<T> {
pub fn new<F>(f: F) -> Self
where
F: Fn(T) -> () + Send + 'static,
T: Send + 'static,
{
Self(DebouncerThread::new(MixedEventBuffer::new(), f))
}
pub fn put(&self, data: T, delay: Duration) {
self.0.mutex.lock().unwrap().put(data, delay);
self.0.thread.thread().unpark();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn event_debouncer() {
let result = Arc::new(Mutex::new(vec![]));
let result_clone = Arc::clone(&result);
let debouncer = EventDebouncer::new(Duration::from_millis(10), move |s: String| {
result_clone.lock().unwrap().push(s);
});
debouncer.put(String::from("Test"));
debouncer.put(String::from("Test"));
thread::sleep(Duration::from_millis(20));
assert_eq!(result.lock().unwrap().as_slice(), [String::from("Test")]);
}
#[test]
fn mixed_event_debouncer() {
let result = Arc::new(Mutex::new(vec![]));
let result_clone = Arc::clone(&result);
let debouncer = MixedEventDebouncer::new(move |s: String| {
result_clone.lock().unwrap().push(s);
});
debouncer.put(String::from("Test"), Duration::from_millis(10));
debouncer.put(String::from("Test"), Duration::from_millis(10));
thread::sleep(Duration::from_millis(20));
assert_eq!(result.lock().unwrap().as_slice(), [String::from("Test")]);
}
}