1use crate::signal::{Callback, Signal, SubscriptionGuard};
2use std::cell::RefCell;
3use std::rc::Rc;
4
5#[derive(Clone, Copy)]
6pub struct FrameTimeSignalHandle;
7
8thread_local! {
9 static FRAME_TIME_SIGNAL: RefCell<Signal<f64>> = RefCell::new(Signal::new(0.0));
10}
11
12impl FrameTimeSignalHandle {
13 pub fn value(&self) -> f64 {
14 FRAME_TIME_SIGNAL.with(|slot| slot.borrow().get())
15 }
16
17 pub fn subscribe(&self, handler: impl Fn(f64) + 'static) -> SubscriptionGuard {
18 handler(self.value());
19 FRAME_TIME_SIGNAL.with(|slot| {
20 let callback: Callback = Rc::new(move || handler(frame_time_signal().value()));
21 slot.borrow_mut().subscribe(callback)
22 })
23 }
24}
25
26pub fn frame_time_signal() -> FrameTimeSignalHandle {
27 FrameTimeSignalHandle
28}
29
30pub(crate) fn set_frame_time(timestamp_ms: f64) {
31 FRAME_TIME_SIGNAL.with(|slot| {
32 let callbacks = slot.borrow_mut().set(timestamp_ms);
33 if let Some(callbacks) = callbacks {
34 for callback in callbacks {
35 callback();
36 }
37 }
38 });
39}
40
41#[cfg(test)]
42mod tests {
43 use super::{frame_time_signal, set_frame_time};
44 use std::cell::Cell;
45 use std::rc::Rc;
46
47 #[test]
48 fn updates_frame_time_signal_and_notifies_subscribers() {
49 let count = Rc::new(Cell::new(0));
50 let seen = Rc::new(Cell::new(0.0));
51 let count_for_handler = count.clone();
52 let seen_for_handler = seen.clone();
53 let _guard = frame_time_signal().subscribe(move |value| {
54 count_for_handler.set(count_for_handler.get() + 1);
55 seen_for_handler.set(value);
56 });
57
58 set_frame_time(1234.5);
59
60 assert_eq!(frame_time_signal().value(), 1234.5);
61 assert_eq!(seen.get(), 1234.5);
62 assert!(count.get() >= 2);
63 }
64}