mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
More robust task.spawn implementation
This commit is contained in:
parent
ecf5c9db44
commit
d7404679c7
1 changed files with 47 additions and 14 deletions
|
@ -9,12 +9,58 @@ use crate::lune::{scheduler::Scheduler, util::TableBuilder};
|
|||
mod tof;
|
||||
use tof::LuaThreadOrFunction;
|
||||
|
||||
/*
|
||||
The spawn function needs special treatment,
|
||||
we need to yield right away to allow the
|
||||
spawned task to run until first yield
|
||||
|
||||
1. Schedule this current thread at the front
|
||||
2. Schedule given thread/function at the front,
|
||||
the previous schedule now comes right after
|
||||
3. Give control over to the scheduler, which will
|
||||
resume the above tasks in order when its ready
|
||||
*/
|
||||
const SPAWN_IMPL_LUA: &str = r#"
|
||||
push(currentThread())
|
||||
local thread = push(...)
|
||||
yield()
|
||||
return thread
|
||||
"#;
|
||||
|
||||
pub fn create(lua: &'static Lua) -> LuaResult<LuaTable<'_>> {
|
||||
let coroutine_running = lua
|
||||
.globals()
|
||||
.get::<_, LuaTable>("coroutine")?
|
||||
.get::<_, LuaFunction>("running")?;
|
||||
let coroutine_yield = lua
|
||||
.globals()
|
||||
.get::<_, LuaTable>("coroutine")?
|
||||
.get::<_, LuaFunction>("yield")?;
|
||||
let push_front =
|
||||
lua.create_function(|lua, (tof, args): (LuaThreadOrFunction, LuaMultiValue)| {
|
||||
let thread = tof.into_thread(lua)?;
|
||||
let sched = lua
|
||||
.app_data_ref::<&Scheduler>()
|
||||
.expect("Lua struct is missing scheduler");
|
||||
sched.push_front(thread.clone(), args)?;
|
||||
Ok(thread)
|
||||
})?;
|
||||
let task_spawn_env = TableBuilder::new(lua)?
|
||||
.with_value("currentThread", coroutine_running)?
|
||||
.with_value("yield", coroutine_yield)?
|
||||
.with_value("push", push_front)?
|
||||
.build_readonly()?;
|
||||
let task_spawn = lua
|
||||
.load(SPAWN_IMPL_LUA)
|
||||
.set_name("task.spawn")
|
||||
.set_environment(task_spawn_env)
|
||||
.into_function()?;
|
||||
|
||||
TableBuilder::new(lua)?
|
||||
.with_function("cancel", task_cancel)?
|
||||
.with_function("defer", task_defer)?
|
||||
.with_function("delay", task_delay)?
|
||||
.with_function("spawn", task_spawn)?
|
||||
.with_value("spawn", task_spawn)?
|
||||
.with_async_function("wait", task_wait)?
|
||||
.build_readonly()
|
||||
}
|
||||
|
@ -69,19 +115,6 @@ where
|
|||
Ok(thread)
|
||||
}
|
||||
|
||||
fn task_spawn<'lua>(
|
||||
lua: &'lua Lua,
|
||||
(tof, args): (LuaThreadOrFunction<'lua>, LuaMultiValue<'_>),
|
||||
) -> LuaResult<LuaThread<'lua>> {
|
||||
let thread = tof.into_thread(lua)?;
|
||||
let resume = lua
|
||||
.globals()
|
||||
.get::<_, LuaTable>("coroutine")?
|
||||
.get::<_, LuaFunction>("resume")?;
|
||||
resume.call((thread.clone(), args))?;
|
||||
Ok(thread)
|
||||
}
|
||||
|
||||
async fn task_wait(_: &Lua, secs: Option<f64>) -> LuaResult<f64> {
|
||||
let duration = Duration::from_secs_f64(secs.unwrap_or_default());
|
||||
|
||||
|
|
Loading…
Reference in a new issue