dotfiles from arch
This commit is contained in:
121
nvim/mason/packages/lua-language-server/libexec/script/gc.lua
Normal file
121
nvim/mason/packages/lua-language-server/libexec/script/gc.lua
Normal file
@@ -0,0 +1,121 @@
|
||||
local util = require 'utility'
|
||||
|
||||
---@class gc
|
||||
---@field package _list table
|
||||
local mt = {}
|
||||
mt.__index = mt
|
||||
mt.type = 'gc'
|
||||
mt._removed = false
|
||||
|
||||
---@package
|
||||
mt._max = 10
|
||||
|
||||
local function destroyGCObject(obj)
|
||||
local tp = type(obj)
|
||||
if tp == 'function' then
|
||||
xpcall(obj, log.error)
|
||||
elseif tp == 'table' then
|
||||
local remove = obj.remove
|
||||
if type(remove) == 'function' then
|
||||
xpcall(remove, log.error, obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function isRemoved(obj)
|
||||
local tp = type(obj)
|
||||
if tp == 'function' then
|
||||
for i = 1, 1000 do
|
||||
local n, v = debug.getupvalue(obj, i)
|
||||
if not n then
|
||||
if i > 1 then
|
||||
log.warn('函数式析构器没有 removed 上值!', util.dump(debug.getinfo(obj)))
|
||||
end
|
||||
break
|
||||
end
|
||||
if n == 'removed' then
|
||||
if v then
|
||||
return true
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif tp == 'table' then
|
||||
if obj._removed then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function zip(self)
|
||||
local list = self._list
|
||||
local index = 1
|
||||
for _ = 1, #list do
|
||||
local obj = list[index]
|
||||
if not obj then
|
||||
break
|
||||
end
|
||||
if isRemoved(obj) then
|
||||
if index == #list then
|
||||
list[#list] = nil
|
||||
break
|
||||
end
|
||||
list[index] = list[#list]
|
||||
else
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
self._max = #list * 1.5
|
||||
if self._max < 10 then
|
||||
self._max = 10
|
||||
end
|
||||
end
|
||||
|
||||
function mt:remove()
|
||||
if self._removed then
|
||||
return
|
||||
end
|
||||
self._removed = true
|
||||
local list = self._list
|
||||
for i = 1, #list do
|
||||
destroyGCObject(list[i])
|
||||
end
|
||||
end
|
||||
|
||||
--- 标记`obj`在buff移除时自动移除。如果`obj`是个`function`,
|
||||
--- 则直接调用;如果`obj`是个`table`,则调用内部的`remove`方法。
|
||||
--- 其他情况不做处理
|
||||
---@param obj any
|
||||
---@return any
|
||||
function mt:add(obj)
|
||||
if self._removed then
|
||||
destroyGCObject(obj)
|
||||
return nil
|
||||
end
|
||||
self._list[#self._list+1] = obj
|
||||
if #self._list > self._max then
|
||||
zip(self)
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
--- 创建一个gc容器,使用 `gc:add(obj)` 将析构器放入gc容器。
|
||||
---
|
||||
--- 当gc容器被销毁时,会调用内部的析构器(不保证调用顺序)
|
||||
---
|
||||
--- 析构器必须是以下格式中的一种:
|
||||
--- 1. 一个对象,使用 `obj:remove()` 方法来析构,使用 `obj._removed` 属性来标记已被析构。
|
||||
--- 2. 一个析构函数,使用上值 `removed` 来标记已被析构。
|
||||
---
|
||||
--- ```lua
|
||||
--- local gc = ac.gc() -- 创建gc容器
|
||||
--- gc:add(obj1) -- 将obj1放入gc容器
|
||||
--- gc:add(obj2) -- 将obj2放入gc容器
|
||||
--- gc:remove() -- 移除gc容器,同时也会移除obj1与obj2
|
||||
--- ```
|
||||
return function ()
|
||||
return setmetatable({
|
||||
_list = {},
|
||||
}, mt)
|
||||
end
|
||||
Reference in New Issue
Block a user