use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use rich_intuituive::{Ctx, signal, watch};
use crate::host::Notify;
pub(crate) trait Fed: 'static {
fn install(&mut self, notify: Notify);
fn pump(this: &Rc<RefCell<Self>>, cx: &mut Ctx);
}
pub(crate) fn connect<S: Fed>(state: &Rc<RefCell<S>>) {
let cell = signal(Rc::downgrade(state));
let mut connected = false;
watch(
|| (),
move |(), cx| {
if connected {
return;
}
connected = true;
let Some(state) = cell.with_untracked(Weak::upgrade) else {
return;
};
let proxy = cx.proxy();
let queued = Arc::new(AtomicBool::new(false));
let notify: Notify = Arc::new(move || {
if queued.swap(true, Ordering::SeqCst) {
return;
}
let queued = Arc::clone(&queued);
proxy.run_with(move |cx| {
queued.store(false, Ordering::SeqCst);
if let Some(state) = cell.with_untracked(Weak::upgrade) {
S::pump(&state, cx);
}
});
});
state.borrow_mut().install(notify);
S::pump(&state, cx);
},
);
}