From 09c2533bf5bceb7d7b20cbb475ae51a1c5b8b81c Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 18 Jun 2022 09:49:17 +0200 Subject: [PATCH] Don't store the TurnChoices as Arc>, to prevent locking issues. --- src/dynamic_data/choices/mod.rs | 2 +- src/dynamic_data/flow/choice_queue.rs | 12 ++++------ src/dynamic_data/flow/turn_runner.rs | 33 +++++++++----------------- src/dynamic_data/models/battle.rs | 22 ++++++++--------- src/dynamic_data/models/battle_side.rs | 8 +++---- tests/common/library_loader.rs | 2 +- 6 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/dynamic_data/choices/mod.rs b/src/dynamic_data/choices/mod.rs index 9d349e6..8af5e0b 100644 --- a/src/dynamic_data/choices/mod.rs +++ b/src/dynamic_data/choices/mod.rs @@ -72,7 +72,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> { self.choice_data_mut().random_value = val; } - pub(crate) fn get_move_turn_data<'b>(&'b mut self) -> &'b mut MoveChoice<'user, 'library> { + pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> { if let TurnChoice::Move(data) = self { return data; } diff --git a/src/dynamic_data/flow/choice_queue.rs b/src/dynamic_data/flow/choice_queue.rs index 48ae48f..5e33412 100644 --- a/src/dynamic_data/flow/choice_queue.rs +++ b/src/dynamic_data/flow/choice_queue.rs @@ -1,26 +1,24 @@ use crate::dynamic_data::choices::TurnChoice; use crate::dynamic_data::models::pokemon::Pokemon; -use parking_lot::RwLock; -use std::sync::Arc; #[derive(Debug)] pub struct ChoiceQueue<'battle, 'library> { - queue: Vec>>>, + queue: Vec>, current: usize, } impl<'battle, 'library> ChoiceQueue<'battle, 'library> { - pub fn new(queue: Vec>>>) -> Self { + pub fn new(queue: Vec>) -> Self { Self { queue, current: 0 } } - pub fn dequeue<'b>(&'b mut self) -> &'b Arc>> { + pub fn dequeue<'b>(&'b mut self) -> &'b TurnChoice<'battle, 'library> { let c = &self.queue[self.current]; self.current += 1; c } - pub fn peek(&mut self) -> &'battle Arc> { + pub fn peek(&mut self) -> &'battle TurnChoice { &self.queue[self.current] } @@ -32,7 +30,7 @@ impl<'battle, 'library> ChoiceQueue<'battle, 'library> { todo!() } - pub(crate) fn get_queue(&self) -> &Vec>>> { + pub(crate) fn get_queue(&self) -> &Vec> { &self.queue } } diff --git a/src/dynamic_data/flow/turn_runner.rs b/src/dynamic_data/flow/turn_runner.rs index 329b70e..ceacfa9 100644 --- a/src/dynamic_data/flow/turn_runner.rs +++ b/src/dynamic_data/flow/turn_runner.rs @@ -25,17 +25,15 @@ impl<'own, 'library> Battle<'own, 'library> { // to check whether a pokemon was hit this turn. By resetting here, and setting a variable to true // they can then know this later on.) for choice in choice_queue.get_queue() { - let choice_guard = choice.read(); - let c = choice_guard.deref(); - script_hook!(on_before_turn, c, c); + script_hook!(on_before_turn, choice, choice); } // Now we can properly begin executing choices. // One by one dequeue the turns, and run them. If the battle has ended we do not want to // continue running however. while choice_queue.has_next() && !self.has_ended() { - let choice = choice_queue.dequeue().clone(); - self.execute_choice(choice.clone())?; + let choice = choice_queue.dequeue(); + self.execute_choice(&choice)?; } // If the battle is not ended, we have arrived at the normal end of a turn. and thus want @@ -63,15 +61,14 @@ impl<'own, 'library> Battle<'own, 'library> { Ok(()) } - fn execute_choice(&self, choice: Arc>>) -> PkmnResult<()> { - let choice_guard = choice.read(); - if let TurnChoice::Pass(..) = choice_guard.deref() { + fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> { + if let TurnChoice::Pass(..) = choice { return Ok(()); } if self.has_ended() { return Ok(()); } - let user = choice_guard.user().read(); + let user = choice.user().read(); if !user.is_usable() { return Ok(()); } @@ -79,15 +76,11 @@ impl<'own, 'library> Battle<'own, 'library> { return Ok(()); } - if !self.can_use(choice_guard.deref()) { + if !self.can_use(&choice) { return Ok(()); } - match choice_guard.deref() { - TurnChoice::Move(..) => { - drop(user); - drop(choice_guard); - self.execute_move_choice(&choice)? - } + match choice { + TurnChoice::Move(..) => self.execute_move_choice(&choice)?, TurnChoice::Item(_) => {} TurnChoice::Switch(_) => {} TurnChoice::Flee(_) => {} @@ -96,12 +89,8 @@ impl<'own, 'library> Battle<'own, 'library> { Ok(()) } - fn execute_move_choice<'func>( - &'func self, - choice: &'func Arc>>, - ) -> PkmnResult<()> { - let mut write_guard = choice.write(); - let choice = write_guard.get_move_turn_data(); + fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> { + let choice = choice.get_move_turn_data(); let used_move = choice.used_move(); let move_data_lock = used_move.read(); let move_data = move_data_lock.move_data(); diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index e4ac6db..e93578c 100644 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -237,35 +237,35 @@ impl<'own, 'library> Battle<'own, 'library> { let start_time = chrono::Utc::now(); let mut choices = Vec::with_capacity(self.number_of_sides as usize * self.pokemon_per_side as usize); for side in &mut self.sides { - for choice in side.choices() { - if choice.is_none() { + for choice_opt in side.choices_mut() { + if choice_opt.is_none() { panic!("Choice was none, but all choices were set? Logic error."); } - let mut choice_guard = choice.as_ref().unwrap().write(); - let c = choice_guard.deref(); + let mut choice = choice_opt.as_mut().unwrap(); + let c = choice.deref(); if let TurnChoice::Move(data) = c { let mut change_priority = data.priority(); script_hook!(change_priority, c, c, &mut change_priority); if change_priority != data.priority() { - if let TurnChoice::Move(data) = choice_guard.deref_mut() { + if let TurnChoice::Move(data) = choice.deref_mut() { *data.priority_mut() = change_priority; } } } - let mut speed = choice_guard.speed(); - let c = choice_guard.deref(); + let mut speed = choice.speed(); + let c = choice.deref(); script_hook!(change_speed, c, c, &mut speed); - *choice_guard.speed_mut() = speed; + *choice.speed_mut() = speed; - choice_guard.set_random_value(self.random.get() as u32); - choices.push(choice.as_ref().unwrap().clone()); + choice.set_random_value(self.random.get() as u32); + choices.push(choice_opt.take().unwrap()); } side.reset_choices(); } self.current_turn += 1; - choices.sort_unstable_by(|a, b| b.read().deref().cmp(a.read().deref())); + choices.sort_unstable_by(|a, b| b.cmp(a)); self.current_turn_queue = Some(Arc::new(RwLock::new(ChoiceQueue::new(choices)))); { diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index 57ac59e..103da70 100644 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -16,7 +16,7 @@ pub struct BattleSide<'own, 'library> { index: u8, pokemon_per_side: u8, pokemon: Vec>>>>, - choices: Vec>>>>, + choices: Vec>>, fillable_slots: Vec, choices_set: u8, battle: *mut Battle<'own, 'library>, @@ -65,10 +65,10 @@ impl<'own, 'library> BattleSide<'own, 'library> { pub fn pokemon(&self) -> &Vec>>>> { &self.pokemon } - pub fn choices(&self) -> &Vec>>>> { + pub fn choices(&self) -> &Vec>> { &self.choices } - pub fn choices_mut(&mut self) -> &mut Vec>>>> { + pub fn choices_mut(&mut self) -> &mut Vec>> { &mut self.choices } @@ -110,7 +110,7 @@ impl<'own, 'library> BattleSide<'own, 'library> { for (index, pokemon_slot) in self.pokemon.iter().enumerate() { if let Some(pokemon) = pokemon_slot { if std::ptr::eq(pokemon.data_ptr(), choice.user().data_ptr()) { - self.choices[index] = Some(Arc::new(RwLock::new(choice))); + self.choices[index] = Some(choice); self.choices_set += 1; return; } diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index 52a2bd3..0b32111 100644 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -251,7 +251,7 @@ pub fn load_species(path: &String, library: &mut StaticData) { let default_form_value = &forms["default"]; let default_form = parse_form("default".into(), default_form_value, library); - let mut species = Box::new(Species::new( + let species = Box::new(Species::new( id as u16, &name, gender_rate as f32,