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)]
|
||||
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> {
|
||||
unsafe fn push_to_lua_stack(&self, state: &'a State) -> Result<()>;
|
||||
}
|
||||
|
|
96
src/state.rs
96
src/state.rs
|
@ -4,7 +4,7 @@ use std::{alloc::{self, Layout}, any::TypeId, cell::RefCell, collections::HashMa
|
|||
use lua::lua_gc;
|
||||
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> {
|
||||
let c = unsafe { CStr::from_ptr(ptr) };
|
||||
|
@ -522,6 +522,13 @@ impl State {
|
|||
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> {
|
||||
let s = self.state_ptr();
|
||||
|
||||
|
@ -535,6 +542,7 @@ impl State {
|
|||
Box::from_raw(ar)
|
||||
}
|
||||
|
||||
/// Retrieves the current line of the script
|
||||
pub fn current_line(&self) -> usize {
|
||||
unsafe {
|
||||
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> {
|
||||
unsafe {
|
||||
let _g = StackGuard::new(self);
|
||||
|
@ -589,24 +598,97 @@ impl State {
|
|||
}
|
||||
|
||||
/// Triggers a full garbage-collection cycle.
|
||||
pub fn gc_collect(&self) -> Result<()> {
|
||||
pub fn gc_collect(&self) {
|
||||
unsafe {
|
||||
let s = self.state_ptr();
|
||||
|
||||
lua_gc(s, lua::LUA_GCCOLLECT);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Disable the garbage collector
|
||||
pub fn gc_stop(&self) -> Result<()> {
|
||||
pub fn gc_stop(&self) {
|
||||
unsafe {
|
||||
let s = self.state_ptr();
|
||||
|
||||
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)]
|
||||
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;
|
||||
|
||||
|
@ -120,7 +120,7 @@ mod tests {
|
|||
|
||||
//println!("i = {}", i);
|
||||
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();
|
||||
t.x += 50.0;
|
||||
|
|
|
@ -141,7 +141,7 @@ mod tests {
|
|||
|
||||
//println!("i = {}", i);
|
||||
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;
|
||||
y += 5.0;
|
||||
|
@ -184,7 +184,7 @@ mod tests {
|
|||
}
|
||||
|
||||
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();
|
||||
assert_eq!(100.0, t.x);
|
||||
|
|
Loading…
Reference in New Issue