use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
pub(crate) static NEEDS_REDRAW: AtomicBool = AtomicBool::new(false);
pub fn needs_redraw() -> bool {
NEEDS_REDRAW.load(Ordering::Relaxed)
}
pub fn clear_redraw() {
NEEDS_REDRAW.store(false, Ordering::Relaxed);
}
pub struct Signal<T: Clone> {
value: Arc<Mutex<T>>,
}
impl<T: Clone> Signal<T> {
pub fn new(value: T) -> Self {
Self { value: Arc::new(Mutex::new(value)) }
}
pub fn get(&self) -> T {
self.value.lock().unwrap().clone()
}
pub fn set(&self, value: T) {
*self.value.lock().unwrap() = value;
NEEDS_REDRAW.store(true, Ordering::Relaxed);
}
}
impl<T: Clone> Clone for Signal<T> {
fn clone(&self) -> Self {
Self { value: Arc::clone(&self.value) }
}
}
impl<T: Clone> Signal<T> {
pub fn as_raw_arc(&self) -> *const std::sync::Mutex<T> {
Arc::into_raw(Arc::clone(&self.value))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_returns_initial_value() {
let s = Signal::new(42i32);
assert_eq!(s.get(), 42);
}
#[test]
fn set_updates_value() {
let s = Signal::new(0i32);
s.set(99);
assert_eq!(s.get(), 99);
}
#[test]
fn set_marks_redraw() {
clear_redraw();
let s = Signal::new(false);
assert!(!needs_redraw());
s.set(true);
assert!(needs_redraw());
clear_redraw();
}
#[test]
fn clone_shares_value() {
let a = Signal::new(1i32);
let b = a.clone();
a.set(7);
assert_eq!(b.get(), 7);
}
#[test]
fn independent_signals_do_not_share_value() {
let a = Signal::new(1i32);
let b = Signal::new(1i32);
a.set(99);
assert_eq!(b.get(), 1);
}
}