unref LuaRefs when they are dropped
This commit is contained in:
parent
fcc33d4607
commit
a3dbe82613
|
@ -7,7 +7,7 @@ use mlua_sys as lua;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Function<'a> {
|
pub struct Function<'a> {
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
lref: LuaRef,
|
lref: LuaRef<'a>,
|
||||||
pub(crate) error_handler: Option<Arc<Function<'a>>>,
|
pub(crate) error_handler: Option<Arc<Function<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl<'a> PushToLuaStack<'a> for Function<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Function<'a> {
|
impl<'a> Function<'a> {
|
||||||
pub fn from_ref(state: &'a State, lref: LuaRef) -> Self {
|
pub fn from_ref(state: &'a State, lref: LuaRef<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state,
|
state,
|
||||||
lref,
|
lref,
|
||||||
|
|
45
src/main.rs
45
src/main.rs
|
@ -143,42 +143,55 @@ fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A LuaRef is a a handle to something in Lua.
|
||||||
|
///
|
||||||
|
/// These are created with `luaL_ref`, they can be created from anything on the top of the stack
|
||||||
|
/// with [`LuaRef::from_stack`]. The references are automatically freed with `luaL_unref` when
|
||||||
|
/// the inner Arc detects a single strong count.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LuaRef(Arc<i32>);
|
pub struct LuaRef<'a>(Arc<i32>, &'a State);
|
||||||
|
|
||||||
impl From<i32> for LuaRef {
|
impl<'a> Drop for LuaRef<'a> {
|
||||||
fn from(value: i32) -> Self {
|
fn drop(&mut self) {
|
||||||
Self(Arc::new(value))
|
unsafe {
|
||||||
|
let s = self.1.state_ptr();
|
||||||
|
|
||||||
|
if Arc::strong_count(&self.0) == 1 {
|
||||||
|
lua::luaL_unref(s, lua::LUA_REGISTRYINDEX, *self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaRef {
|
impl<'a> LuaRef<'a> {
|
||||||
|
pub fn new(lua_ref: i32, state: &'a State) -> Self {
|
||||||
|
Self(Arc::new(lua_ref), state)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a reference to what is at the top of the stack.
|
/// Creates a reference to what is at the top of the stack.
|
||||||
pub unsafe fn from_stack(state: &State) -> Result<Self> {
|
pub unsafe fn from_stack(state: &'a State) -> Result<Self> {
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
|
|
||||||
let r = lua::luaL_ref(s, lua::LUA_REGISTRYINDEX);
|
let r = lua::luaL_ref(s, lua::LUA_REGISTRYINDEX);
|
||||||
if r == lua::LUA_REFNIL {
|
if r == lua::LUA_REFNIL {
|
||||||
Err(Error::Nil)
|
Err(Error::Nil)
|
||||||
} else {
|
} else {
|
||||||
Ok(LuaRef::from(r))
|
Ok(LuaRef::new(r, state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PushToLuaStack<'a> for LuaRef {
|
impl<'a> PushToLuaStack<'a> for LuaRef<'a> {
|
||||||
unsafe fn push_to_lua_stack(&self, state: &State) -> Result<()> {
|
unsafe fn push_to_lua_stack(&self, state: &State) -> Result<()> {
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
|
|
||||||
unsafe {
|
state.ensure_stack(1)?;
|
||||||
state.ensure_stack(1)?;
|
let top = lua::lua_gettop(s);
|
||||||
let top = lua::lua_gettop(s);
|
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, *self.0 as i64);
|
||||||
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, *self.0 as i64);
|
let new_top = lua::lua_gettop(s);
|
||||||
let new_top = lua::lua_gettop(s);
|
|
||||||
|
|
||||||
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
||||||
return Err(Error::Nil);
|
return Err(Error::Nil);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -88,8 +88,8 @@ struct ClosureData<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ExtraSpace {
|
struct ExtraSpace<'a> {
|
||||||
userdata_metatables: HashMap<TypeId, LuaRef>,
|
userdata_metatables: HashMap<TypeId, LuaRef<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{ensure_type, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuar
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Table<'a> {
|
pub struct Table<'a> {
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
pub(crate) lref: LuaRef,
|
pub(crate) lref: LuaRef<'a>,
|
||||||
/// a boolean indicating if this Table is a Metatable
|
/// a boolean indicating if this Table is a Metatable
|
||||||
mt_marker: bool,
|
mt_marker: bool,
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ impl<'a> Table<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a table with a lua reference to one.
|
/// Construct a table with a lua reference to one.
|
||||||
pub fn with_ref(state: &'a State, lua_ref: LuaRef, is_metatable: bool) -> Result<Self> {
|
pub fn with_ref(state: &'a State, lua_ref: LuaRef<'a>, is_metatable: bool) -> Result<Self> {
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -255,12 +255,12 @@ pub trait Userdata: Sized {
|
||||||
/// A handle to some userdata on the stack
|
/// A handle to some userdata on the stack
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AnyUserdata<'a> {
|
pub struct AnyUserdata<'a> {
|
||||||
pub(crate) lref: LuaRef,
|
pub(crate) lref: LuaRef<'a>,
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AnyUserdata<'a> {
|
impl<'a> AnyUserdata<'a> {
|
||||||
pub fn from_ref(state: &'a State, lref: LuaRef) -> Self {
|
pub fn from_ref(state: &'a State, lref: LuaRef<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
lref,
|
lref,
|
||||||
state,
|
state,
|
||||||
|
|
Loading…
Reference in New Issue