luby/crates/lb/src/runtime.rs

87 lines
2.1 KiB
Rust

use crate::{chan::lb_chanlib, fs::lb_fslib, net::lb_netlib, task::lb_tasklib};
use derive_more::{Deref, DerefMut};
use luaffi::{Registry, Type};
use luajit::{Chunk, State};
use std::fmt::Display;
use tokio::{
task::{JoinHandle, LocalSet, futures::TaskLocalFuture, spawn_local},
task_local,
};
#[derive(Debug, Default)]
pub struct Builder {
registry: Registry,
}
impl Builder {
pub fn new() -> Self {
let mut registry = Registry::new();
registry
.preload::<lb_tasklib>("lb:task")
.preload::<lb_chanlib>("lb:channel")
.preload::<lb_fslib>("lb:fs")
.preload::<lb_netlib>("lb:net");
Self { registry }
}
pub fn module<T: Type>(&mut self, name: impl Display) -> &mut Self {
self.registry.preload::<T>(name);
self
}
pub fn registry(&self) -> &Registry {
&self.registry
}
pub fn build(&self) -> luajit::Result<Runtime> {
Ok(Runtime {
state: {
let mut s = State::new()?;
let mut chunk = Chunk::new(self.registry.done());
chunk.extend(include_bytes!("./runtime.lua"));
// println!("{chunk}");
s.eval(chunk.path("[luby]"), 0, 0)?;
s
},
tasks: LocalSet::new(),
})
}
}
#[derive(Debug, Deref, DerefMut)]
pub struct Runtime {
#[deref]
#[deref_mut]
state: State,
tasks: LocalSet,
}
task_local! {
static STATE: State;
}
impl Runtime {
pub fn spawn<T: 'static>(
&self,
f: impl AsyncFnOnce(&mut State) -> T + 'static,
) -> JoinHandle<T> {
self.tasks
.spawn_local(async move { f(&mut STATE.with(|s| s.new_thread())).await })
}
}
pub fn spawn<T: 'static>(f: impl AsyncFnOnce(&mut State) -> T + 'static) -> JoinHandle<T> {
spawn_local(async move { f(&mut STATE.with(|s| s.new_thread())).await })
}
impl IntoFuture for Runtime {
type Output = ();
type IntoFuture = TaskLocalFuture<State, LocalSet>;
fn into_future(self) -> Self::IntoFuture {
STATE.scope(self.state, self.tasks)
}
}