From a295107baca4a5fef79c3353e44989874f448de8 Mon Sep 17 00:00:00 2001 From: luaneko Date: Wed, 25 Jun 2025 10:43:00 +1000 Subject: [PATCH] Create channel and task libs --- crates/lb/src/channel.rs | 64 ++++++++++++++++++++++++++++++++++++++++ crates/lb/src/task.rs | 46 +++++++++++++++++++++++++++++ crates/lb/tests/net.rs | 32 ++++++++++++++++++++ crates/lb/tests/task.rs | 35 ++++++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 crates/lb/src/channel.rs create mode 100644 crates/lb/src/task.rs create mode 100644 crates/lb/tests/net.rs create mode 100644 crates/lb/tests/task.rs diff --git a/crates/lb/src/channel.rs b/crates/lb/src/channel.rs new file mode 100644 index 0000000..3c206c4 --- /dev/null +++ b/crates/lb/src/channel.rs @@ -0,0 +1,64 @@ +// use flume::{Receiver, Sender}; +use luaffi::{cdef, metatype}; + +#[cdef] +pub struct lb_libchannel; + +#[metatype] +impl lb_libchannel { + #[new] + extern "Lua-C" fn new() -> Self { + Self + } + + extern "Lua" fn unbounded(self) { + let (send, recv) = (__new(__ct.lb_sender), __new(__ct.lb_receiver)); + self.__unbounded(send, recv); + (send, recv) + } + + extern "Lua" fn bounded(self, cap: number) { + assert(cap >= 0, "channel capacity must be nonnegative"); + let (send, recv) = (__new(__ct.lb_sender), __new(__ct.lb_receiver)); + self.__bounded(cap, send, recv); + (send, recv) + } + + // extern "Lua-C" fn __unbounded(&self, s: *mut lb_sender, r: *mut lb_receiver) { + // let (send, recv) = flume::unbounded(); + // unsafe { + // ptr::write(s, lb_sender { send }); + // ptr::write(r, lb_receiver { recv }); + // } + // } + + // extern "Lua-C" fn __bounded(&self, cap: usize, s: *mut lb_sender, r: *mut lb_receiver) { + // let (send, recv) = flume::bounded(cap); + // unsafe { + // ptr::write(s, lb_sender { send }); + // ptr::write(r, lb_receiver { recv }); + // } + // } +} + +// #[cdef] +// pub struct lb_sender { +// #[opaque] +// send: Sender, +// } + +// #[metatype] +// impl lb_sender { +// extern "Lua" fn send(self, value: _) { +// let key = __ref(value); +// } +// } + +// #[cdef] +// pub struct lb_receiver { +// #[opaque] +// recv: Receiver, +// } + +// #[metatype] +// impl lb_receiver {} diff --git a/crates/lb/src/task.rs b/crates/lb/src/task.rs new file mode 100644 index 0000000..dd0596d --- /dev/null +++ b/crates/lb/src/task.rs @@ -0,0 +1,46 @@ +use crate::runtime::spawn; +use luaffi::{cdef, metatype}; +use std::{ffi::c_int, process}; +use tokio::task::JoinHandle; + +#[cdef] +pub struct lb_libtask; + +#[metatype] +impl lb_libtask { + #[new] + extern "Lua-C" fn new() -> Self { + Self + } + + pub extern "Lua" fn spawn(self, f: function, ...) { + // pack the function and its arguments into a table and pass its ref to rust + self.__spawn(__ref(__tpack(f, variadic!()))) + } + + extern "Lua-C" fn __spawn(&self, key: c_int) -> lb_task { + let handle = spawn(async move |s| { + // SAFETY: key is always unique, created by __ref above + let arg = unsafe { s.new_ref_unchecked(key) }; + s.resize(0); + s.push(arg); + let narg = s.unpack(1, 1, None) - 1; + println!("{s:?}"); + if let Err(_err) = s.call_async(narg, 0).await { + process::exit(1) + } + println!("{s:?}"); + }); + + lb_task { handle } + } +} + +#[cdef] +pub struct lb_task { + #[opaque] + handle: JoinHandle<()>, +} + +#[metatype] +impl lb_task {} diff --git a/crates/lb/tests/net.rs b/crates/lb/tests/net.rs new file mode 100644 index 0000000..680bd45 --- /dev/null +++ b/crates/lb/tests/net.rs @@ -0,0 +1,32 @@ +use lb::runtime; +use luaify::luaify; +use luajit::{Chunk, LoadMode}; +use tokio::test; + +async fn run_lua(s: &'static str) { + let rt = runtime::Builder::new().build().unwrap(); + let task = rt.spawn(async move |state| { + println!("executing test chunk: {s}"); + + state + .load(Chunk::new(s).mode(LoadMode::TEXT)) + .unwrap_or_else(|err| panic!("{err}")); + + state + .call_async(0, 0) + .await + .unwrap_or_else(|err| panic!("{err}")); + }); + + rt.await; + task.await.unwrap_or_else(|err| panic!("{err}")); +} + +#[test] +async fn ipaddr() { + run_lua(luaify!({ + let net = require("lb:net"); + print(net.ipaddr("127.0.0.1")); + })) + .await +} diff --git a/crates/lb/tests/task.rs b/crates/lb/tests/task.rs new file mode 100644 index 0000000..76026be --- /dev/null +++ b/crates/lb/tests/task.rs @@ -0,0 +1,35 @@ +use lb::runtime; +use luaify::luaify; +use luajit::{Chunk, LoadMode}; +use tokio::test; + +async fn run_lua(s: &'static str) { + let rt = runtime::Builder::new().build().unwrap(); + let task = rt.spawn(async move |state| { + println!("executing test chunk: {s}"); + + state + .load(Chunk::new(s).mode(LoadMode::TEXT)) + .unwrap_or_else(|err| panic!("{err}")); + + state + .call_async(0, 0) + .await + .unwrap_or_else(|err| panic!("{err}")); + }); + + rt.await; + task.await.unwrap_or_else(|err| panic!("{err}")); +} + +#[test] +async fn task_test() { + run_lua(luaify!({ + let thing = spawn(|| { + print("spawn callback!!!!!!!!!!!!!"); + }); + print("thing is", thing); + // + })) + .await +}