vide/src/on_gc.luau
Aaron Smith fe3af737be
2023-09-05 18:15:18 +01:00

40 lines
1.3 KiB
Lua

if not game then script = require "test/relative-string" end
local flags = require(script.Parent.flags)
local throw = require(script.Parent.throw)
-- array of all cleanup callbacks
local cleanup_callbacks = {} :: { [number]: () -> () } -- always dense
-- weak array of all cleanup lifetimes
local cleanup_lifetime = {} :: { [number]: unknown } -- can be sparse
setmetatable(cleanup_lifetime :: any, { __mode = "v" })
local function on_gc(lifetime: unknown, callback: () -> ())
local id = #cleanup_callbacks + 1
cleanup_lifetime[id :: any] = lifetime -- todo
cleanup_callbacks[id] = callback
end
local function sweep()
for id = #cleanup_callbacks, 1, -1 do
if cleanup_lifetime[id] == nil then -- lifetime was garbage collected
local callback = cleanup_callbacks[id]
do -- swap and pop
local max_id = #cleanup_callbacks
cleanup_callbacks[id] = cleanup_callbacks[max_id]
cleanup_callbacks[max_id] = nil
cleanup_lifetime[id] = cleanup_lifetime[max_id]
cleanup_lifetime[max_id] = nil
end
local ok, err: string? = pcall(callback)
if not ok then warn(`error occured during cleanup: {err}`) end
end
end
end
return function() return on_gc, sweep end