From d4ad835fd80a4fc1367b9ea63f8ccb74b811cf0b Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Mon, 23 Jan 2023 18:52:31 -0500 Subject: [PATCH] Lune library internal util improvements, type definition improvements --- lune.yml | 6 +- luneTypes.d.luau | 10 ++ src/lib/globals/console.rs | 2 +- src/lib/globals/fs.rs | 2 +- src/lib/globals/net.rs | 2 +- src/lib/globals/process.rs | 2 +- src/lib/globals/task.rs | 134 +++++-------------- src/lib/utils/mod.rs | 3 +- src/lib/utils/{table_builder.rs => table.rs} | 0 src/lib/utils/task.rs | 62 +++++++++ 10 files changed, 118 insertions(+), 105 deletions(-) rename src/lib/utils/{table_builder.rs => table.rs} (100%) create mode 100644 src/lib/utils/task.rs diff --git a/lune.yml b/lune.yml index 11b736a..8d2ae18 100644 --- a/lune.yml +++ b/lune.yml @@ -78,17 +78,17 @@ globals: task.defer: args: - type: thread | function - - type: "..." + # - type: "..." task.delay: args: - required: false type: number - type: thread | function - - type: "..." + # - type: "..." task.spawn: args: - type: thread | function - - type: "..." + # - type: "..." task.wait: args: - required: false diff --git a/luneTypes.d.luau b/luneTypes.d.luau index 791075e..6fb9fa3 100644 --- a/luneTypes.d.luau +++ b/luneTypes.d.luau @@ -52,6 +52,15 @@ declare process: { }, } +declare task: { + cancel: (t: thread) -> (), + defer: (f: thread | (...any) -> (...any)) -> thread, + delay: (duration: number?, f: thread | (...any) -> (...any)) -> thread, + spawn: (f: thread | (...any) -> (...any)) -> thread, + wait: (duration: number?) -> (number), +} + +--[[ declare task: { cancel: (t: thread) -> (), defer: (f: thread | (T...) -> (...any), T...) -> thread, @@ -59,3 +68,4 @@ declare task: { spawn: (f: thread | (T...) -> (...any), T...) -> thread, wait: (duration: number?) -> (number), } +]] diff --git a/src/lib/globals/console.rs b/src/lib/globals/console.rs index 79bc86d..f897daf 100644 --- a/src/lib/globals/console.rs +++ b/src/lib/globals/console.rs @@ -2,7 +2,7 @@ use mlua::prelude::*; use crate::utils::{ formatting::{flush_stdout, pretty_format_multi_value, print_color, print_label, print_style}, - table_builder::TableBuilder, + table::TableBuilder, }; pub fn create(lua: &Lua) -> LuaResult<()> { diff --git a/src/lib/globals/fs.rs b/src/lib/globals/fs.rs index 7154052..4ee9652 100644 --- a/src/lib/globals/fs.rs +++ b/src/lib/globals/fs.rs @@ -3,7 +3,7 @@ use std::path::{PathBuf, MAIN_SEPARATOR}; use mlua::prelude::*; use smol::{fs, prelude::*}; -use crate::utils::table_builder::TableBuilder; +use crate::utils::table::TableBuilder; pub fn create(lua: &Lua) -> LuaResult<()> { lua.globals().raw_set( diff --git a/src/lib/globals/net.rs b/src/lib/globals/net.rs index 85381fe..825dbd4 100644 --- a/src/lib/globals/net.rs +++ b/src/lib/globals/net.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use mlua::prelude::*; -use crate::utils::{net::get_request_user_agent_header, table_builder::TableBuilder}; +use crate::utils::{net::get_request_user_agent_header, table::TableBuilder}; pub fn create(lua: &Lua) -> LuaResult<()> { lua.globals().raw_set( diff --git a/src/lib/globals/process.rs b/src/lib/globals/process.rs index c1756e5..19d6014 100644 --- a/src/lib/globals/process.rs +++ b/src/lib/globals/process.rs @@ -4,7 +4,7 @@ use mlua::prelude::*; use os_str_bytes::RawOsString; use smol::{channel::Sender, process::Command, LocalExecutor}; -use crate::{utils::table_builder::TableBuilder, LuneMessage}; +use crate::{utils::table::TableBuilder, LuneMessage}; pub fn create(lua: &Lua, args_vec: Vec) -> LuaResult<()> { // Create readonly args array diff --git a/src/lib/globals/task.rs b/src/lib/globals/task.rs index 59016e3..309bdf0 100644 --- a/src/lib/globals/task.rs +++ b/src/lib/globals/task.rs @@ -4,14 +4,16 @@ use std::{ }; use mlua::prelude::*; -use smol::{channel::Sender, LocalExecutor, Timer}; -use smol::{future::yield_now, prelude::*}; +use smol::Timer; -use crate::{utils::table_builder::TableBuilder, LuneMessage}; +use crate::utils::{ + table::TableBuilder, + task::{run_registered_task, TaskRunMode}, +}; pub fn create(lua: &Lua) -> LuaResult<()> { // HACK: There is no way to call coroutine.close directly from the mlua - // create, so we need to fetch the function and store it in the registry + // crate, so we need to fetch the function and store it in the registry let coroutine: LuaTable = lua.globals().raw_get("coroutine")?; let close: LuaFunction = coroutine.raw_get("close")?; lua.set_named_registry_value("coroutine.close", close)?; @@ -43,51 +45,6 @@ fn tof_to_thread<'a>(lua: &'a Lua, tof: LuaValue<'a>) -> LuaResult } } -async fn run_registered_task( - lua: &Lua, - to_run: impl Future> + 'static, - run_in_background: bool, -) -> LuaResult<()> { - // Fetch global references to task executor & message sender - let exec = lua - .app_data_ref::>() - .unwrap() - .upgrade() - .unwrap(); - let sender = lua - .app_data_ref::>>() - .unwrap() - .upgrade() - .unwrap(); - // Send a message that we have started our task - sender - .send(LuneMessage::Spawned) - .await - .map_err(LuaError::external)?; - // Run the new task separately from the current one using the executor - let sender = sender.clone(); - let task = exec.spawn(async move { - sender - .send(match to_run.await { - Ok(_) => LuneMessage::Finished, - Err(e) => LuneMessage::LuaError(e), - }) - .await - }); - // Wait for the task to complete OR let it run in the background - // Any lua errors will be sent through the message channel back - // to the main thread which will then handle them properly - if run_in_background { - task.detach(); - } else { - task.await.map_err(LuaError::external)?; - } - // Yield once right away to let the above spawned task start working - // instantly, forcing it to run until completion or until it yields - yield_now().await; - Ok(()) -} - async fn task_cancel<'a>(lua: &'a Lua, thread: LuaThread<'a>) -> LuaResult<()> { let close: LuaFunction = lua.named_registry_value("coroutine.close")?; close.call_async::<_, LuaMultiValue>(thread).await?; @@ -100,18 +57,13 @@ async fn task_defer<'a>(lua: &'a Lua, tof: LuaValue<'a>) -> LuaResult(&task_thread_key)?; - if thread.status() == LuaThreadStatus::Resumable { - thread.into_async::<_, LuaMultiValue>(()).await?; - } - Ok(()) - }, - true, - ) + run_registered_task(lua, TaskRunMode::Deferred, async move { + let thread = task_lua.registry_value::(&task_thread_key)?; + if thread.status() == LuaThreadStatus::Resumable { + thread.into_async::<_, LuaMultiValue>(()).await?; + } + Ok(()) + }) .await?; Ok(lua_thread_to_return) } @@ -125,18 +77,14 @@ async fn task_delay<'a>( let task_thread = tof_to_thread(lua, tof)?; let task_thread_key = lua.create_registry_value(task_thread)?; let lua_thread_to_return = lua.registry_value(&task_thread_key)?; - run_registered_task( - lua, - async move { - task_wait(&task_lua, duration).await?; - let thread = task_lua.registry_value::(&task_thread_key)?; - if thread.status() == LuaThreadStatus::Resumable { - thread.into_async::<_, LuaMultiValue>(()).await?; - } - Ok(()) - }, - true, - ) + run_registered_task(lua, TaskRunMode::Deferred, async move { + task_wait(&task_lua, duration).await?; + let thread = task_lua.registry_value::(&task_thread_key)?; + if thread.status() == LuaThreadStatus::Resumable { + thread.into_async::<_, LuaMultiValue>(()).await?; + } + Ok(()) + }) .await?; Ok(lua_thread_to_return) } @@ -147,36 +95,28 @@ async fn task_spawn<'a>(lua: &'a Lua, tof: LuaValue<'a>) -> LuaResult(&task_thread_key)?; - if thread.status() == LuaThreadStatus::Resumable { - thread.into_async::<_, LuaMultiValue>(()).await?; - } - Ok(()) - }, - true, - ) + run_registered_task(lua, TaskRunMode::Instant, async move { + let thread = task_lua.registry_value::(&task_thread_key)?; + if thread.status() == LuaThreadStatus::Resumable { + thread.into_async::<_, LuaMultiValue>(()).await?; + } + Ok(()) + }) .await?; Ok(lua_thread_to_return) } async fn task_wait(lua: &Lua, duration: Option) -> LuaResult { let start = Instant::now(); - run_registered_task( - lua, - async move { - Timer::after( - duration - .map(Duration::from_secs_f32) - .unwrap_or(Duration::ZERO), - ) - .await; - Ok(()) - }, - false, - ) + run_registered_task(lua, TaskRunMode::Blocking, async move { + Timer::after( + duration + .map(Duration::from_secs_f32) + .unwrap_or(Duration::ZERO), + ) + .await; + Ok(()) + }) .await?; let end = Instant::now(); Ok((end - start).as_secs_f32()) diff --git a/src/lib/utils/mod.rs b/src/lib/utils/mod.rs index 7440516..8775dcd 100644 --- a/src/lib/utils/mod.rs +++ b/src/lib/utils/mod.rs @@ -1,3 +1,4 @@ pub mod formatting; pub mod net; -pub mod table_builder; +pub mod table; +pub mod task; diff --git a/src/lib/utils/table_builder.rs b/src/lib/utils/table.rs similarity index 100% rename from src/lib/utils/table_builder.rs rename to src/lib/utils/table.rs diff --git a/src/lib/utils/task.rs b/src/lib/utils/task.rs new file mode 100644 index 0000000..5275a59 --- /dev/null +++ b/src/lib/utils/task.rs @@ -0,0 +1,62 @@ +use std::sync::Weak; + +use mlua::prelude::*; +use smol::{channel::Sender, LocalExecutor}; +use smol::{future::yield_now, prelude::*}; + +use crate::LuneMessage; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum TaskRunMode { + Blocking, + Instant, + Deferred, +} + +pub async fn run_registered_task( + lua: &Lua, + mode: TaskRunMode, + to_run: impl Future> + 'static, +) -> LuaResult<()> { + // Fetch global references to task executor & message sender + let exec = lua + .app_data_ref::>() + .unwrap() + .upgrade() + .unwrap(); + let sender = lua + .app_data_ref::>>() + .unwrap() + .upgrade() + .unwrap(); + // Send a message that we have started our task + sender + .send(LuneMessage::Spawned) + .await + .map_err(LuaError::external)?; + // Run the new task separately from the current one using the executor + let sender = sender.clone(); + let task = exec.spawn(async move { + if mode == TaskRunMode::Deferred { + yield_now().await; + } + sender + .send(match to_run.await { + Ok(_) => LuneMessage::Finished, + Err(e) => LuneMessage::LuaError(e), + }) + .await + }); + // Wait for the task to complete OR let it run in the background + // Any lua errors will be sent through the message channel back + // to the main thread which will then handle them properly + if mode == TaskRunMode::Blocking { + task.await.map_err(LuaError::external)?; + } else { + task.detach(); + } + // Yield once right away to let the above spawned task start working + // instantly, forcing it to run until completion or until it yields + yield_now().await; + Ok(()) +}