#![allow(dead_code)]
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::sync::Mutex;
pub trait HookResultMessage: Send + Sync + Clone + 'static {}
impl<T: Send + Sync + Clone + 'static> HookResultMessage for T {}
pub trait Message: Send + Sync + Clone + 'static {}
impl<T: Send + Sync + Clone + 'static> Message for T {}
struct DeferredState<M: Message> {
pending: Option<tokio::sync::oneshot::Receiver<Vec<Box<dyn HookResultMessage>>>>,
resolved: AtomicBool,
}
pub struct DeferredHookMessages<M: Message> {
state: Arc<Mutex<DeferredState<M>>>,
set_messages: Arc<dyn Fn(Vec<Box<dyn HookResultMessage>>) + Send + Sync>,
}
impl<M: Message> DeferredHookMessages<M> {
pub fn new(
pending_messages: Option<tokio::sync::oneshot::Receiver<Vec<Box<dyn HookResultMessage>>>>,
set_messages: impl Fn(Vec<Box<dyn HookResultMessage>>) + Send + Sync + 'static,
) -> Self {
let state = Arc::new(Mutex::new(DeferredState {
pending: pending_messages,
resolved: AtomicBool::new(pending_messages.is_none()),
}));
let set_messages = Arc::new(set_messages);
{
let state = Arc::clone(&state);
let set_messages = Arc::clone(&set_messages);
tokio::spawn(async move {
let msgs = {
let mut guard = state.lock().await;
guard.pending.take()
};
if let Some(rx) = msgs {
if let Ok(msgs) = rx.await {
let already_resolved = state.lock().await.resolved.load(Ordering::SeqCst);
if already_resolved {
return;
}
state.lock().await.resolved.store(true, Ordering::SeqCst);
if !msgs.is_empty() {
set_messages(msgs);
}
}
}
});
}
Self { state, set_messages }
}
pub async fn wait_for_messages(&self) {
let already_resolved = {
let guard = self.state.lock().await;
guard.resolved.load(Ordering::SeqCst)
};
if already_resolved {
return;
}
let rx = {
let mut guard = self.state.lock().await;
guard.pending.take()
};
if let Some(rx) = rx {
if let Ok(msgs) = rx.await {
let already_resolved = {
let guard = self.state.lock().await;
guard.resolved.load(Ordering::SeqCst)
};
if already_resolved {
return;
}
{
let mut guard = self.state.lock().await;
guard.resolved.store(true, Ordering::SeqCst);
guard.pending = None;
}
if !msgs.is_empty() {
(self.set_messages)(msgs);
}
}
}
}
}