lua - Могу ли я «почистить» слабую таблицу, не вызывая весь GC? - PullRequest
1 голос
/ 03 февраля 2012

У меня есть таблица со слабыми ссылками на ее ключи.Я использую его для «регистрации» событий:

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, и обратные вызовы выполняются для объектов, которые в основном больше не существуют.Например, я создаю кнопку и связываю ее с событием «щелчка».Затем я удаляю кнопку (установите ее на ноль).Примерно на секунду я все еще могу «щелкнуть по нему», что является позором.

Единственное исправление, которое я смог найти, - это ручной запуск ГХ в launchEvents:

function launchEvents()
  collectgarbage()
  for reference,callback in pairs(events)
    callback(reference)
  end
end

Но это кажется немного излишним.launchEvents можно вызывать много раз в секунду.Я использую полный цикл сбора мусора только для очистки одной таблицы.

Есть ли альтернатива этому подходу?Можно ли "собрать мусор" или "очистить" только одну слабую таблицу?

PS: я в Lua 5.1, кстати

1 Ответ

2 голосов
/ 03 февраля 2012

Сборщик мусора Lua так не работает. Вы можете запустить его постепенно, вызвав lua_gc с LUA_GCSTEP. Но это не гарантия, что он будет исследовать какой-либо конкретный объект.

Ваш дизайн в корне ошибочен. Если вы хотите собрать группу событий, затем выполнить их, затем собрать новую группу событий, а затем выполнить их, тогда вы должны это сделать. Вам нужно явно выбросить старые события; не просто помещайте их в слабую таблицу и ожидайте, что GC nil из ссылок.

GC не похож на распределение / освобождение в C и C ++. Это нерегулярно и ненадежно. Вы не должны полагаться на это для фактической функциональности дизайна.

...