add api for remote thread engine access

This commit is contained in:
Jaroslaw Konik 2025-05-13 17:44:20 +02:00
parent fcf2680824
commit 54a47572db
6 changed files with 84 additions and 10 deletions

View file

@ -77,8 +77,16 @@ where
let result = inner_system.run((), world); let result = inner_system.run((), world);
inner_system.apply_deferred(world); inner_system.apply_deferred(world);
let mut runtime = world.get_resource_mut::<R>().expect("No runtime resource"); let mut runtime = world.get_resource_mut::<R>().expect("No runtime resource");
runtime
.with_engine_mut(move |engine| Out::into_runtime_value_with_engine(result, engine)) if R::is_current_thread() {
runtime.with_engine_mut(move |engine| {
Out::into_runtime_value_with_engine(result, engine)
})
} else {
runtime.with_engine_thread_mut(move |engine| {
Out::into_runtime_value_with_engine(result, engine)
})
}
}; };
let system = IntoSystem::into_system(system_fn); let system = IntoSystem::into_system(system_fn);
CallbackSystem { CallbackSystem {
@ -110,9 +118,15 @@ macro_rules! impl_tuple {
let result = inner_system.run(args, world); let result = inner_system.run(args, world);
inner_system.apply_deferred(world); inner_system.apply_deferred(world);
let mut runtime = world.get_resource_mut::<RN>().expect("No runtime resource"); let mut runtime = world.get_resource_mut::<RN>().expect("No runtime resource");
if RN::is_current_thread() {
runtime.with_engine_mut(move |engine| { runtime.with_engine_mut(move |engine| {
Out::into_runtime_value_with_engine(result, engine) Out::into_runtime_value_with_engine(result, engine)
}) })
} else {
runtime.with_engine_thread_mut(move |engine| {
Out::into_runtime_value_with_engine(result, engine)
})
}
}; };
let system = IntoSystem::into_system(system_fn); let system = IntoSystem::into_system(system_fn);
CallbackSystem { CallbackSystem {

View file

@ -300,10 +300,12 @@ pub trait Runtime: Resource + Default {
type Value: Send + Clone; type Value: Send + Clone;
type RawEngine; type RawEngine;
fn is_current_thread() -> bool;
/// Provides mutable reference to raw scripting engine instance. /// Provides mutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces /// Can be used to directly interact with an interpreter to use interfaces
/// that bevy_scriptum does not provided adapters for. /// that bevy_scriptum does not provided adapters for.
fn with_engine_mut<T: Send + 'static>( fn with_engine_thread_mut<T: Send + 'static>(
&mut self, &mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static, f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T; ) -> T;
@ -311,11 +313,21 @@ pub trait Runtime: Resource + Default {
/// Provides immutable reference to raw scripting engine instance. /// Provides immutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces /// Can be used to directly interact with an interpreter to use interfaces
/// that bevy_scriptum does not provided adapters for. /// that bevy_scriptum does not provided adapters for.
fn with_engine<T: Send + 'static>( fn with_engine_thread<T: Send + 'static>(
&self, &self,
f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static, f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static,
) -> T; ) -> T;
/// Provides mutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces
/// that bevy_scriptum does not provided adapters for.
fn with_engine_mut<T>(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T;
/// Provides immutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces
/// that bevy_scriptum does not provided adapters for.
fn with_engine<T>(&self, f: impl FnOnce(&Self::RawEngine) -> T) -> T;
fn eval( fn eval(
&self, &self,
script: &Self::ScriptAsset, script: &Self::ScriptAsset,

View file

@ -257,6 +257,24 @@ impl Runtime for LuaRuntime {
let engine = self.engine.lock().unwrap(); let engine = self.engine.lock().unwrap();
f(&engine) f(&engine)
} }
fn with_engine_thread_mut<T: Send + 'static>(
&mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T {
todo!()
}
fn with_engine_thread<T: Send + 'static>(
&self,
f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static,
) -> T {
todo!()
}
fn is_current_thread() -> bool {
true
}
} }
impl<'a, T: IntoLuaMulti<'a>> IntoRuntimeValueWithEngine<'a, T, LuaRuntime> for T { impl<'a, T: IntoLuaMulti<'a>> IntoRuntimeValueWithEngine<'a, T, LuaRuntime> for T {

View file

@ -160,6 +160,24 @@ impl Runtime for RhaiRuntime {
fn with_engine<T>(&self, f: impl FnOnce(&Self::RawEngine) -> T) -> T { fn with_engine<T>(&self, f: impl FnOnce(&Self::RawEngine) -> T) -> T {
f(&self.engine) f(&self.engine)
} }
fn with_engine_thread_mut<T: Send + 'static>(
&mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T {
todo!()
}
fn with_engine_thread<T: Send + 'static>(
&self,
f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static,
) -> T {
todo!()
}
fn is_current_thread() -> bool {
true
}
} }
impl Default for RhaiRuntime { impl Default for RhaiRuntime {

View file

@ -136,7 +136,7 @@ impl Runtime for RubyRuntime {
type RawEngine = magnus::Ruby; type RawEngine = magnus::Ruby;
fn with_engine_mut<T: Send + 'static>( fn with_engine_thread_mut<T: Send + 'static>(
&mut self, &mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static, f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T { ) -> T {
@ -146,7 +146,7 @@ impl Runtime for RubyRuntime {
.execute_in(Box::new(move |mut ruby| f(&mut ruby))) .execute_in(Box::new(move |mut ruby| f(&mut ruby)))
} }
fn with_engine<T: Send + 'static>( fn with_engine_thread<T: Send + 'static>(
&self, &self,
f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static, f: impl FnOnce(&Self::RawEngine) -> T + Send + 'static,
) -> T { ) -> T {
@ -156,6 +156,14 @@ impl Runtime for RubyRuntime {
.execute_in(Box::new(move |ruby| f(&ruby))) .execute_in(Box::new(move |ruby| f(&ruby)))
} }
fn with_engine_mut<T>(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T {
unimplemented!();
}
fn with_engine<T>(&self, f: impl FnOnce(&Self::RawEngine) -> T) -> T {
unimplemented!();
}
fn eval( fn eval(
&self, &self,
script: &Self::ScriptAsset, script: &Self::ScriptAsset,
@ -256,6 +264,10 @@ impl Runtime for RubyRuntime {
) -> Result<Self::Value, crate::ScriptingError> { ) -> Result<Self::Value, crate::ScriptingError> {
todo!() todo!()
} }
fn is_current_thread() -> bool {
false
}
} }
pub mod prelude { pub mod prelude {

View file

@ -495,7 +495,7 @@ mod ruby_tests {
fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) { fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) {
let runtime = world.get_resource::<RubyRuntime>().unwrap(); let runtime = world.get_resource::<RubyRuntime>().unwrap();
let key = key.to_string(); let key = key.to_string();
runtime.with_engine(move |engine| { runtime.with_engine_thread(move |engine| {
let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap(); let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap();
let res: i64 = state.funcall_public("[]", (key,)).unwrap(); let res: i64 = state.funcall_public("[]", (key,)).unwrap();
assert_eq!(res, value) assert_eq!(res, value)