use std::sync::Arc;
use hello_egui_utils::MaybeSend;
use parking_lot::Mutex;
#[cfg(not(target_arch = "wasm32"))]
use type_map::concurrent::TypeMap;
#[cfg(target_arch = "wasm32")]
use type_map::TypeMap;
use crate::{AsRequestRepaint, RequestRepaintContext, UiInbox, UiInboxSender};
#[derive(Debug)]
struct TypeInboxEntry<T> {
sender: UiInboxSender<T>,
inbox: UiInbox<T>,
}
impl<T> TypeInboxEntry<T> {
fn new() -> Self {
let (sender, inbox) = UiInbox::channel();
Self { sender, inbox }
}
}
#[derive(Debug)]
struct TypeInboxInner {
map: TypeMap,
ctx: RequestRepaintContext,
}
#[derive(Clone, Debug)]
pub struct TypeInbox(Arc<Mutex<TypeInboxInner>>);
impl TypeInbox {
pub fn new(ctx: &(impl AsRequestRepaint + 'static)) -> Self {
Self(Arc::new(Mutex::new(TypeInboxInner {
map: TypeMap::new(),
ctx: ctx.as_request_repaint(),
})))
}
#[track_caller]
pub fn send<T: MaybeSend + 'static>(&self, message: T) {
let ctx = {
let mut guard = self.0.lock();
let entry = guard.map.entry().or_insert_with(TypeInboxEntry::<T>::new);
entry.sender.send(message).ok();
guard.ctx.clone()
};
ctx.request_repaint();
}
pub fn send_without_repaint<T: MaybeSend + 'static>(&self, message: T) {
let mut guard = self.0.lock();
let entry = guard.map.entry().or_insert_with(TypeInboxEntry::<T>::new);
entry.sender.send(message).ok();
}
pub fn read<T: MaybeSend + 'static>(&self) -> impl Iterator<Item = T> {
let mut guard = self.0.lock();
let iter = guard
.map
.entry()
.or_insert_with(TypeInboxEntry::<T>::new)
.inbox
.read_without_ctx();
iter
}
}