mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 12:20:41 +00:00
add sharetable update
This commit is contained in:
@@ -190,12 +190,202 @@ function sharetable.loadtable(filename, tbl)
|
||||
skynet.call(sharetable.address, "lua", "loadtable", filename, skynet.pack(tbl))
|
||||
end
|
||||
|
||||
|
||||
local RECORD = {}
|
||||
function sharetable.query(filename)
|
||||
local newptr = skynet.call(sharetable.address, "lua", "query", filename)
|
||||
if newptr then
|
||||
return core.clone(newptr)
|
||||
local t = core.clone(newptr)
|
||||
local map = RECORD[filename]
|
||||
if not map then
|
||||
map = {}
|
||||
RECORD[filename] = map
|
||||
end
|
||||
map[t] = true
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local assert = assert
|
||||
local next = next
|
||||
local rawset = rawset
|
||||
local getuservalue = debug.getuservalue
|
||||
local setuservalue = debug.setuservalue
|
||||
local getupvalue = debug.getupvalue
|
||||
local setupvalue = debug.setupvalue
|
||||
local getlocal = debug.getlocal
|
||||
local setlocal = debug.setlocal
|
||||
|
||||
local NILOBJ = {}
|
||||
local function insert_replace(old_t, new_t, replace_map)
|
||||
for k, ov in pairs(old_t) do
|
||||
if type(ov) == "table" then
|
||||
local nv = new_t[k]
|
||||
if nv == nil then
|
||||
nv = NILOBJ
|
||||
end
|
||||
assert(replace_map[ov] == nil)
|
||||
replace_map[ov] = nv
|
||||
nv = type(nv) == "table" and nv or NILOBJ
|
||||
insert_replace(ov, nv, replace_map)
|
||||
end
|
||||
end
|
||||
replace_map[old_t] = new_t
|
||||
return replace_map
|
||||
end
|
||||
|
||||
|
||||
local function resolve_replace(replace_map)
|
||||
local match = {}
|
||||
local record_map = {}
|
||||
|
||||
local function getnv(v)
|
||||
local nv = replace_map[v]
|
||||
if nv then
|
||||
if nv == NILOBJ then
|
||||
return nil
|
||||
end
|
||||
return nv
|
||||
end
|
||||
assert(false)
|
||||
end
|
||||
|
||||
local function match_value(v)
|
||||
assert(v ~= nil)
|
||||
local tv = type(v)
|
||||
local f = match[tv]
|
||||
if record_map[v] then
|
||||
return
|
||||
end
|
||||
|
||||
if f then
|
||||
record_map[v] = true
|
||||
f(v)
|
||||
end
|
||||
end
|
||||
|
||||
local function match_mt(v)
|
||||
local mt = getmetatable(v)
|
||||
if mt then
|
||||
local nv = replace_map[mt]
|
||||
if nv then
|
||||
nv = getnv(mt)
|
||||
setmetatable(t, nv)
|
||||
else
|
||||
match_value(mt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function match_table(t)
|
||||
for k,v in next, t do
|
||||
local nv = replace_map[v]
|
||||
if nv then
|
||||
nv = getnv(v)
|
||||
rawset(t, k, nv)
|
||||
else
|
||||
match_value(v)
|
||||
end
|
||||
end
|
||||
match_mt(t)
|
||||
end
|
||||
|
||||
local function match_userdata(u)
|
||||
local uv = getuservalue(u)
|
||||
local nv = replace_map[uv]
|
||||
if nv then
|
||||
nv = getnv(uv)
|
||||
setuservalue(u, nv)
|
||||
end
|
||||
match_mt(u)
|
||||
end
|
||||
|
||||
local function match_funcinfo(info)
|
||||
local func = info.func
|
||||
local nups = info.nups
|
||||
for i=1,nups do
|
||||
local name, upv = getupvalue(func, i)
|
||||
local nv = replace_map[upv]
|
||||
if nv then
|
||||
nv = getnv(upv)
|
||||
setupvalue(func, i, nv)
|
||||
elseif upv then
|
||||
match_value(upv)
|
||||
end
|
||||
end
|
||||
|
||||
local level = info.level
|
||||
local curco = info.curco or coroutine.running()
|
||||
if not level then
|
||||
return
|
||||
end
|
||||
local i = 1
|
||||
while true do
|
||||
local name, v = getlocal(curco, level, i)
|
||||
if name == nil then
|
||||
break
|
||||
end
|
||||
if replace_map[v] then
|
||||
local nv = getnv(v)
|
||||
setlocal(curco, level, i, nv)
|
||||
elseif v then
|
||||
match_value(v)
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function match_function(f)
|
||||
local info = debug.getinfo(f)
|
||||
match_funcinfo(info)
|
||||
end
|
||||
|
||||
local function match_thread(co)
|
||||
local level = 1
|
||||
while true do
|
||||
local info = debug.getinfo(co, level)
|
||||
if not info then
|
||||
break
|
||||
end
|
||||
info.level = level
|
||||
info.curco = co
|
||||
match_funcinfo(info)
|
||||
level = level + 1
|
||||
end
|
||||
end
|
||||
|
||||
match["table"] = match_table
|
||||
match["function"] = match_function
|
||||
match["userdata"] = match_userdata
|
||||
match["thread"] = match_thread
|
||||
|
||||
local root = debug.getregistry()
|
||||
assert(replace_map[root] == nil)
|
||||
match_table(root)
|
||||
end
|
||||
|
||||
|
||||
function sharetable.update(...)
|
||||
local names = {...}
|
||||
local replace_map = {}
|
||||
for _, name in ipairs(names) do
|
||||
local map = RECORD[name]
|
||||
if map then
|
||||
local new_t = sharetable.query(name)
|
||||
for old_t,_ in pairs(map) do
|
||||
if old_t ~= new_t then
|
||||
insert_replace(old_t, new_t, replace_map)
|
||||
end
|
||||
end
|
||||
RECORD[name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
resolve_replace(replace_map)
|
||||
end
|
||||
|
||||
return sharetable
|
||||
|
||||
|
||||
Reference in New Issue
Block a user