use std::sync::Arc as StdArc;
use teksilo_canvas::sync::{Arc, AtomicU64, AtomicUsize, Ordering, model, thread};
use teksilo_canvas::wake::{RedrawWaker, WakeKind};
use super::{NodeWakeState, RepaintTrigger};
struct LoomWaker(AtomicUsize);
impl RedrawWaker for LoomWaker {
fn wake(&self, _kind: WakeKind) {
self.0.fetch_add(1, Ordering::Relaxed);
}
}
#[test]
fn loom_trigger_attach_register_then_read() {
model(|| {
let trigger = RepaintTrigger::new();
let waker = StdArc::new(LoomWaker(AtomicUsize::new(0)));
let content = Arc::new(AtomicU64::new(0));
let producer = {
let (trigger, content) = (trigger.clone(), content.clone());
thread::spawn(move || {
content.store(1, Ordering::Relaxed);
trigger.request_repaint();
})
};
let state = StdArc::new(NodeWakeState::new(Some(waker.clone())));
trigger.attach_state(&state);
state.consume_repaint();
let seen = content.load(Ordering::Relaxed);
producer.join().unwrap();
assert!(
seen == 1 || waker.0.load(Ordering::Relaxed) == 1,
"the change was neither read nor woken for"
);
});
}
#[test]
fn loom_trigger_waker_install_after_raise() {
model(|| {
let trigger = RepaintTrigger::new();
let state = StdArc::new(NodeWakeState::new(None));
trigger.attach_state(&state);
let waker = StdArc::new(LoomWaker(AtomicUsize::new(0)));
let producer = {
let trigger = trigger.clone();
thread::spawn(move || trigger.request_repaint())
};
state.set_waker(Some(waker.clone()));
producer.join().unwrap();
if state.repaint_pending() {
assert!(
waker.0.load(Ordering::Relaxed) >= 1,
"a pending request whose window was never woken"
);
}
});
}