Lune library internal util improvements, type definition improvements

This commit is contained in:
Filip Tibell 2023-01-23 18:52:31 -05:00
parent 2eb12c9aed
commit d4ad835fd8
No known key found for this signature in database
10 changed files with 118 additions and 105 deletions

View file

@ -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

View file

@ -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: <T...>(f: thread | (T...) -> (...any), T...) -> thread,
@ -59,3 +68,4 @@ declare task: {
spawn: <T...>(f: thread | (T...) -> (...any), T...) -> thread,
wait: (duration: number?) -> (number),
}
]]

View file

@ -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<()> {

View file

@ -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(

View file

@ -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(

View file

@ -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<String>) -> LuaResult<()> {
// Create readonly args array

View file

@ -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<LuaThread<'a>
}
}
async fn run_registered_task(
lua: &Lua,
to_run: impl Future<Output = LuaResult<()>> + 'static,
run_in_background: bool,
) -> LuaResult<()> {
// Fetch global references to task executor & message sender
let exec = lua
.app_data_ref::<Weak<LocalExecutor>>()
.unwrap()
.upgrade()
.unwrap();
let sender = lua
.app_data_ref::<Weak<Sender<LuneMessage>>>()
.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<LuaThread<
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, None).await?;
run_registered_task(lua, TaskRunMode::Deferred, async move {
let thread = task_lua.registry_value::<LuaThread>(&task_thread_key)?;
if thread.status() == LuaThreadStatus::Resumable {
thread.into_async::<_, LuaMultiValue>(()).await?;
}
Ok(())
},
true,
)
})
.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 {
run_registered_task(lua, TaskRunMode::Deferred, async move {
task_wait(&task_lua, duration).await?;
let thread = task_lua.registry_value::<LuaThread>(&task_thread_key)?;
if thread.status() == LuaThreadStatus::Resumable {
thread.into_async::<_, LuaMultiValue>(()).await?;
}
Ok(())
},
true,
)
})
.await?;
Ok(lua_thread_to_return)
}
@ -147,26 +95,20 @@ async fn task_spawn<'a>(lua: &'a Lua, tof: LuaValue<'a>) -> LuaResult<LuaThread<
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 {
run_registered_task(lua, TaskRunMode::Instant, async move {
let thread = task_lua.registry_value::<LuaThread>(&task_thread_key)?;
if thread.status() == LuaThreadStatus::Resumable {
thread.into_async::<_, LuaMultiValue>(()).await?;
}
Ok(())
},
true,
)
})
.await?;
Ok(lua_thread_to_return)
}
async fn task_wait(lua: &Lua, duration: Option<f32>) -> LuaResult<f32> {
let start = Instant::now();
run_registered_task(
lua,
async move {
run_registered_task(lua, TaskRunMode::Blocking, async move {
Timer::after(
duration
.map(Duration::from_secs_f32)
@ -174,9 +116,7 @@ async fn task_wait(lua: &Lua, duration: Option<f32>) -> LuaResult<f32> {
)
.await;
Ok(())
},
false,
)
})
.await?;
let end = Instant::now();
Ok((end - start).as_secs_f32())

View file

@ -1,3 +1,4 @@
pub mod formatting;
pub mod net;
pub mod table_builder;
pub mod table;
pub mod task;

62
src/lib/utils/task.rs Normal file
View file

@ -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<T>(
lua: &Lua,
mode: TaskRunMode,
to_run: impl Future<Output = LuaResult<T>> + 'static,
) -> LuaResult<()> {
// Fetch global references to task executor & message sender
let exec = lua
.app_data_ref::<Weak<LocalExecutor>>()
.unwrap()
.upgrade()
.unwrap();
let sender = lua
.app_data_ref::<Weak<Sender<LuneMessage>>>()
.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(())
}