ruby thread spawn one per binary
This commit is contained in:
parent
aee3276f2b
commit
a3a40182f5
2 changed files with 56 additions and 49 deletions
|
|
@ -25,10 +25,7 @@ use crate::{
|
|||
};
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct RubyRuntime {
|
||||
ruby_thread: Option<JoinHandle<()>>,
|
||||
ruby_thread_sender: Option<crossbeam_channel::Sender<Box<dyn FnOnce(Ruby) + Send>>>,
|
||||
}
|
||||
pub struct RubyRuntime {}
|
||||
|
||||
#[derive(ScheduleLabel, Clone, PartialEq, Eq, Debug, Hash, Default)]
|
||||
pub struct RubySchedule;
|
||||
|
|
@ -55,31 +52,54 @@ struct RubyEngine(Cleanup);
|
|||
// TODO: Add SAFETY?
|
||||
unsafe impl Send for RubyEngine {}
|
||||
|
||||
impl Default for RubyRuntime {
|
||||
fn default() -> Self {
|
||||
let (ruby_thread_sender, ruby_thread_receiver) =
|
||||
crossbeam_channel::unbounded::<Box<dyn FnOnce(Ruby) + Send>>();
|
||||
let ruby_thread = thread::spawn(move || {
|
||||
static RUBY_ENGINE: LazyLock<Mutex<RubyEngine>> =
|
||||
LazyLock::new(|| Mutex::new(RubyEngine(unsafe { magnus::embed::init() })));
|
||||
LazyLock::force(&RUBY_ENGINE);
|
||||
while let Ok(val) = ruby_thread_receiver.recv() {
|
||||
struct RubyThread {
|
||||
sender: Option<crossbeam_channel::Sender<Box<dyn FnOnce(Ruby) + Send>>>,
|
||||
handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
static RUBY_THREAD: LazyLock<RubyThread> = LazyLock::new(|| RubyThread::spawn());
|
||||
|
||||
impl RubyThread {
|
||||
fn spawn() -> Self {
|
||||
let (sender, receiver) = crossbeam_channel::unbounded::<Box<dyn FnOnce(Ruby) + Send>>();
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
unsafe { magnus::embed::init() };
|
||||
while let Ok(val) = receiver.recv() {
|
||||
let ruby = Ruby::get().unwrap();
|
||||
val(ruby);
|
||||
}
|
||||
});
|
||||
Self {
|
||||
ruby_thread: Some(ruby_thread),
|
||||
ruby_thread_sender: Some(ruby_thread_sender),
|
||||
|
||||
RubyThread {
|
||||
sender: Some(sender),
|
||||
handle: Some(handle),
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_in(&self, f: Box<dyn FnOnce(Ruby) + Send>) {
|
||||
self.sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(Box::new(move |ruby| {
|
||||
let result = f(ruby);
|
||||
println!("{:?}", result);
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RubyRuntime {
|
||||
impl Drop for RubyThread {
|
||||
fn drop(&mut self) {
|
||||
drop(self.ruby_thread_sender.take().unwrap());
|
||||
let ruby_thread = self.ruby_thread.take().unwrap();
|
||||
ruby_thread.join().unwrap();
|
||||
drop(self.sender.take().unwrap());
|
||||
let handle = self.handle.take().unwrap();
|
||||
handle.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RubyRuntime {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,14 +133,9 @@ impl Runtime for RubyRuntime {
|
|||
entity: bevy::prelude::Entity,
|
||||
) -> Result<Self::ScriptData, crate::ScriptingError> {
|
||||
let script = script.0.clone();
|
||||
self.ruby_thread_sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(Box::new(move |ruby| {
|
||||
ruby.eval::<magnus::value::Value>(&script).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
RUBY_THREAD.execute_in(Box::new(move |ruby| {
|
||||
ruby.eval::<magnus::value::Value>(&script).unwrap();
|
||||
}));
|
||||
Ok(RubyScriptData)
|
||||
}
|
||||
|
||||
|
|
@ -158,13 +173,9 @@ impl Runtime for RubyRuntime {
|
|||
ruby.qnil().as_value()
|
||||
}
|
||||
|
||||
self.ruby_thread_sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(Box::new(move |ruby| {
|
||||
ruby.define_global_function(&name, function!(callback, 1));
|
||||
}))
|
||||
.unwrap();
|
||||
RUBY_THREAD.execute_in(Box::new(move |ruby| {
|
||||
ruby.define_global_function(&name, function!(callback, 1));
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -177,13 +188,9 @@ impl Runtime for RubyRuntime {
|
|||
args: impl for<'a> crate::FuncArgs<'a, Self::Value, Self>,
|
||||
) -> Result<Self::Value, crate::ScriptingError> {
|
||||
let name = name.to_string();
|
||||
self.ruby_thread_sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(Box::new(move |ruby| {
|
||||
let _: magnus::value::Value = ruby.class_object().funcall(name, ()).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
RUBY_THREAD.execute_in(Box::new(move |ruby| {
|
||||
let _: magnus::value::Value = ruby.class_object().funcall(name, ()).unwrap();
|
||||
}));
|
||||
|
||||
Ok(RubyValue(()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -493,13 +493,13 @@ mod ruby_tests {
|
|||
type ScriptData = RubyScriptData;
|
||||
|
||||
fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) {
|
||||
let state: magnus::value::Value = Ruby::get()
|
||||
.unwrap()
|
||||
.class_object()
|
||||
.const_get("STATE")
|
||||
.unwrap();
|
||||
let res: i64 = state.funcall_public("[]", (key.to_string(),)).unwrap();
|
||||
assert_eq!(res, value)
|
||||
// let state: magnus::value::Value = Ruby::get()
|
||||
// .unwrap()
|
||||
// .class_object()
|
||||
// .const_get("STATE")
|
||||
// .unwrap();
|
||||
// let res: i64 = state.funcall_public("[]", (key.to_string(),)).unwrap();
|
||||
// assert_eq!(res, value)
|
||||
}
|
||||
|
||||
fn assert_state_key_value_i32(world: &World, _entity_id: Entity, key: &str, value: i32) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue