Skip to content

Commit

Permalink
Add methods LuaRuntime.gccollect() and LuaRuntime.nogc() to control t…
Browse files Browse the repository at this point in the history
…he Lua garbage collector.
  • Loading branch information
scoder committed May 29, 2024
1 parent cc7b1a6 commit 1af4dea
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Lupa change log
===============

2.2 (2024-??-??)
----------------

* A new method ``LuaRuntime.gc()`` was added to control the Lua garbage collector.


2.1 (2024-03-24)
----------------

Expand Down
48 changes: 48 additions & 0 deletions lupa/_lupa.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,23 @@ cdef class LuaRuntime:
finally:
unlock_runtime(self)

def nogc(self):
"""
Return a context manager that temporarily disables the Lua garbage collector.
"""
return _LuaNoGC(self)

def gccollect(self):
"""
Run a full pass of the Lua garbage collector.
"""
assert self._state is not NULL
cdef lua_State *L = self._state
lock_runtime(self)
# Pass third argument for compatibility with Lua 5.[123].
lua.lua_gc(L, lua.LUA_GCCOLLECT, <int> 0)
unlock_runtime(self)

def set_max_memory(self, size_t max_memory, total=False):
"""Set maximum allowed memory for this LuaRuntime.
Expand Down Expand Up @@ -644,6 +661,37 @@ cdef class LuaRuntime:
return 0 # nothing left to return on the stack


@cython.internal
cdef class _LuaNoGC:
"""
A context manager that temporarily disables the Lua garbage collector.
"""
cdef LuaRuntime _runtime

def __cinit__(self, LuaRuntime runtime not None):
self._runtime = runtime

def __enter__(self):
if self._runtime is None:
return # e.g. system teardown
assert self._runtime._state is not NULL
cdef lua_State *L = self._runtime._state
lock_runtime(self._runtime)
# Pass third argument for compatibility with Lua 5.[123].
lua.lua_gc(L, lua.LUA_GCSTOP, <int> 0)
unlock_runtime(self._runtime)

def __exit__(self, *exc):
if self._runtime is None:
return # e.g. system teardown
assert self._runtime._state is not NULL
cdef lua_State *L = self._runtime._state
lock_runtime(self._runtime)
# Pass third argument for compatibility with Lua 5.[123].
lua.lua_gc(L, lua.LUA_GCRESTART, <int> 0)
unlock_runtime(self._runtime)


################################################################################
# decorators for calling Python functions with keyword (named) arguments
# from Lua scripts
Expand Down
14 changes: 14 additions & 0 deletions lupa/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,20 @@ def test_lua_implementation(self):
self.assertTrue(lua_implementation.startswith("Lua"), lua_implementation)
self.assertTrue(lua_implementation.split()[0] in ("Lua", "LuaJIT"), lua_implementation)

def test_lua_gccollect(self):
self.lua.gccollect()

def test_lua_nogc(self):
if self.lua.lua_version >= (5,2):
self.assertTrue(self.lua.eval('collectgarbage("isrunning")'))

with self.lua.nogc():
if self.lua.lua_version >= (5,2):
self.assertFalse(self.lua.eval('collectgarbage("isrunning")'))

if self.lua.lua_version >= (5,2):
self.assertTrue(self.lua.eval('collectgarbage("isrunning")'))

def test_eval(self):
self.assertEqual(2, self.lua.eval('1+1'))

Expand Down

0 comments on commit 1af4dea

Please sign in to comment.