mirror of
https://github.com/lune-org/mlua-luau-scheduler.git
synced 2025-04-10 21:40:55 +01:00
Improve ergonomics for callbacks struct, improve examples, docs, naming
This commit is contained in:
parent
f33bb81324
commit
d21b3723f5
7 changed files with 89 additions and 34 deletions
|
@ -23,7 +23,7 @@ pub fn main() -> LuaResult<()> {
|
||||||
// Load the main script into a runtime and run it until completion
|
// Load the main script into a runtime and run it until completion
|
||||||
let rt = Runtime::new(&lua)?;
|
let rt = Runtime::new(&lua)?;
|
||||||
let main = lua.load(MAIN_SCRIPT);
|
let main = lua.load(MAIN_SCRIPT);
|
||||||
rt.push_main(&lua, main, ());
|
rt.push_thread(&lua, main, ());
|
||||||
rt.run_blocking(&lua);
|
rt.run_blocking(&lua);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn main() -> LuaResult<()> {
|
||||||
// Load the main script into a runtime and run it until completion
|
// Load the main script into a runtime and run it until completion
|
||||||
let rt = Runtime::new(&lua)?;
|
let rt = Runtime::new(&lua)?;
|
||||||
let main = lua.load(MAIN_SCRIPT);
|
let main = lua.load(MAIN_SCRIPT);
|
||||||
rt.push_main(&lua, main, ());
|
rt.push_thread(&lua, main, ());
|
||||||
rt.run_blocking(&lua);
|
rt.run_blocking(&lua);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -9,15 +9,22 @@ pub fn main() -> LuaResult<()> {
|
||||||
// Set up persistent lua environment
|
// Set up persistent lua environment
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
||||||
// Load the main script into a runtime
|
// Create a new runtime with custom callbacks
|
||||||
let rt = Runtime::new(&lua)?;
|
let rt = Runtime::new(&lua)?;
|
||||||
|
rt.set_callbacks(
|
||||||
|
&lua,
|
||||||
|
Callbacks::default().on_error(|_, _, e| {
|
||||||
|
println!(
|
||||||
|
"Captured error from Lua!\n{}\n{e}\n{}",
|
||||||
|
"-".repeat(15),
|
||||||
|
"-".repeat(15)
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load and run the main script until completion
|
||||||
let main = lua.load(MAIN_SCRIPT);
|
let main = lua.load(MAIN_SCRIPT);
|
||||||
|
rt.push_thread(&lua, main, ());
|
||||||
// Inject default value & error callbacks - this will print lua errors to stderr
|
|
||||||
Callbacks::default().inject(&lua);
|
|
||||||
|
|
||||||
// Run the main script until completion
|
|
||||||
rt.push_main(&lua, main, ());
|
|
||||||
rt.run_blocking(&lua);
|
rt.run_blocking(&lua);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -45,28 +45,30 @@ pub fn main() -> LuaResult<()> {
|
||||||
fn run<'lua>(lua: &'lua Lua, main: impl IntoLuaThread<'lua>) -> LuaResult<LuaValue> {
|
fn run<'lua>(lua: &'lua Lua, main: impl IntoLuaThread<'lua>) -> LuaResult<LuaValue> {
|
||||||
// Set up runtime (thread queue / async executors)
|
// Set up runtime (thread queue / async executors)
|
||||||
let rt = Runtime::new(lua)?;
|
let rt = Runtime::new(lua)?;
|
||||||
let thread = rt.push_main(lua, main, ());
|
let thread = rt.push_thread(lua, main, ());
|
||||||
lua.set_named_registry_value("mainThread", thread)?;
|
lua.set_named_registry_value("mainThread", thread)?;
|
||||||
|
|
||||||
// Add callbacks to capture resulting value/error of main thread,
|
// Create callbacks to capture resulting value/error of main thread,
|
||||||
// we need to do some tricks to get around lifetime issues with 'lua
|
// we need to do some tricks to get around the lifetime issues with 'lua
|
||||||
// being different inside the callback vs outside the callback for LuaValue
|
// being different inside the callback vs. outside the callback, for LuaValue
|
||||||
let captured_error = Rc::new(Mutex::new(None));
|
let captured_error = Rc::new(Mutex::new(None));
|
||||||
let captured_error_inner = Rc::clone(&captured_error);
|
let captured_error_inner = Rc::clone(&captured_error);
|
||||||
Callbacks::new()
|
rt.set_callbacks(
|
||||||
.on_value(|lua, thread, val| {
|
lua,
|
||||||
let main: LuaThread = lua.named_registry_value("mainThread").unwrap();
|
Callbacks::new()
|
||||||
if main == thread {
|
.on_value(|lua, thread, val| {
|
||||||
lua.set_named_registry_value("mainValue", val).unwrap();
|
let main: LuaThread = lua.named_registry_value("mainThread").unwrap();
|
||||||
}
|
if main == thread {
|
||||||
})
|
lua.set_named_registry_value("mainValue", val).unwrap();
|
||||||
.on_error(move |lua, thread, err| {
|
}
|
||||||
let main: LuaThread = lua.named_registry_value("mainThread").unwrap();
|
})
|
||||||
if main == thread {
|
.on_error(move |lua, thread, err| {
|
||||||
captured_error_inner.lock_blocking().replace(err);
|
let main: LuaThread = lua.named_registry_value("mainThread").unwrap();
|
||||||
}
|
if main == thread {
|
||||||
})
|
captured_error_inner.lock_blocking().replace(err);
|
||||||
.inject(lua);
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// Run until end
|
// Run until end
|
||||||
rt.run_blocking(lua);
|
rt.run_blocking(lua);
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn main() -> LuaResult<()> {
|
||||||
// Load the main script into a runtime and run it until completion
|
// Load the main script into a runtime and run it until completion
|
||||||
let rt = Runtime::new(&lua)?;
|
let rt = Runtime::new(&lua)?;
|
||||||
let main = lua.load(MAIN_SCRIPT);
|
let main = lua.load(MAIN_SCRIPT);
|
||||||
rt.push_main(&lua, main, ());
|
rt.push_thread(&lua, main, ());
|
||||||
rt.run_blocking(&lua);
|
rt.run_blocking(&lua);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -6,16 +6,34 @@ type ErrorCallback = Box<dyn for<'lua> Fn(&'lua Lua, LuaThread<'lua>, LuaError)
|
||||||
const FORWARD_VALUE_KEY: &str = "__runtime__forwardValue";
|
const FORWARD_VALUE_KEY: &str = "__runtime__forwardValue";
|
||||||
const FORWARD_ERROR_KEY: &str = "__runtime__forwardError";
|
const FORWARD_ERROR_KEY: &str = "__runtime__forwardError";
|
||||||
|
|
||||||
|
/**
|
||||||
|
A set of callbacks for thread values and errors.
|
||||||
|
|
||||||
|
These callbacks are used to forward values and errors from
|
||||||
|
Lua threads back to Rust. By default, the runtime will print
|
||||||
|
any errors to stderr and not do any operations with values.
|
||||||
|
|
||||||
|
You can set your own callbacks using the `on_value` and `on_error` builder methods.
|
||||||
|
*/
|
||||||
pub struct Callbacks {
|
pub struct Callbacks {
|
||||||
on_value: Option<ValueCallback>,
|
on_value: Option<ValueCallback>,
|
||||||
on_error: Option<ErrorCallback>,
|
on_error: Option<ErrorCallback>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Callbacks {
|
impl Callbacks {
|
||||||
pub fn new() -> Callbacks {
|
/**
|
||||||
Default::default()
|
Creates a new set of callbacks with no callbacks set.
|
||||||
|
*/
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
on_value: None,
|
||||||
|
on_error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the callback for thread values being yielded / returned.
|
||||||
|
*/
|
||||||
pub fn on_value<F>(mut self, f: F) -> Self
|
pub fn on_value<F>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&Lua, LuaThread, LuaValue) + 'static,
|
F: Fn(&Lua, LuaThread, LuaValue) + 'static,
|
||||||
|
@ -24,6 +42,9 @@ impl Callbacks {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the callback for thread errors.
|
||||||
|
*/
|
||||||
pub fn on_error<F>(mut self, f: F) -> Self
|
pub fn on_error<F>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&Lua, LuaThread, LuaError) + 'static,
|
F: Fn(&Lua, LuaThread, LuaError) + 'static,
|
||||||
|
@ -32,17 +53,27 @@ impl Callbacks {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes any current thread value callback.
|
||||||
|
*/
|
||||||
pub fn without_value_callback(mut self) -> Self {
|
pub fn without_value_callback(mut self) -> Self {
|
||||||
self.on_value.take();
|
self.on_value.take();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes any current thread error callback.
|
||||||
|
*/
|
||||||
pub fn without_error_callback(mut self) -> Self {
|
pub fn without_error_callback(mut self) -> Self {
|
||||||
self.on_error.take();
|
self.on_error.take();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inject(self, lua: &Lua) {
|
pub(crate) fn inject(self, lua: &Lua) {
|
||||||
|
// Remove any previously injected callbacks
|
||||||
|
lua.unset_named_registry_value(FORWARD_VALUE_KEY).ok();
|
||||||
|
lua.unset_named_registry_value(FORWARD_ERROR_KEY).ok();
|
||||||
|
|
||||||
// Create functions to forward values & errors
|
// Create functions to forward values & errors
|
||||||
if let Some(f) = self.on_value {
|
if let Some(f) = self.on_value {
|
||||||
lua.set_named_registry_value(
|
lua.set_named_registry_value(
|
||||||
|
|
|
@ -29,7 +29,8 @@ impl Runtime {
|
||||||
/**
|
/**
|
||||||
Creates a new runtime for the given Lua state.
|
Creates a new runtime for the given Lua state.
|
||||||
|
|
||||||
This will inject some functions to interact with the scheduler / executor.
|
This will inject some functions to interact with the scheduler / executor,
|
||||||
|
as well as the default [`Callbacks`] for thread values and errors.
|
||||||
*/
|
*/
|
||||||
pub fn new(lua: &Lua) -> LuaResult<Runtime> {
|
pub fn new(lua: &Lua) -> LuaResult<Runtime> {
|
||||||
let queue_status = Rc::new(Cell::new(false));
|
let queue_status = Rc::new(Cell::new(false));
|
||||||
|
@ -106,6 +107,9 @@ impl Runtime {
|
||||||
lua.globals().set(GLOBAL_NAME_SPAWN, fn_spawn)?;
|
lua.globals().set(GLOBAL_NAME_SPAWN, fn_spawn)?;
|
||||||
lua.globals().set(GLOBAL_NAME_DEFER, fn_defer)?;
|
lua.globals().set(GLOBAL_NAME_DEFER, fn_defer)?;
|
||||||
|
|
||||||
|
// Finally, inject default callbacks
|
||||||
|
Callbacks::default().inject(lua);
|
||||||
|
|
||||||
Ok(Runtime {
|
Ok(Runtime {
|
||||||
queue_status,
|
queue_status,
|
||||||
queue_spawn,
|
queue_spawn,
|
||||||
|
@ -116,9 +120,20 @@ impl Runtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Pushes a chunk / function / thread to the front of the runtime.
|
Sets the callbacks for this runtime.
|
||||||
|
|
||||||
|
This will overwrite any previously set callbacks, including default ones.
|
||||||
*/
|
*/
|
||||||
pub fn push_main<'lua>(
|
pub fn set_callbacks(&self, lua: &Lua, callbacks: Callbacks) {
|
||||||
|
callbacks.inject(lua);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Pushes a chunk / function / thread to the runtime queue.
|
||||||
|
|
||||||
|
Threads are guaranteed to be resumed in the order that they were pushed to the queue.
|
||||||
|
*/
|
||||||
|
pub fn push_thread<'lua>(
|
||||||
&self,
|
&self,
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
thread: impl IntoLuaThread<'lua>,
|
thread: impl IntoLuaThread<'lua>,
|
||||||
|
|
Loading…
Add table
Reference in a new issue