61 lines
1.6 KiB
Rust
61 lines
1.6 KiB
Rust
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||
|
|
use std::sync::Arc;
|
||
|
|
|
||
|
|
use tokio::sync::Mutex;
|
||
|
|
use werewolves_proto::player::PlayerId;
|
||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct ConnectUpdate {
|
||
|
|
updated: Arc<AtomicBool>,
|
||
|
|
connected: Arc<Mutex<Vec<PlayerId>>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl ConnectUpdate {
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
updated: Arc::new(AtomicBool::new(false)),
|
||
|
|
connected: Arc::new(Mutex::new(Vec::new())),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn connect(&self, pid: PlayerId) {
|
||
|
|
let mut connected = self.connected.lock().await;
|
||
|
|
if connected.iter().any(|c| c == &pid) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
connected.push(pid);
|
||
|
|
self.updated.store(true, Ordering::SeqCst);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn disconnect(&self, pid: PlayerId) {
|
||
|
|
let mut connected = self.connected.lock().await;
|
||
|
|
if let Some(idx) = connected
|
||
|
|
.iter()
|
||
|
|
.enumerate()
|
||
|
|
.find_map(|(idx, c)| (c == &pid).then_some(idx))
|
||
|
|
{
|
||
|
|
connected.swap_remove(idx);
|
||
|
|
self.updated.store(true, Ordering::SeqCst);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Future for ConnectUpdate {
|
||
|
|
type Output = Arc<[PlayerId]>;
|
||
|
|
|
||
|
|
fn poll(
|
||
|
|
self: std::pin::Pin<&mut Self>,
|
||
|
|
cx: &mut std::task::Context<'_>,
|
||
|
|
) -> std::task::Poll<Self::Output> {
|
||
|
|
if self.updated.load(Ordering::SeqCst)
|
||
|
|
&& let Ok(connected) = self.connected.try_lock()
|
||
|
|
{
|
||
|
|
self.updated.store(false, Ordering::SeqCst);
|
||
|
|
std::task::Poll::Ready(connected.clone().into())
|
||
|
|
} else {
|
||
|
|
cx.waker().wake_by_ref();
|
||
|
|
std::task::Poll::Pending
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|