//! Fan-out to clients. Drop-only: each client has a bounded queue that loses its //! oldest message when full, so a tablet with its screen off never stalls anything. use std::collections::VecDeque; use std::sync::{Arc, Condvar, Mutex}; use std::time::Duration; const QUEUE: usize = 64; pub struct Outbox { q: Mutex>, cv: Condvar, } impl Outbox { pub fn push(&self, msg: String) { let mut q = self.q.lock().unwrap(); if q.len() >= QUEUE { q.pop_front(); } q.push_back(msg); self.cv.notify_one(); } /// Everything queued, waiting at most `wait` for something to arrive. pub fn drain(&self, wait: Duration) -> Vec { let q = self.q.lock().unwrap(); let (mut q, _) = self.cv.wait_timeout_while(q, wait, |q| q.is_empty()).unwrap(); q.drain(..).collect() } } #[derive(Default, Clone)] pub struct Hub { clients: Arc>>>, } impl Hub { pub fn join(&self) -> Arc { let o = Arc::new(Outbox { q: Mutex::new(VecDeque::new()), cv: Condvar::new() }); self.clients.lock().unwrap().push(o.clone()); o } pub fn leave(&self, o: &Arc) { self.clients.lock().unwrap().retain(|c| !Arc::ptr_eq(c, o)); } pub fn broadcast(&self, msg: &str) { for c in self.clients.lock().unwrap().iter() { c.push(msg.to_string()); } } pub fn count(&self) -> usize { self.clients.lock().unwrap().len() } }