mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
Refactor codebase
This commit is contained in:
parent
07ae542e28
commit
a3f03fd067
15 changed files with 228 additions and 128 deletions
|
|
@ -3,15 +3,41 @@ if not game then script = require "test/relative-string" end
|
|||
local flags = require(script.Parent.flags)
|
||||
local throw = require(script.Parent.throw)
|
||||
|
||||
--[[
|
||||
|
||||
Cleanups associate a callback with an arbitrary value with an unknown lifetime.
|
||||
Anytime a new callback is registered with a value that already has one registered,
|
||||
the registered callback is ran and then replaced with the new one.
|
||||
|
||||
When the value is eventually garbage collected, Vide checks for callbacks
|
||||
without an associated value, which it will then run and clear, recycling its
|
||||
cleanup id.
|
||||
|
||||
By default the arbitrary value is the function object that calls `cleanup()`.
|
||||
There are exceptions such as with `indexes()` and `values()` where the
|
||||
arbitrary value is manually set to be the new source created instead of the
|
||||
caller, as the same caller can be used to create multiple new objects.
|
||||
|
||||
todo: remove need for ref to id maps?
|
||||
|
||||
]]
|
||||
|
||||
-- maps a ref to cleanup id
|
||||
local ref_to_id = {} :: { [string]: number }
|
||||
-- maps a cleanup id to a ref
|
||||
local id_to_ref = {} :: { [number]: string }
|
||||
-- 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" })
|
||||
|
||||
-- detects in strict mode when multiple cleanups are registered in the same scope
|
||||
local debug_caller_to_line = {} :: { [() -> ()]: number }
|
||||
setmetatable(debug_caller_to_line, { __mode = "k" })
|
||||
|
||||
-- when active, cleanup callbacks are not automatically registered but are
|
||||
-- added to an array for manual registering internally
|
||||
local manual_mode = {
|
||||
caller = false :: false | () -> (),
|
||||
callbacks = {} :: { () -> () }
|
||||
|
|
@ -20,13 +46,14 @@ local manual_mode = {
|
|||
-- todo: rare case where mem address is reused by another function
|
||||
-- does this case handle itself?
|
||||
|
||||
-- registers a callback with the given lifetime using the given ref
|
||||
local function cleanup_ref(ref: string, lifetime: unknown, callback: () -> ())
|
||||
local id = ref_to_id[ref]
|
||||
|
||||
if id then
|
||||
if id then -- invoke previously registered callback then register new one
|
||||
cleanup_callbacks[id]()
|
||||
cleanup_lifetime[id] = lifetime -- rare case where ref is reused while lifetime is nil
|
||||
else
|
||||
else -- no previously registered callback, add and register new one
|
||||
id = #cleanup_callbacks + 1
|
||||
ref_to_id[ref] = id
|
||||
id_to_ref[id :: any] = ref -- todo
|
||||
|
|
@ -36,6 +63,7 @@ local function cleanup_ref(ref: string, lifetime: unknown, callback: () -> ())
|
|||
cleanup_callbacks[id] = callback
|
||||
end
|
||||
|
||||
-- registers a callback with its caller as the lifetime, and caller address as the ref
|
||||
local function cleanup(callback: () -> ())
|
||||
local lifetime = debug.info(2, "f") -- `caller of cleanup() is lifetime of cleanup`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue