use observable_property::ObservableProperty;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
fn main() -> Result<(), observable_property::PropertyError> {
println!("=== Weak Observer Example ===\n");
println!("Example 1: Basic weak observer");
{
let property = ObservableProperty::new(0);
{
let observer: Arc<dyn Fn(&i32, &i32) + Send + Sync> = Arc::new(|old: &i32, new: &i32| {
println!(" Observer called: {} -> {}", old, new);
});
let _id = property.subscribe_weak(Arc::downgrade(&observer))?;
property.set(10)?; property.set(20)?;
}
println!(" Observer Arc dropped, next set will clean it up:");
property.set(30)?; println!(" (No observer called - it was automatically cleaned up)\n");
}
println!("Example 2: Strong observer (for comparison)");
{
let property = ObservableProperty::new(0);
{
let observer: Arc<dyn Fn(&i32, &i32) + Send + Sync> = Arc::new(|old: &i32, new: &i32| {
println!(" Strong observer: {} -> {}", old, new);
});
let _id = property.subscribe(observer)?;
property.set(10)?; property.set(20)?; }
property.set(30)?; println!(" (Strong observer keeps working even after Arc goes out of scope)\n");
}
println!("Example 3: Multiple weak observers with independent lifetimes");
{
let property = ObservableProperty::new(String::from("start"));
let observer1: Arc<dyn Fn(&String, &String) + Send + Sync> = Arc::new(|old: &String, new: &String| {
println!(" Observer 1: '{}' -> '{}'", old, new);
});
let observer2: Arc<dyn Fn(&String, &String) + Send + Sync> = Arc::new(|old: &String, new: &String| {
println!(" Observer 2: '{}' -> '{}'", old, new);
});
let observer3: Arc<dyn Fn(&String, &String) + Send + Sync> = Arc::new(|old: &String, new: &String| {
println!(" Observer 3: '{}' -> '{}'", old, new);
});
property.subscribe_weak(Arc::downgrade(&observer1))?;
property.subscribe_weak(Arc::downgrade(&observer2))?;
property.subscribe_weak(Arc::downgrade(&observer3))?;
println!(" All three observers active:");
property.set(String::from("step1"))?;
drop(observer2);
println!("\n Observer 2 dropped:");
property.set(String::from("step2"))?;
drop(observer1);
println!("\n Observer 1 dropped:");
property.set(String::from("step3"))?;
drop(observer3);
println!("\n Observer 3 dropped:");
property.set(String::from("step4"))?;
println!(" (No observers left)\n");
}
println!("Example 4: Weak observers in multi-threaded context");
{
let property = Arc::new(ObservableProperty::new(0));
let property_clone = property.clone();
let observer: Arc<dyn Fn(&i32, &i32) + Send + Sync> = Arc::new(|old: &i32, new: &i32| {
println!(" Thread observer: {} -> {}", old, new);
});
property.subscribe_weak(Arc::downgrade(&observer))?;
let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(50));
let _ = property_clone.set(42);
thread::sleep(Duration::from_millis(50));
let _ = property_clone.set(100);
});
thread::sleep(Duration::from_millis(200));
drop(observer);
handle.join().unwrap();
property.set(200)?;
println!(" (Observer was cleaned up after being dropped)\n");
}
println!("Example 5: Conditional monitoring");
{
let temperature = ObservableProperty::new(20.0_f64);
println!(" Initial temperature: 20.0°C");
temperature.set(22.0)?;
if temperature.get()? > 25.0 {
println!(" Temperature above 25°C - enabling monitor");
} else {
println!(" Temperature rising to 28.0°C - enabling monitor");
temperature.set(28.0)?;
let monitor: Arc<dyn Fn(&f64, &f64) + Send + Sync> = Arc::new(|old: &f64, new: &f64| {
println!(" 🔥 High temp alert: {:.1}°C -> {:.1}°C", old, new);
});
temperature.subscribe_weak(Arc::downgrade(&monitor))?;
temperature.set(30.0)?;
temperature.set(32.0)?;
println!("\n Cooling down - disabling monitor");
drop(monitor);
}
temperature.set(25.0)?;
println!(" (No alerts - monitor was automatically cleaned up)\n");
}
println!("=== Weak Observer Examples Complete ===");
Ok(())
}