use std::collections::HashMap;
use std::fmt;
use std::sync::{Arc, Condvar, Mutex, RwLock};
pub struct Notifier(RwLock<Inner>);
struct Inner {
next_id: u64,
subscriptions: HashMap<u64, Subscription>,
}
struct Subscription {
mutex: Arc<Mutex<()>>,
cond: Arc<Condvar>,
}
impl Notifier {
pub fn new() -> Notifier {
Notifier(RwLock::new(Inner {
next_id: 0,
subscriptions: HashMap::new(),
}))
}
pub fn notify(&self) {
let notify = self.0.read().unwrap();
for sub in notify.subscriptions.values() {
let _lock = sub.mutex.lock().unwrap();
sub.cond.notify_all();
}
}
pub fn subscribe(
&self,
mutex: Arc<Mutex<()>>,
condvar: Arc<Condvar>,
) -> u64 {
let mut notify = self.0.write().unwrap();
let id = notify.next_id;
notify.next_id = notify.next_id.checked_add(1).unwrap();
notify.subscriptions.insert(id, Subscription {
mutex: mutex,
cond: condvar,
});
id
}
pub fn unsubscribe(&self, key: u64) {
let mut notify = self.0.write().unwrap();
notify.subscriptions.remove(&key);
}
#[cfg(test)]
pub fn len(&self) -> usize {
let notify = self.0.read().unwrap();
notify.subscriptions.len()
}
}
impl fmt::Debug for Notifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let notify = self.0.read().unwrap();
writeln!(f, "Notifier({:?})",
notify.subscriptions.keys().collect::<Vec<_>>())
}
}