2023-01-23 02:14:13 +00:00
|
|
|
use std::time::{Duration, Instant};
|
2023-01-21 18:33:33 +00:00
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
use mlua::prelude::*;
|
2023-01-23 02:14:13 +00:00
|
|
|
use smol::Timer;
|
2023-01-21 18:33:33 +00:00
|
|
|
|
2023-01-23 01:18:09 +00:00
|
|
|
use crate::utils::table_builder::TableBuilder;
|
2023-01-21 20:48:56 +00:00
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
pub async fn create(lua: &Lua) -> LuaResult<()> {
|
2023-01-22 20:23:56 +00:00
|
|
|
lua.globals().raw_set(
|
|
|
|
"task",
|
2023-01-23 01:18:09 +00:00
|
|
|
TableBuilder::new(lua)?
|
2023-01-22 21:26:45 +00:00
|
|
|
.with_async_function("cancel", task_cancel)?
|
|
|
|
.with_async_function("defer", task_defer)?
|
|
|
|
.with_async_function("delay", task_delay)?
|
|
|
|
.with_async_function("spawn", task_spawn)?
|
2023-01-22 20:23:56 +00:00
|
|
|
.with_async_function("wait", task_wait)?
|
2023-01-23 01:18:09 +00:00
|
|
|
.build_readonly()?,
|
2023-01-22 21:26:45 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
fn get_or_create_thread_from_arg<'a>(lua: &'a Lua, arg: LuaValue<'a>) -> LuaResult<LuaThread<'a>> {
|
2023-01-23 02:21:11 +00:00
|
|
|
match arg {
|
2023-01-23 02:31:55 +00:00
|
|
|
LuaValue::Thread(thread) => Ok(thread),
|
|
|
|
LuaValue::Function(func) => Ok(lua.create_thread(func)?),
|
|
|
|
val => Err(LuaError::RuntimeError(format!(
|
2023-01-23 02:21:11 +00:00
|
|
|
"Expected type thread or function, got {}",
|
|
|
|
val.type_name()
|
|
|
|
))),
|
|
|
|
}
|
2023-01-22 21:26:45 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
async fn resume_thread(lua: &Lua, thread: LuaThread<'_>, args: LuaMultiValue<'_>) -> LuaResult<()> {
|
|
|
|
let coroutine: LuaTable = lua.globals().raw_get("coroutine")?;
|
|
|
|
let resume: LuaFunction = coroutine.raw_get("resume")?;
|
2023-01-22 22:05:01 +00:00
|
|
|
// FIXME: This is blocking, we should spawn a local tokio task,
|
|
|
|
// but doing that moves "thread" and "args", that both have
|
|
|
|
// the lifetime of the outer function, so it doesn't work
|
|
|
|
resume.call_async((thread, args)).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
async fn task_cancel(lua: &Lua, thread: LuaThread<'_>) -> LuaResult<()> {
|
|
|
|
let coroutine: LuaTable = lua.globals().raw_get("coroutine")?;
|
|
|
|
let close: LuaFunction = coroutine.raw_get("close")?;
|
2023-01-22 21:26:45 +00:00
|
|
|
close.call_async(thread).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
async fn task_defer<'a>(
|
|
|
|
lua: &'a Lua,
|
|
|
|
(tof, args): (LuaValue<'a>, LuaMultiValue<'a>),
|
|
|
|
) -> LuaResult<LuaThread<'a>> {
|
2023-01-22 22:05:01 +00:00
|
|
|
// TODO: Defer (sleep a minimum amount of time)
|
|
|
|
let thread = get_or_create_thread_from_arg(lua, tof)?;
|
|
|
|
resume_thread(lua, thread.clone(), args).await?;
|
|
|
|
Ok(thread)
|
2023-01-22 21:26:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn task_delay<'a>(
|
2023-01-22 22:05:01 +00:00
|
|
|
lua: &'a Lua,
|
2023-01-23 02:31:55 +00:00
|
|
|
(_delay, tof, args): (Option<f32>, LuaValue<'a>, LuaMultiValue<'a>),
|
|
|
|
) -> LuaResult<LuaThread<'a>> {
|
2023-01-22 22:05:01 +00:00
|
|
|
// TODO: Delay by the amount of time wanted
|
|
|
|
let thread = get_or_create_thread_from_arg(lua, tof)?;
|
|
|
|
resume_thread(lua, thread.clone(), args).await?;
|
|
|
|
Ok(thread)
|
2023-01-22 21:26:45 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 02:31:55 +00:00
|
|
|
async fn task_spawn<'a>(
|
|
|
|
lua: &'a Lua,
|
|
|
|
(tof, args): (LuaValue<'a>, LuaMultiValue<'a>),
|
|
|
|
) -> LuaResult<LuaThread<'a>> {
|
2023-01-22 22:05:01 +00:00
|
|
|
let thread = get_or_create_thread_from_arg(lua, tof)?;
|
|
|
|
resume_thread(lua, thread.clone(), args).await?;
|
|
|
|
Ok(thread)
|
2023-01-21 18:33:33 +00:00
|
|
|
}
|
2023-01-22 01:11:17 +00:00
|
|
|
|
2023-01-22 21:26:45 +00:00
|
|
|
// FIXME: It doesn't seem possible to properly make an async wait
|
2023-01-22 01:11:17 +00:00
|
|
|
// function with mlua right now, something breaks when using
|
2023-01-22 21:26:45 +00:00
|
|
|
// the async wait function inside of a coroutine
|
2023-01-23 02:31:55 +00:00
|
|
|
async fn task_wait(_: &Lua, duration: Option<f32>) -> LuaResult<f32> {
|
2023-01-22 21:26:45 +00:00
|
|
|
let start = Instant::now();
|
2023-01-23 02:14:13 +00:00
|
|
|
Timer::after(
|
2023-01-22 21:26:45 +00:00
|
|
|
duration
|
|
|
|
.map(Duration::from_secs_f32)
|
|
|
|
.unwrap_or(Duration::ZERO),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
let end = Instant::now();
|
|
|
|
Ok((end - start).as_secs_f32())
|
2023-01-22 01:11:17 +00:00
|
|
|
}
|