1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
use std::cell::RefCell;
use mlua::{Lua, Result, Table};
#[test]
fn test_static_lua() -> Result<()> {
let lua = Lua::new().into_static();
thread_local! {
static TABLE: RefCell<Option<Table<'static>>> = RefCell::new(None);
}
let f = lua.create_function(|_, table: Table| {
TABLE.with(|t| {
table.raw_insert(1, "hello")?;
*t.borrow_mut() = Some(table);
Ok(())
})
})?;
f.call(lua.create_table()?)?;
drop(f);
lua.gc_collect()?;
TABLE.with(|t| {
assert!(t.borrow().as_ref().unwrap().len().unwrap() == 1);
*t.borrow_mut() = None;
});
// Consume the Lua instance
unsafe { Lua::from_static(lua) };
Ok(())
}
#[test]
fn test_static_lua_coroutine() -> Result<()> {
let lua = Lua::new().into_static();
thread_local! {
static TABLE: RefCell<Option<Table<'static>>> = RefCell::new(None);
}
let f = lua.create_function(|_, table: Table| {
TABLE.with(|t| {
table.raw_insert(1, "hello")?;
*t.borrow_mut() = Some(table);
Ok(())
})
})?;
let co = lua.create_thread(f)?;
co.resume::<_, ()>(lua.create_table()?)?;
drop(co);
lua.gc_collect()?;
TABLE.with(|t| {
assert_eq!(
t.borrow().as_ref().unwrap().get::<_, String>(1i32).unwrap(),
"hello".to_string()
);
*t.borrow_mut() = None;
});
// Consume the Lua instance
unsafe { Lua::from_static(lua) };
Ok(())
}
#[cfg(feature = "async")]
#[tokio::test]
async fn test_static_async() -> Result<()> {
let lua = Lua::new().into_static();
#[cfg(not(target_arch = "wasm32"))]
async fn sleep_ms(ms: u64) {
tokio::time::sleep(std::time::Duration::from_millis(ms)).await;
}
#[cfg(target_arch = "wasm32")]
async fn sleep_ms(_ms: u64) {
tokio::task::yield_now().await;
}
let timer =
lua.create_async_function(|_, (i, n, f): (u64, u64, mlua::Function)| async move {
tokio::task::spawn_local(async move {
for _ in 0..n {
tokio::task::spawn_local(f.call_async::<(), ()>(()));
sleep_ms(i).await;
}
});
Ok(())
})?;
lua.globals().set("timer", timer)?;
{
let local_set = tokio::task::LocalSet::new();
local_set
.run_until(
lua.load(
r#"
local cnt = 0
timer(1, 100, function()
cnt = cnt + 1
if cnt % 10 == 0 then
collectgarbage()
end
end)
"#,
)
.exec_async(),
)
.await?;
local_set.await;
}
// Consume the Lua instance
unsafe { Lua::from_static(lua) };
Ok(())
}
|