我有一个表,其键上有弱引用。我用它来“注册”事件:
local events = setmetatable({}, {__mode="k"})
function registerEvent(reference, callback)
events[reference] = callback
end
每隔一段时间我就会执行所有“当前”事件;也就是说,我解析events
表并执行其回调。
function launchEvents()
for reference,callback in pairs(events)
callback(reference)
end
end
此设置通常可以正常工作。一旦引用停止使用,它就会被垃圾收集,其回调将从events
消失。
问题是 - 有时launchEvents
在删除引用时执行,但垃圾收集器仍然没有运行。在这种情况下,我在events
中有一些“幻像引用”,并且对基本上不再存在的对象执行回调。例如,我创建一个按钮并将其与“click”事件相关联。然后我删除按钮(将其设置为零)。大约一秒左右,我仍然可以“点击它”,这是一种耻辱。
我能找到的唯一解决方法是在launchEvents中手动运行GC:
function launchEvents()
collectgarbage()
for reference,callback in pairs(events)
callback(reference)
end
end
但这似乎有点矫枉过正。每秒可以多次调用launchEvents
。我正在调用完整的垃圾收集周期来清理一个表。
这种方法有替代方案吗?我可以“垃圾收集”或“清理”一个弱桌吗?
PS:顺便说一下,我在Lua 5.1中。
答案 0 :(得分:2)
Lua的垃圾收集器不起作用。您可以使用lua_gc
调用LUA_GCSTEP
以递增方式运行它。但这并不能保证会调查任何特定的对象。
您的设计存在根本缺陷。如果你想收集一堆事件,然后执行它们,然后收集一堆新的事件,然后执行它们,那么你必须这样做。你需要明确扔掉旧事件;不要只是将它们放在弱表中,并期望GC将nil
输出参考。
GC与C和C ++中的分配/释放不同。这是不规则和不可靠的。您不应该依赖它来实现实际的设计功能。