Implement all methods for controlling the Lua GC, and some code cleanup
This commit is contained in:
parent
25f4116278
commit
bed5091ecd
65
src/lib.rs
65
src/lib.rs
|
@ -33,71 +33,6 @@ use lref::*;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
/* fn main() -> Result<()> {
|
|
||||||
let lua = State::new();
|
|
||||||
lua.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
|
||||||
|
|
||||||
let globals = lua.globals()?;
|
|
||||||
|
|
||||||
let v1 = RefCell::new(Vec2 { x: 50.0, y: 5.0 });
|
|
||||||
let ud = lua.create_userdata(UserdataRef::from(v1.borrow()))?;
|
|
||||||
globals.set("v1", ud)?;
|
|
||||||
|
|
||||||
let v2 = Vec2 { x: 10.0, y: 15.0 };
|
|
||||||
let ud = lua.create_userdata(UserdataRef::from(&v2))?;
|
|
||||||
globals.set("v2", ud)?;
|
|
||||||
|
|
||||||
//lua.gc_stop()?;
|
|
||||||
let chunk = lua.load(
|
|
||||||
"text.lua",
|
|
||||||
r#"
|
|
||||||
require "util"
|
|
||||||
|
|
||||||
--if vec2 ~= nil then
|
|
||||||
print("v1: (" .. v1.x .. ", " .. v1.y .. ")")
|
|
||||||
--print("v2: (" .. v2.x .. ", " .. v2.y .. ")")
|
|
||||||
--end
|
|
||||||
|
|
||||||
--print("vec2.x = " .. vec2.x)
|
|
||||||
--print("vec2.y = " .. vec2.y)
|
|
||||||
"#,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
const MAX_RUNS: i32 = 400;
|
|
||||||
for i in 0..MAX_RUNS {
|
|
||||||
// I don't care about the result of this execution, so I set the result as a
|
|
||||||
// Value which can be anything
|
|
||||||
//
|
|
||||||
// Chunks can also be executed with: `chunk.execute(())?;`
|
|
||||||
let res = lua.execute_chunk::<_, Value>(&chunk, ());
|
|
||||||
|
|
||||||
// if unwrapped, the new lines in the message would be escaped making
|
|
||||||
// the traceback in the error difficult to read.
|
|
||||||
if let Err(e) = res {
|
|
||||||
panic!("{}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
//print_refs(&lua).unwrap();
|
|
||||||
println!("i = {}", i);
|
|
||||||
globals.set("v1", Value::Nil)?;
|
|
||||||
lua.gc_collect()?;
|
|
||||||
|
|
||||||
let mut t = v1.borrow_mut();
|
|
||||||
t.x += 50.0;
|
|
||||||
t.y += 5.0;
|
|
||||||
drop(t);
|
|
||||||
|
|
||||||
let ud = lua.create_userdata(UserdataRef::from(v1.borrow()))?;
|
|
||||||
globals.raw_set("v1", ud)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(lua::lua_gettop(lua.state_ptr()), 0); // ensure that nothing is left on the stack
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} */
|
|
||||||
|
|
||||||
pub trait PushToLuaStack<'a> {
|
pub trait PushToLuaStack<'a> {
|
||||||
unsafe fn push_to_lua_stack(&self, state: &'a State) -> Result<()>;
|
unsafe fn push_to_lua_stack(&self, state: &'a State) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
94
src/state.rs
94
src/state.rs
|
@ -4,7 +4,7 @@ use std::{alloc::{self, Layout}, any::TypeId, cell::RefCell, collections::HashMa
|
||||||
use lua::lua_gc;
|
use lua::lua_gc;
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
use crate::{lua_error_guard, AnyUserdata, AsLua, Chunk, Error, FromLua, FromLuaStack, FromLuaVec, Function, IntoChunkData, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
use crate::{lua_error_guard, proxy::UserdataProxy, AnyUserdata, AsLua, Chunk, Error, FromLua, FromLuaStack, FromLuaVec, Function, IntoChunkData, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
||||||
|
|
||||||
pub fn ptr_to_string(ptr: *const i8) -> std::result::Result<String, Utf8Error> {
|
pub fn ptr_to_string(ptr: *const i8) -> std::result::Result<String, Utf8Error> {
|
||||||
let c = unsafe { CStr::from_ptr(ptr) };
|
let c = unsafe { CStr::from_ptr(ptr) };
|
||||||
|
@ -522,6 +522,13 @@ impl State {
|
||||||
Ok(mt)
|
Ok(mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a userdata proxy. This proxy has the same metatable as `T`, but has no default value.
|
||||||
|
/// This eliminates the need for `T` to have a default value.
|
||||||
|
pub fn create_proxy<T: Userdata + 'static>(&self) -> Result<AnyUserdata> {
|
||||||
|
self.create_userdata(UserdataProxy::<T>::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the debug info from the Lua stack.
|
||||||
pub(crate) unsafe fn debug_info(&self) -> Box<lua::lua_Debug> {
|
pub(crate) unsafe fn debug_info(&self) -> Box<lua::lua_Debug> {
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
@ -535,6 +542,7 @@ impl State {
|
||||||
Box::from_raw(ar)
|
Box::from_raw(ar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the current line of the script
|
||||||
pub fn current_line(&self) -> usize {
|
pub fn current_line(&self) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ar = self.debug_info();
|
let ar = self.debug_info();
|
||||||
|
@ -542,6 +550,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves a traceback of the Lua stack, optionally prepends the traceback string with `msg`
|
||||||
pub fn traceback(&self, msg: Option<&str>) -> Result<String> {
|
pub fn traceback(&self, msg: Option<&str>) -> Result<String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _g = StackGuard::new(self);
|
let _g = StackGuard::new(self);
|
||||||
|
@ -589,24 +598,97 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triggers a full garbage-collection cycle.
|
/// Triggers a full garbage-collection cycle.
|
||||||
pub fn gc_collect(&self) -> Result<()> {
|
pub fn gc_collect(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
|
|
||||||
lua_gc(s, lua::LUA_GCCOLLECT);
|
lua_gc(s, lua::LUA_GCCOLLECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the garbage collector
|
/// Disable the garbage collector
|
||||||
pub fn gc_stop(&self) -> Result<()> {
|
pub fn gc_stop(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
|
|
||||||
lua_gc(s, lua::LUA_GCSTOP);
|
lua_gc(s, lua::LUA_GCSTOP);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
/// Restarts the garbage collector
|
||||||
|
pub fn gc_restart(&self) {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
lua_gc(s, lua::LUA_GCRESTART);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the current amount of memory used by Lua in kilabytes
|
||||||
|
pub fn memory_usage(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
lua_gc(s, lua::LUA_GCCOUNT) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024.
|
||||||
|
pub fn memory_usage_rem(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
lua_gc(s, lua::LUA_GCCOUNTB) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trigger a step of the garbage collector
|
||||||
|
///
|
||||||
|
/// Lua docs:
|
||||||
|
/// > Performs an incremental step of garbage collection, corresponding to the allocation
|
||||||
|
/// of stepsize Kbytes.
|
||||||
|
pub fn gc_step(&self, step_size: i32) {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
lua_gc(s, lua::LUA_GCSTEP, step_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Changes the collector to incremental mode with the given parameters
|
||||||
|
/// (see [Incremental Garbage Collection](https://www.lua.org/manual/5.4/manual.html#2.5.1)).
|
||||||
|
/// Returns the previous mode.
|
||||||
|
pub fn gc_set_incremental(&self, pause: i32, step_mul: i32, step_size: i32) -> GcMode {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
let mode = lua_gc(s, lua::LUA_GCINC, pause, step_mul, step_size);
|
||||||
|
if mode == lua::LUA_GCGEN {
|
||||||
|
GcMode::Generational
|
||||||
|
} else {
|
||||||
|
GcMode::Incremental
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Changes the collector to generational mode with the given parameters
|
||||||
|
/// (see [Generational Garbage Collection](https://www.lua.org/manual/5.4/manual.html#2.5.2)).
|
||||||
|
/// Returns the previous mode.
|
||||||
|
pub fn gc_set_generational(&self, minor_mul: i32, major_mul: i32)-> GcMode {
|
||||||
|
unsafe {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
|
||||||
|
let mode = lua_gc(s, lua::LUA_GCGEN, minor_mul, major_mul);
|
||||||
|
if mode == lua::LUA_GCGEN {
|
||||||
|
GcMode::Generational
|
||||||
|
} else {
|
||||||
|
GcMode::Incremental
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum GcMode {
|
||||||
|
Incremental,
|
||||||
|
Generational,
|
||||||
|
}
|
|
@ -87,9 +87,9 @@ impl<'a, T: Userdata + 'static> Userdata for UserdataRef<'a, T> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{borrow::Borrow, cell::{Ref, RefCell}};
|
use std::cell::{Ref, RefCell};
|
||||||
|
|
||||||
use crate::{tests::Vec2, AnyUserdata, State, StdLibrary, Value};
|
use crate::{tests::Vec2, State, StdLibrary, Value};
|
||||||
|
|
||||||
use super::UserdataRef;
|
use super::UserdataRef;
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ mod tests {
|
||||||
|
|
||||||
//println!("i = {}", i);
|
//println!("i = {}", i);
|
||||||
globals.set("v1", Value::Nil)?;
|
globals.set("v1", Value::Nil)?;
|
||||||
lua.gc_collect()?; // must collect here to drop the Ref
|
lua.gc_collect(); // must collect here to drop the Ref
|
||||||
|
|
||||||
let mut t = v1.borrow_mut();
|
let mut t = v1.borrow_mut();
|
||||||
t.x += 50.0;
|
t.x += 50.0;
|
||||||
|
|
|
@ -141,7 +141,7 @@ mod tests {
|
||||||
|
|
||||||
//println!("i = {}", i);
|
//println!("i = {}", i);
|
||||||
globals.set("v1", Value::Nil)?;
|
globals.set("v1", Value::Nil)?;
|
||||||
lua.gc_collect()?; // must collect here to drop the RefMut
|
lua.gc_collect(); // must collect here to drop the RefMut
|
||||||
|
|
||||||
x += 50.0;
|
x += 50.0;
|
||||||
y += 5.0;
|
y += 5.0;
|
||||||
|
@ -184,7 +184,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
globals.set("v1", Value::Nil)?;
|
globals.set("v1", Value::Nil)?;
|
||||||
lua.gc_collect()?; // must collect here to drop the RefMut
|
lua.gc_collect(); // must collect here to drop the RefMut
|
||||||
|
|
||||||
let t = v1.borrow();
|
let t = v1.borrow();
|
||||||
assert_eq!(100.0, t.x);
|
assert_eq!(100.0, t.x);
|
||||||
|
|
Loading…
Reference in New Issue