Skip to content

Commit b805939

Browse files
committed
Make Lua::weak() method and WeakLua struct public.
This can be useful to prevent circular dependencies between Rust and Lua or check that Lua instance is still alive.
1 parent bd13300 commit b805939

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub use crate::function::{Function, FunctionInfo};
104104
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack};
105105
pub use crate::multi::{MultiValue, Variadic};
106106
pub use crate::scope::Scope;
107-
pub use crate::state::{GCMode, Lua, LuaOptions};
107+
pub use crate::state::{GCMode, Lua, LuaOptions, WeakLua};
108108
pub use crate::stdlib::StdLib;
109109
pub use crate::string::{BorrowedBytes, BorrowedStr, String};
110110
pub use crate::table::{Table, TablePairs, TableSequence};

src/prelude.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use crate::{
1313
UserData as LuaUserData, UserDataFields as LuaUserDataFields, UserDataMetatable as LuaUserDataMetatable,
1414
UserDataMethods as LuaUserDataMethods, UserDataRef as LuaUserDataRef,
1515
UserDataRefMut as LuaUserDataRefMut, UserDataRegistry as LuaUserDataRegistry, Value as LuaValue,
16-
Variadic as LuaVariadic, VmState as LuaVmState,
16+
Variadic as LuaVariadic, VmState as LuaVmState, WeakLua,
1717
};
1818

1919
#[cfg(not(feature = "luau"))]

src/state.rs

+30-7
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ pub struct Lua {
5555
pub(self) collect_garbage: bool,
5656
}
5757

58+
/// Weak reference to Lua instance.
59+
///
60+
/// This can used to prevent circular references between Lua and Rust objects.
5861
#[derive(Clone)]
59-
pub(crate) struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
62+
pub struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
6063

6164
pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
6265

@@ -1995,6 +1998,15 @@ impl Lua {
19951998
LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut std::os::raw::c_void)
19961999
}
19972000

2001+
/// Returns a weak reference to the Lua instance.
2002+
///
2003+
/// This is useful for creating a reference to the Lua instance that does not prevent it from
2004+
/// being deallocated.
2005+
#[inline(always)]
2006+
pub fn weak(&self) -> WeakLua {
2007+
WeakLua(XRc::downgrade(&self.raw))
2008+
}
2009+
19982010
// Luau version located in `luau/mod.rs`
19992011
#[cfg(not(feature = "luau"))]
20002012
fn disable_c_modules(&self) -> Result<()> {
@@ -2038,11 +2050,6 @@ impl Lua {
20382050
LuaGuard(self.raw.lock_arc())
20392051
}
20402052

2041-
#[inline(always)]
2042-
pub(crate) fn weak(&self) -> WeakLua {
2043-
WeakLua(XRc::downgrade(&self.raw))
2044-
}
2045-
20462053
/// Returns a handle to the unprotected Lua state without any synchronization.
20472054
///
20482055
/// This is useful where we know that the lock is already held by the caller.
@@ -2070,14 +2077,30 @@ impl WeakLua {
20702077
Some(LuaGuard::new(self.0.upgrade()?))
20712078
}
20722079

2080+
/// Upgrades the weak Lua reference to a strong reference.
2081+
///
2082+
/// # Panics
2083+
///
2084+
/// Panics if the Lua instance is destroyed.
20732085
#[track_caller]
20742086
#[inline(always)]
2075-
pub(crate) fn upgrade(&self) -> Lua {
2087+
pub fn upgrade(&self) -> Lua {
20762088
Lua {
20772089
raw: self.0.upgrade().expect("Lua instance is destroyed"),
20782090
collect_garbage: false,
20792091
}
20802092
}
2093+
2094+
/// Tries to upgrade the weak Lua reference to a strong reference.
2095+
///
2096+
/// Returns `None` if the Lua instance is destroyed.
2097+
#[inline(always)]
2098+
pub fn try_upgrade(&self) -> Option<Lua> {
2099+
Some(Lua {
2100+
raw: self.0.upgrade()?,
2101+
collect_garbage: false,
2102+
})
2103+
}
20812104
}
20822105

20832106
impl PartialEq for WeakLua {

tests/tests.rs

+18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ use mlua::{
1212
UserData, Value, Variadic,
1313
};
1414

15+
#[test]
16+
fn test_weak_lua() {
17+
let lua = Lua::new();
18+
let weak_lua = lua.weak();
19+
assert!(weak_lua.try_upgrade().is_some());
20+
drop(lua);
21+
assert!(weak_lua.try_upgrade().is_none());
22+
}
23+
24+
#[test]
25+
#[should_panic(expected = "Lua instance is destroyed")]
26+
fn test_weak_lua_panic() {
27+
let lua = Lua::new();
28+
let weak_lua = lua.weak();
29+
drop(lua);
30+
let _ = weak_lua.upgrade();
31+
}
32+
1533
#[cfg(not(feature = "luau"))]
1634
#[test]
1735
fn test_safety() -> Result<()> {

0 commit comments

Comments
 (0)