89 lines
1.6 KiB
Rust
89 lines
1.6 KiB
Rust
// Watchers on the wall was the last good episode of Game of Thrones
|
|
|
|
use std::{
|
|
collections::*,
|
|
sync::Arc,
|
|
time::Duration,
|
|
};
|
|
|
|
use futures::channel::oneshot;
|
|
use tokio::{
|
|
sync::Mutex,
|
|
time::delay_for,
|
|
};
|
|
|
|
pub struct Watchers <T> {
|
|
pub next_id: u64,
|
|
pub senders: HashMap <u64, oneshot::Sender <T>>,
|
|
}
|
|
|
|
impl <T> Default for Watchers <T> {
|
|
fn default () -> Self {
|
|
Self {
|
|
next_id: 0,
|
|
senders: Default::default (),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl <T: 'static + Clone + Send + Sync> Watchers <T> {
|
|
fn take_id (&mut self) -> u64 {
|
|
let id = self.next_id;
|
|
self.next_id += 1;
|
|
id
|
|
}
|
|
|
|
fn add_watcher_with_id (&mut self, id: u64, s: oneshot::Sender <T>) {
|
|
self.senders.insert (id, s);
|
|
}
|
|
|
|
pub fn add_watcher (&mut self, s: oneshot::Sender <T>) -> u64 {
|
|
let id = self.take_id ();
|
|
self.add_watcher_with_id (id, s);
|
|
|
|
id
|
|
}
|
|
|
|
pub fn remove_watcher (&mut self, id: u64) {
|
|
self.senders.remove (&id);
|
|
}
|
|
|
|
pub fn wake_all (&mut self, msg: T) {
|
|
let waiters = {
|
|
std::mem::take (&mut self.senders)
|
|
};
|
|
|
|
for (_id, waiter) in waiters.into_iter () {
|
|
waiter.send (msg.clone ()).ok ();
|
|
}
|
|
}
|
|
|
|
pub fn num_watchers (&self) -> usize {
|
|
self.senders.len ()
|
|
}
|
|
|
|
pub async fn long_poll (that: Arc <Mutex <Self>>) -> Option <T> {
|
|
let (s, r) = oneshot::channel ();
|
|
|
|
let timeout = Duration::from_secs (10);
|
|
|
|
let id = {
|
|
let mut that = that.lock ().await;
|
|
that.add_watcher (s)
|
|
};
|
|
|
|
tokio::spawn (async move {
|
|
delay_for (timeout).await;
|
|
let mut that = that.lock ().await;
|
|
that.remove_watcher (id);
|
|
});
|
|
|
|
if let Ok (message) = r.await {
|
|
Some (message)
|
|
}
|
|
else {
|
|
None
|
|
}
|
|
}
|
|
}
|