Bind Futures lifetimes to 'lua rather than 'static.
Fix async examples.
This commit is contained in:
parent
7efcee853d
commit
6e2bb73cff
|
@ -61,10 +61,7 @@ impl UserData for LuaTcpStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
async fn run_server(lua: &'static Lua) -> Result<()> {
|
||||
let spawn = lua.create_function(move |_, func: Function| {
|
||||
task::spawn_local(async move { func.call_async::<_, ()>(()).await.unwrap() });
|
||||
Ok(())
|
||||
|
@ -80,20 +77,33 @@ async fn main() -> Result<()> {
|
|||
local addr = ...
|
||||
local listener = tcp.bind(addr)
|
||||
print("listening on "..addr)
|
||||
|
||||
local accept_new = true
|
||||
while true do
|
||||
local stream = listener:accept()
|
||||
local peer_addr = stream:peer_addr()
|
||||
print("connected from "..peer_addr)
|
||||
|
||||
if not accept_new then
|
||||
return
|
||||
end
|
||||
|
||||
spawn(function()
|
||||
while true do
|
||||
local data = stream:read(100)
|
||||
data = data:match("^%s*(.-)%s*$") -- trim
|
||||
print("["..peer_addr.."] "..data)
|
||||
stream:write("got: "..data.."\n")
|
||||
if data == "bye" then
|
||||
stream:write("bye bye\n")
|
||||
stream:close()
|
||||
return
|
||||
end
|
||||
if data == "exit" then
|
||||
stream:close()
|
||||
break
|
||||
accept_new = false
|
||||
return
|
||||
end
|
||||
stream:write("echo: "..data.."\n")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
@ -105,3 +115,15 @@ async fn main() -> Result<()> {
|
|||
.run_until(server.call_async::<_, ()>("0.0.0.0:1234"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let lua = Lua::new().into_static();
|
||||
|
||||
run_server(lua).await.unwrap();
|
||||
|
||||
// Consume the static reference and drop it.
|
||||
// This is safe as long as we don't hold any other references to Lua
|
||||
// or alive resources.
|
||||
unsafe { Lua::from_static(lua) };
|
||||
}
|
||||
|
|
36
src/lua.rs
36
src/lua.rs
|
@ -75,7 +75,7 @@ impl Drop for Lua {
|
|||
extra.registry_unref_list.try_borrow_mut(),
|
||||
"unref list borrowed"
|
||||
) = None;
|
||||
ffi::lua_close(self.state);
|
||||
ffi::lua_close(self.main_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,30 @@ impl Lua {
|
|||
}
|
||||
}
|
||||
|
||||
/// Consumes and leaks `Lua` object, returning a static reference `&'static Lua`.
|
||||
///
|
||||
/// This function is useful when the `Lua` object is supposed to live for the remainder
|
||||
/// of the program's life.
|
||||
/// In particular in asynchronous context this will allow to spawn Lua tasks to execute
|
||||
/// in background.
|
||||
///
|
||||
/// Dropping the returned reference will cause a memory leak. If this is not acceptable,
|
||||
/// the reference should first be wrapped with the [`Lua::from_static`] function producing a `Lua`.
|
||||
/// This `Lua` object can then be dropped which will properly release the allocated memory.
|
||||
///
|
||||
/// [`Lua::from_static`]: #method.from_static
|
||||
pub fn into_static(self) -> &'static Self {
|
||||
Box::leak(Box::new(self))
|
||||
}
|
||||
|
||||
/// Constructs a `Lua` from a static reference to it.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function is unsafe because improper use may lead to memory problems or undefined behavior.
|
||||
pub unsafe fn from_static(lua: &'static Lua) -> Self {
|
||||
*Box::from_raw(lua as *const Lua as *mut Lua)
|
||||
}
|
||||
|
||||
/// Loads the specified set of standard libraries into an existing Lua state.
|
||||
///
|
||||
/// Use the [`StdLib`] flags to specifiy the libraries you want to load.
|
||||
|
@ -529,7 +553,7 @@ impl Lua {
|
|||
A: FromLuaMulti<'callback>,
|
||||
R: ToLuaMulti<'callback>,
|
||||
F: 'static + Fn(&'callback Lua, A) -> FR,
|
||||
FR: 'static + Future<Output = Result<R>>,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.create_async_callback(Box::new(move |lua, args| {
|
||||
let args = match A::from_lua_multi(args, lua) {
|
||||
|
@ -1614,7 +1638,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'static + Future<Output = Result<R>>,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.async_methods
|
||||
.push((name.as_ref().to_vec(), Self::box_async_method(method)));
|
||||
|
@ -1650,7 +1674,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'static + Future<Output = Result<R>>,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.async_methods
|
||||
.push((name.as_ref().to_vec(), Self::box_async_function(function)));
|
||||
|
@ -1748,7 +1772,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'static + Future<Output = Result<R>>,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
Box::new(move |lua, mut args| {
|
||||
let fut_res = || {
|
||||
|
@ -1801,7 +1825,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'static + Future<Output = Result<R>>,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
Box::new(move |lua, args| {
|
||||
let args = match A::from_lua_multi(args, lua) {
|
||||
|
|
|
@ -165,7 +165,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'static + Future<Output = Result<R>>;
|
||||
MR: 'lua + Future<Output = Result<R>>;
|
||||
|
||||
/// Add a regular method as a function which accepts generic arguments, the first argument will
|
||||
/// be a `UserData` of type T if the method is called with Lua method syntax:
|
||||
|
@ -209,7 +209,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'static + Future<Output = Result<R>>;
|
||||
FR: 'lua + Future<Output = Result<R>>;
|
||||
|
||||
/// Add a metamethod which accepts a `&T` as the first parameter.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue