mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 12:43:09 +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))
|
skynet.call(sharetable.address, "lua", "loadtable", filename, skynet.pack(tbl))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local RECORD = {}
|
||||||
function sharetable.query(filename)
|
function sharetable.query(filename)
|
||||||
local newptr = skynet.call(sharetable.address, "lua", "query", filename)
|
local newptr = skynet.call(sharetable.address, "lua", "query", filename)
|
||||||
if newptr then
|
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
|
||||||
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
|
return sharetable
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user