diff --git a/src/dynamic_data/script_handling/mod.rs b/src/dynamic_data/script_handling/mod.rs index 22fdab2..e5e63f3 100644 --- a/src/dynamic_data/script_handling/mod.rs +++ b/src/dynamic_data/script_handling/mod.rs @@ -12,8 +12,8 @@ pub mod volatile_scripts; macro_rules! script_hook { ($hook_name: ident, $source: ident, $($parameters: expr),*) => { let mut aggregator = $source.get_script_iterator(); - while let Some(script) = aggregator.get_next() { - let script = script.get(); + while let Some(script_container) = aggregator.get_next() { + let script = script_container.get(); if let Some(script) = script { if let Some(script) = script.read().as_deref() { if !script.is_suppressed() { diff --git a/src/dynamic_data/script_handling/script.rs b/src/dynamic_data/script_handling/script.rs index 6ac579e..296786f 100644 --- a/src/dynamic_data/script_handling/script.rs +++ b/src/dynamic_data/script_handling/script.rs @@ -12,6 +12,7 @@ use std::fmt::{Debug, Formatter}; use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; +use std::thread::JoinHandle; pub trait Script: Send + Sync { fn name(&self) -> &StringKey; @@ -144,15 +145,17 @@ impl Debug for dyn Script { type ScriptHolder = Arc>>>; -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug)] pub struct ScriptContainer { script: ScriptHolder, + pub(crate) join_handle: RwLock>>, } impl ScriptContainer { pub fn new(script: Arc) -> ScriptContainer { Self { script: Arc::new(RwLock::new(Some(script))), + join_handle: RwLock::new(None), } } @@ -169,14 +172,16 @@ impl ScriptContainer { pub fn set(&self, script: Arc) -> Arc { if let Some(v) = self.script.read().deref() { + v.on_remove(); v.mark_for_deletion(); } if self.script.is_locked() { let holder = self.script.clone(); let new = script.clone(); - std::thread::spawn(move || { + let handle = std::thread::spawn(move || { holder.write().replace(new); }); + self.join_handle.write().replace(handle); } else { self.script.write().replace(script.clone()); }; @@ -185,6 +190,7 @@ impl ScriptContainer { pub fn clear(&self) { if let Some(v) = self.script.read().deref() { + v.on_remove(); v.mark_for_deletion(); } if !self.script.is_locked() { @@ -207,7 +213,19 @@ impl ScriptContainer { impl From for ScriptContainer { fn from(a: ScriptHolder) -> Self { - Self { script: a } + Self { + script: a, + join_handle: RwLock::new(None), + } + } +} + +impl Clone for ScriptContainer { + fn clone(&self) -> Self { + Self { + script: self.script.clone(), + join_handle: RwLock::new(None), + } } } @@ -215,8 +233,6 @@ impl From for ScriptContainer { mod tests { use super::*; use std::sync::atomic::{AtomicBool, AtomicPtr}; - use std::thread::sleep; - use std::time::Duration; pub struct TestScript { name: StringKey, @@ -361,7 +377,12 @@ mod tests { .downcast_ref::() .unwrap() .test(script2); - sleep(Duration::from_micros(500)); + let mut jh = container.join_handle.write(); + if jh.is_some() { + let h = jh.take().unwrap(); + h.join().unwrap(); + } + assert_eq!( container.script.read().as_ref().unwrap().name(), &StringKey::new("script2")