multithreaded/
multithreaded.rs

1use observable_property::ObservableProperty;
2use std::sync::Arc;
3use std::thread;
4use std::time::Duration;
5
6// --- Person struct and impl (from basic.rs, adapted) ---
7#[derive(Clone, Debug)]
8struct Person {
9    name: ObservableProperty<String>,
10    age: ObservableProperty<i32>,
11}
12
13impl Person {
14    fn new(name: String, age: i32) -> Self {
15        Self {
16            name: ObservableProperty::new(name),
17            age: ObservableProperty::new(age),
18        }
19    }
20
21    fn get_name(&self) -> Result<String, observable_property::PropertyError> {
22        self.name.get()
23    }
24
25    fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
26        self.name.set(new_name)
27    }
28
29    fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
30        self.age.get()
31    }
32
33    fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
34        self.age.set(new_age)
35    }
36
37    fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
38        let current_age = self.age.get()?;
39        self.age.set(current_age + 1)
40    }
41}
42// --- End Person struct and impl ---
43
44fn main() -> Result<(), Box<dyn std::error::Error>> {
45    println!("=== Observable Property Multithreaded Person Example ===\n");
46
47    let person = Arc::new(Person::new("Bob".to_string(), 30));
48
49    // Subscribe to name changes
50    let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
51        println!("šŸ“ Name changed: '{}' → '{}'", old_name, new_name);
52    }))?;
53
54    // Subscribe to age changes
55    let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
56        println!("šŸŽ‚ Age changed: {} → {}", old_age, new_age);
57    }))?;
58
59    // Spawn threads to update name and age concurrently
60    let person_clone1 = person.clone();
61    let handle1 = thread::spawn(move || {
62        for i in 0..3 {
63            let new_name = format!("Bob #{}", i + 1);
64            person_clone1.set_name(new_name).unwrap();
65            thread::sleep(Duration::from_millis(50));
66        }
67    });
68
69    let person_clone2 = person.clone();
70    let handle2 = thread::spawn(move || {
71        for _ in 0..3 {
72            person_clone2.celebrate_birthday().unwrap();
73            thread::sleep(Duration::from_millis(30));
74        }
75    });
76
77    handle1.join().unwrap();
78    handle2.join().unwrap();
79
80    println!("\nFinal state:");
81    println!("  Name: {}", person.get_name()?);
82    println!("  Age: {}", person.get_age()?);
83
84    // Cleanup observers
85    person.name.unsubscribe(name_observer_id)?;
86    person.age.unsubscribe(age_observer_id)?;
87
88    println!("\nāœ… Multithreaded Person example completed successfully!");
89    Ok(())
90}