4775b3ab7f
Aux would perform unnecessary tasks every frame even when not in use. This has been solved by only running those tasks when Aux is actually doing things.
157 lines
3.0 KiB
Lua
157 lines
3.0 KiB
Lua
if module 'T' then return end
|
|
|
|
local next, getn, setn, tremove, setmetatable = next, getn, table.setn, tremove, setmetatable
|
|
|
|
local wipe, acquire, release
|
|
local pool, pool_size, overflow_pool, auto_release = {}, 0, setmetatable({}, {__mode='k'}), {}
|
|
|
|
function wipe(t)
|
|
setmetatable(t, nil)
|
|
for k in t do
|
|
t[k] = nil
|
|
end
|
|
t.reset, t.reset = nil, 1
|
|
setn(t, 0)
|
|
end
|
|
M.wipe = wipe
|
|
|
|
function acquire()
|
|
if pool_size > 0 then
|
|
pool_size = pool_size - 1
|
|
return pool[pool_size + 1]
|
|
end
|
|
local t = next(overflow_pool)
|
|
if t then
|
|
overflow_pool[t] = nil
|
|
return t
|
|
end
|
|
return {}
|
|
end
|
|
M.acquire = acquire
|
|
|
|
local f = CreateFrame('Frame', 'AuxGCFrame')
|
|
local function AuxGCFrame_OnUpdate()
|
|
for t in auto_release do
|
|
release(t)
|
|
end
|
|
wipe(auto_release)
|
|
this:SetScript("OnUpdate", nil) -- Remove the script, it will be set back if anything is added to auto_release
|
|
end
|
|
local function autoRelease(t)
|
|
auto_release[t] = true
|
|
f:SetScript("OnUpdate", AuxGCFrame_OnUpdate)
|
|
end
|
|
|
|
function release(t)
|
|
wipe(t)
|
|
auto_release[t] = nil
|
|
if pool_size < 50 then
|
|
pool_size = pool_size + 1
|
|
pool[pool_size] = t
|
|
else
|
|
overflow_pool[t] = true
|
|
end
|
|
end
|
|
M.release = release
|
|
|
|
do
|
|
local function f(_, v)
|
|
if v then
|
|
autoRelease(v)
|
|
return v
|
|
end
|
|
end
|
|
M.temp = setmetatable({}, {__metatable=false, __newindex=pass, __call=f, __sub=f})
|
|
end
|
|
do
|
|
local function f(_, v)
|
|
if v then
|
|
auto_release[v] = nil
|
|
return v
|
|
end
|
|
end
|
|
M.static = setmetatable({}, {__metatable=false, __newindex=pass, __call=f, __sub=f})
|
|
end
|
|
|
|
do
|
|
local function unpack(t)
|
|
if getn(t) > 0 then
|
|
return tremove(t, 1), unpack(t)
|
|
else
|
|
release(t)
|
|
end
|
|
end
|
|
M.unpack = unpack
|
|
end
|
|
|
|
M.empty = setmetatable({}, {__metatable=false, __newindex=pass})
|
|
|
|
local vararg
|
|
do
|
|
local MAXPARAMS = 100
|
|
|
|
local code = [[
|
|
local f, setn, acquire, autoRelease = f, setn, acquire, autoRelease
|
|
return function(
|
|
]]
|
|
for i = 1, MAXPARAMS - 1 do
|
|
code = code .. format('a%d,', i)
|
|
end
|
|
code = code .. [[
|
|
overflow)
|
|
if overflow ~= nil then error("T-vararg overflow.", 2) end
|
|
local n = 0
|
|
repeat
|
|
]]
|
|
for i = MAXPARAMS - 1, 1, -1 do
|
|
code = code .. format('if a%1$d ~= nil then n = %1$d; break end;', i)
|
|
end
|
|
code = code .. [[
|
|
until true
|
|
local t = acquire()
|
|
autoRelease(t)
|
|
setn(t, n)
|
|
repeat
|
|
]]
|
|
for i = 1, MAXPARAMS - 1 do
|
|
code = code .. format('if %1$d > n then break end; t[%1$d] = a%1$d;', i)
|
|
end
|
|
code = code .. [[
|
|
until true
|
|
return f(t)
|
|
end
|
|
]]
|
|
|
|
local chunk = loadstring(code)
|
|
local chunkEnv = {setn=setn, acquire=acquire, auto_release=auto_release, autoRelease=autoRelease}
|
|
setfenv(chunk, chunkEnv)
|
|
function vararg(f)
|
|
chunkEnv.f = f
|
|
return chunk()
|
|
end
|
|
M.vararg = setmetatable({}, {
|
|
__metatable = false,
|
|
__sub = function(_, v)
|
|
return vararg(v)
|
|
end,
|
|
})
|
|
end
|
|
|
|
M.list = vararg(function(arg)
|
|
auto_release[arg] = nil
|
|
return arg
|
|
end)
|
|
M.set = vararg(function(arg)
|
|
local t = acquire()
|
|
for _, v in arg do
|
|
t[v] = true
|
|
end
|
|
return t
|
|
end)
|
|
M.map = vararg(function(arg)
|
|
local t = acquire()
|
|
for i = 1, getn(arg), 2 do
|
|
t[arg[i]] = arg[i + 1]
|
|
end
|
|
return t
|
|
end) |