mirror of
https://github.com/lune-org/mlua-luau-scheduler.git
synced 2025-04-04 10:30:56 +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
|
||||
let rt = Runtime::new(&lua)?;
|
||||
let main = lua.load(MAIN_SCRIPT);
|
||||
rt.push_main(&lua, main, ());
|
||||
rt.push_thread(&lua, main, ());
|
||||
rt.run_blocking(&lua);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -29,7 +29,7 @@ pub fn main() -> LuaResult<()> {
|
|||
// Load the main script into a runtime and run it until completion
|
||||
let rt = Runtime::new(&lua)?;
|
||||
let main = lua.load(MAIN_SCRIPT);
|
||||
rt.push_main(&lua, main, ());
|
||||
rt.push_thread(&lua, main, ());
|
||||
rt.run_blocking(&lua);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -9,15 +9,22 @@ pub fn main() -> LuaResult<()> {
|
|||
// Set up persistent lua environment
|
||||
let lua = Lua::new();
|
||||
|
||||
// Load the main script into a runtime
|
||||
// Create a new runtime with custom callbacks
|
||||
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);
|
||||
|
||||
// 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.push_thread(&lua, main, ());
|
||||
rt.run_blocking(&lua);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -45,28 +45,30 @@ pub fn main() -> LuaResult<()> {
|
|||
fn run<'lua>(lua: &'lua Lua, main: impl IntoLuaThread<'lua>) -> LuaResult<LuaValue> {
|
||||
// Set up runtime (thread queue / async executors)
|
||||
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)?;
|
||||
|
||||
// Add callbacks to capture resulting value/error of main thread,
|
||||
// we need to do some tricks to get around lifetime issues with 'lua
|
||||
// being different inside the callback vs outside the callback for LuaValue
|
||||
// Create callbacks to capture resulting value/error of main thread,
|
||||
// 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
|
||||
let captured_error = Rc::new(Mutex::new(None));
|
||||
let captured_error_inner = Rc::clone(&captured_error);
|
||||
Callbacks::new()
|
||||
.on_value(|lua, thread, val| {
|
||||
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 {
|
||||
captured_error_inner.lock_blocking().replace(err);
|
||||
}
|
||||
})
|
||||
.inject(lua);
|
||||
rt.set_callbacks(
|
||||
lua,
|
||||
Callbacks::new()
|
||||
.on_value(|lua, thread, val| {
|
||||
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 {
|
||||
captured_error_inner.lock_blocking().replace(err);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
// Run until end
|
||||
rt.run_blocking(lua);
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn main() -> LuaResult<()> {
|
|||
// Load the main script into a runtime and run it until completion
|
||||
let rt = Runtime::new(&lua)?;
|
||||
let main = lua.load(MAIN_SCRIPT);
|
||||
rt.push_main(&lua, main, ());
|
||||
rt.push_thread(&lua, main, ());
|
||||
rt.run_blocking(&lua);
|
||||
|
||||
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_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 {
|
||||
on_value: Option<ValueCallback>,
|
||||
on_error: Option<ErrorCallback>,
|
||||
}
|
||||
|
||||
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
|
||||
where
|
||||
F: Fn(&Lua, LuaThread, LuaValue) + 'static,
|
||||
|
@ -24,6 +42,9 @@ impl Callbacks {
|
|||
self
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the callback for thread errors.
|
||||
*/
|
||||
pub fn on_error<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Fn(&Lua, LuaThread, LuaError) + 'static,
|
||||
|
@ -32,17 +53,27 @@ impl Callbacks {
|
|||
self
|
||||
}
|
||||
|
||||
/**
|
||||
Removes any current thread value callback.
|
||||
*/
|
||||
pub fn without_value_callback(mut self) -> Self {
|
||||
self.on_value.take();
|
||||
self
|
||||
}
|
||||
|
||||
/**
|
||||
Removes any current thread error callback.
|
||||
*/
|
||||
pub fn without_error_callback(mut self) -> Self {
|
||||
self.on_error.take();
|
||||
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
|
||||
if let Some(f) = self.on_value {
|
||||
lua.set_named_registry_value(
|
||||
|
|
|
@ -29,7 +29,8 @@ impl Runtime {
|
|||
/**
|
||||
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> {
|
||||
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_DEFER, fn_defer)?;
|
||||
|
||||
// Finally, inject default callbacks
|
||||
Callbacks::default().inject(lua);
|
||||
|
||||
Ok(Runtime {
|
||||
queue_status,
|
||||
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,
|
||||
lua: &'lua Lua,
|
||||
thread: impl IntoLuaThread<'lua>,
|
||||
|
|
Loading…
Add table
Reference in a new issue