diff --git a/src/population.rs b/src/population.rs index f9600f6..3085e05 100644 --- a/src/population.rs +++ b/src/population.rs @@ -1,4 +1,8 @@ +use std::sync::Arc; +use std::sync::Mutex; use crate::prelude::*; +use std::thread; + #[derive(Debug)] pub struct Point { @@ -10,7 +14,7 @@ pub struct Population { pub start_infected_ratio: i32, pub start_immune_ratio: i32, pub start_dead_ratio: i32, - pub humans: Vec, + pub humans: Arc>>, pub width: i32, pub height: i32, pub age: i32, @@ -35,14 +39,15 @@ impl Population { let size: usize = (width * height) as usize; - let mut the_humans: Vec = vec![ + let the_humans_arc = Arc::new(Mutex::new(vec![ Human { x: 0, y: 0, present_state: State::Normal }; size - ]; + ])); + let the_humans = Arc::clone(&the_humans_arc); for x in 0..width { for y in 0..height { let idx = human_idx(x, y, width); @@ -60,7 +65,7 @@ impl Population { { present_state = State::Dead; } - the_humans[idx] = Human{x: x, y: y, present_state: present_state}; + the_humans.lock().unwrap()[idx] = Human{x: x, y: y, present_state: present_state}; } } Self { @@ -71,7 +76,7 @@ impl Population { height: height, plague: plague, age: 0, - humans: the_humans, + humans: the_humans_arc, size: size, } } @@ -88,9 +93,11 @@ impl Population { } fn is_inside_and_infected(&self, point: Point) -> bool { + let the_humans_arc = Arc::clone(&self.humans); if self.is_inside(&point) { let idx = human_idx(point.x, point.y, self.width); - if self.humans[idx].present_state == State::Infected { + let humans = the_humans_arc.lock().unwrap(); + if humans[idx].present_state == State::Infected { roll(self.plague.infection_rate) } else { false @@ -114,7 +121,8 @@ impl Population { let mut stats: [i32; 4] = [0, 0, 0, 0]; // stats[0] Normal stats[1] Infected stats[2] Immune stats[3] Dead - for h in self.humans.iter() { + let humans = Arc::clone(&self.humans); + for h in humans.lock().unwrap().iter() { match h.present_state { State::Normal => { possible_infected.push(Point{ x: h.x, y: h.y}); @@ -202,36 +210,60 @@ impl Population { } } - for infected_position in people_to_infect.iter() { - // println!("To infect: {:?}", infected_position); - //people_to_infect.iter().map(|infected_position|{ - let infected_index = human_idx(infected_position.x, infected_position.y, self.width); - // let _ = infected_position.x; - //DEBUG - //println!("x: {} y: {} index: {}",infected_position.x,infected_position.y,infected_index); - self.humans[infected_index].present_state = State::Infected; - //DEBUG - //println!("Infected someone"); +// for infected_position in people_to_infect.iter() { +// // println!("To infect: {:?}", infected_position); +// //people_to_infect.iter().map(|infected_position|{ +// let infected_index = human_idx(infected_position.x, infected_position.y, self.width); +// // let _ = infected_position.x; +// //DEBUG +// //println!("x: {} y: {} index: {}",infected_position.x,infected_position.y,infected_index); +// self.humans[infected_index].present_state = State::Infected; +// //DEBUG +// //println!("Infected someone"); +// } + + let mut threads = vec![]; + { + let humans = Arc::clone(&self.humans); + let width = self.width; + threads.push(thread::spawn(move || { + for infected_position in people_to_infect.iter() { + let infected_index = human_idx(infected_position.x, infected_position.y, width); + humans.lock().unwrap()[infected_index].present_state = State::Infected; + } + })); } - for cured_position in people_to_cure.iter() { - //people_to_cure.iter().map(|cured_position|{ - let cured_index = human_idx(cured_position.x, cured_position.y, self.width); - if self.humans[cured_index].present_state != State::Infected { - println!("not infected"); - } - self.humans[cured_index].present_state = State::Immune; - //DEBUG - //println!("Cured someone"); + { + let humans = Arc::clone(&self.humans); + let width = self.width; + threads.push(thread::spawn(move || { + for cured_position in people_to_cure.iter() { + //people_to_cure.iter().map(|cured_position|{ + let cured_index = human_idx(cured_position.x, cured_position.y, width); + if humans.lock().unwrap()[cured_index].present_state != State::Infected { + println!("not infected"); + } else { + humans.lock().unwrap()[cured_index].present_state = State::Immune; + } + //DEBUG + //println!("Cured someone"); + } + })); + } + + for t in threads { + t.join().unwrap(); } for dead_position in people_to_kill.iter() { + let humans = Arc::clone(&self.humans); //people_to_kill.iter().map(|dead_position|{ let dead_index = human_idx(dead_position.x, dead_position.y, self.width); - if self.humans[dead_index].present_state == State::Dead { + if humans.lock().unwrap()[dead_index].present_state == State::Dead { // println!("Already dead"); } else { - self.humans[dead_index].present_state = State::Dead; + humans.lock().unwrap()[dead_index].present_state = State::Dead; } //DEBUG } @@ -364,13 +396,14 @@ mod tests { let disease = Disease::new(20, 10, 5, String::from("Covid 44")); let (width, height) = (5, 7); let population = Population::new(20, 10, 5, 5, 7, disease); - assert_eq!(population.humans.len(), 5 * 7); - for h in population.humans.iter() { + let humans = Arc::clone(&population.humans); + assert_eq!(humans.lock().unwrap().len(), 5 * 7); + for h in humans.lock().unwrap().iter() { let idx = human_idx(h.x, h.y, width); - assert_eq!(population.humans[idx].x, h.x, "coordinates should match"); - assert_eq!(population.humans[idx].y, h.y, "coordinates should match"); + assert_eq!(humans.lock().unwrap()[idx].x, h.x, "coordinates should match"); + assert_eq!(humans.lock().unwrap()[idx].y, h.y, "coordinates should match"); } - assert_eq!(population.humans.len(), (width * height) as usize); + assert_eq!(humans.lock().unwrap().len(), (width * height) as usize); } #[test]