Made time limit enforcement in __gc wrapper more memory friendly, closes #1079.

This commit is contained in:
Florian Nücke 2015-04-17 20:14:51 +02:00
parent c62feb7136
commit d03e78b0cb

View File

@ -634,6 +634,14 @@ local function spcall(...)
end end
end end
local sgcco
local function sgcf(self, gc)
while true do
self, gc = coroutine.yield(pcall(gc, self))
end
end
local function sgc(self) local function sgc(self)
local oldDeadline, oldHitDeadline = deadline, hitDeadline local oldDeadline, oldHitDeadline = deadline, hitDeadline
local mt = debug.getmetatable(self) local mt = debug.getmetatable(self)
@ -642,11 +650,16 @@ local function sgc(self)
if type(gc) ~= "function" then if type(gc) ~= "function" then
return return
end end
local co = coroutine.create(gc) if not sgcco then
debug.sethook(co, checkDeadline, "", hookInterval) sgcco = coroutine.create(sgcf)
end
debug.sethook(sgcco, checkDeadline, "", hookInterval)
deadline, hitDeadline = math.min(oldDeadline, computer.realTime() + 0.5), true deadline, hitDeadline = math.min(oldDeadline, computer.realTime() + 0.5), true
local result, reason = coroutine.resume(co, self) local _, result, reason = coroutine.resume(sgcco, self, gc)
debug.sethook(co) debug.sethook(sgcco)
if coroutine.status(sgcco) == "dead" then
sgcco = nil
end
deadline, hitDeadline = oldDeadline, oldHitDeadline deadline, hitDeadline = oldDeadline, oldHitDeadline
if not result then if not result then
error(reason, 0) error(reason, 0)