2014-12-11 3 views
3

В настоящее время я столкнулся с проблемой, что вы не можете использовать метод __gc для таблиц в Lua 5.1, поскольку они реализованы в Lua 5.2. Тем не менее, я хочу выпустить выделенные ресурсы, как только таблица lua будет собрана. Можно ли сделать обходное решение, которое дает мне функциональность __gc metamethod в Lua 5.2 для Lua 5.1?Обходное решение Lua 5.1 для метаданных __gc для таблиц

+2

Используйте прокси-объект в таблице и поставьте на него метаметод '__gc'. Когда таблица будет собрана, прокси-сервер затем будет собран и будет вызываться метод '__gc'. Хотя это может потребовать дополнительных циклов gc. –

ответ

3

В lua 5.1 единственные значения lua, которые работают с __gc metamethod, равны userdata. Естественно, любой хак или обходное решение должно будет включать в себя userdata. Обычно нет способа просто создать newuserdata со стороны lua, но есть одна «скрытая» недокументированная функция newproxy для этого.

newproxy принимает необязательный параметр bool или userdata. Если вы перейдете в true, тогда вы получите данные пользователя с новым присоединенным метатетом. Если вы передаете в другом userdata то новый UserData будет назначен тот же метатаблицу, как один принятый в

Итак, теперь вы можете просто взломать вместе функцию, которая будет делать __gc работу по таблицам:.

function setmt__gc(t, mt) 
    local prox = newproxy(true) 
    getmetatable(prox).__gc = function() mt.__gc(t) end 
    t[prox] = true 
    return setmetatable(t, mt) 
end 

И быстрый тест, чтобы подтвердить поведение:

iscollected = false 
function gctest(self) 
    iscollected = true 
    print("cleaning up:", self) 
end 

test = setmt__gc({}, {__gc = gctest}) 
collectgarbage() 
assert(not iscollected) 

test = nil 
collectgarbage() 
assert(iscollected) 

IDEOne Demo

Обратите внимание, что Lua 5.2+ и позже уже не имеют newproxy, так как __gc официально поддерживается на столах.

+0

При использовании предлагаемого решения есть одна вещь - если вы пройдете по таблице по парам(), вы получите один ключ добавления. Возможно, избежать этого, используя прокси-объект с правильными метаметками вместо исходной таблицы. –

+0

Что вы подразумеваете под этим? – Turakar

Смежные вопросы