diff --git a/lune.yml b/lune.yml index 32778b2..335cef8 100644 --- a/lune.yml +++ b/lune.yml @@ -74,6 +74,7 @@ globals: - required: false type: table # Task + task.cancel: task.defer: args: - type: thread | function diff --git a/luneTypes.d.luau b/luneTypes.d.luau index a17c55c..6e09afb 100644 --- a/luneTypes.d.luau +++ b/luneTypes.d.luau @@ -53,6 +53,7 @@ declare process: { } declare task: { + cancel: (t: thread) -> (), defer: (f: thread | (A...) -> (R...), A...) -> (R...), delay: (duration: number?, f: thread | (A...) -> (R...), A...) -> (R...), spawn: (f: thread | (A...) -> (R...), A...) -> (R...), diff --git a/src/lib/globals/task.rs b/src/lib/globals/task.rs index abd9792..d0c0e57 100644 --- a/src/lib/globals/task.rs +++ b/src/lib/globals/task.rs @@ -21,6 +21,10 @@ pub struct WaitingThread<'a> { pub fn new<'a>(lua: &'a Lua, _threads: &Arc>>>) -> Result> { // TODO: Figure out how to insert into threads vec ReadonlyTableBuilder::new(lua)? + .with_function("cancel", |lua, thread: Thread| { + thread.reset(lua.create_function(|_, _: ()| Ok(()))?)?; + Ok(()) + })? .with_async_function( "defer", |lua, (func, args): (Function, Variadic)| async move { @@ -31,7 +35,7 @@ pub fn new<'a>(lua: &'a Lua, _threads: &Arc>>>) -> R )? .with_async_function( "delay", - |lua, (func, duration, args): (Function, Option, Variadic)| async move { + |lua, (duration, func, args): (Option, Function, Variadic)| async move { let secs = duration.unwrap_or(DEFAULT_SLEEP_DURATION); time::sleep(Duration::from_secs_f32(secs)).await; let thread = lua.create_thread(func)?; diff --git a/src/lib/lib.rs b/src/lib/lib.rs index cb139b6..46c4a92 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -81,6 +81,7 @@ mod tests { net_request_redirect: "net/request/redirect", net_json_decode: "net/json/decode", net_json_encode: "net/json/encode", + task_cancel: "task/cancel", task_defer: "task/defer", task_delay: "task/delay", task_spawn: "task/spawn", diff --git a/src/lib/utils/table_builder.rs b/src/lib/utils/table_builder.rs index 2527b0f..8fb3a45 100644 --- a/src/lib/utils/table_builder.rs +++ b/src/lib/utils/table_builder.rs @@ -1,6 +1,6 @@ use std::future::Future; -use mlua::{FromLuaMulti, Lua, Result, Table, ToLuaMulti}; +use mlua::{FromLuaMulti, Lua, Result, Table, ToLuaMulti, Value}; pub struct ReadonlyTableBuilder<'lua> { lua: &'lua Lua, @@ -13,6 +13,11 @@ impl<'lua> ReadonlyTableBuilder<'lua> { Ok(Self { lua, tab }) } + pub fn with_value(self, key: &'static str, value: Value) -> Result { + self.tab.raw_set(key, value)?; + Ok(self) + } + pub fn with_table(self, key: &'static str, value: Table) -> Result { self.tab.raw_set(key, value)?; Ok(self) diff --git a/src/tests/task/cancel.luau b/src/tests/task/cancel.luau new file mode 100644 index 0000000..b7df673 --- /dev/null +++ b/src/tests/task/cancel.luau @@ -0,0 +1,23 @@ +-- Cancel should cancel any deferred or delayed threads + +local flag: boolean = false +local thread = task.defer(function() + flag = true +end) +local thread2 = task.delay(0, function() + flag = true +end) +task.cancel(thread) +task.cancel(thread2) +task.wait(0.1) +assert(not flag, "Cancel should handle non-immediate threads") + +-- Cancellation should be as immediate as possible + +local flag2: number = 1 +task.spawn(function() + flag2 = 2 + task.wait() + flag2 = 3 +end) +assert(flag2 == 2, "Cancel should properly handle yielding threads")