182 lines
3.2 KiB
Lua
182 lines
3.2 KiB
Lua
local core = require "skynet.sharedata.core"
|
|
local type = type
|
|
local rawset = rawset
|
|
|
|
local conf = {}
|
|
|
|
conf.host = {
|
|
new = core.new,
|
|
delete = core.delete,
|
|
getref = core.getref,
|
|
markdirty = core.markdirty,
|
|
incref = core.incref,
|
|
decref = core.decref,
|
|
}
|
|
|
|
local meta = {}
|
|
|
|
local isdirty = core.isdirty
|
|
local index = core.index
|
|
local needupdate = core.needupdate
|
|
local len = core.len
|
|
local core_nextkey = core.nextkey
|
|
|
|
local function findroot(self)
|
|
while self.__parent do
|
|
self = self.__parent
|
|
end
|
|
return self
|
|
end
|
|
|
|
local function update(root, cobj, gcobj)
|
|
root.__obj = cobj
|
|
root.__gcobj = gcobj
|
|
local children = root.__cache
|
|
if children then
|
|
for k,v in pairs(children) do
|
|
local pointer = index(cobj, k)
|
|
if type(pointer) == "userdata" then
|
|
update(v, pointer, gcobj)
|
|
else
|
|
children[k] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function genkey(self)
|
|
local key = tostring(self.__key)
|
|
while self.__parent do
|
|
self = self.__parent
|
|
key = self.__key .. "." .. key
|
|
end
|
|
return key
|
|
end
|
|
|
|
local function getcobj(self)
|
|
local obj = self.__obj
|
|
if isdirty(obj) then
|
|
local newobj, newtbl = needupdate(self.__gcobj)
|
|
if newobj then
|
|
local newgcobj = newtbl.__gcobj
|
|
local root = findroot(self)
|
|
update(root, newobj, newgcobj)
|
|
if obj == self.__obj then
|
|
error ("The key [" .. genkey(self) .. "] doesn't exist after update")
|
|
end
|
|
obj = self.__obj
|
|
end
|
|
end
|
|
return obj
|
|
end
|
|
|
|
function meta:__newindex(key, value)
|
|
error ("Error newindex, the key [" .. genkey(self) .. "]")
|
|
end
|
|
|
|
function meta:__index(key)
|
|
local obj = getcobj(self)
|
|
local v = index(obj, key)
|
|
if type(v) == "userdata" then
|
|
local children = self.__cache
|
|
if children == nil then
|
|
children = {}
|
|
rawset(self, "__cache", children)
|
|
end
|
|
local r = children[key]
|
|
if r then
|
|
return r
|
|
end
|
|
r = setmetatable({
|
|
__obj = v,
|
|
__gcobj = self.__gcobj,
|
|
__parent = self,
|
|
__key = key,
|
|
}, meta)
|
|
children[key] = r
|
|
return r
|
|
else
|
|
return v
|
|
end
|
|
end
|
|
|
|
function meta:__len()
|
|
return len(getcobj(self))
|
|
end
|
|
|
|
function meta:__pairs()
|
|
return conf.next, self, nil
|
|
end
|
|
|
|
function conf.next(obj, key)
|
|
local cobj = getcobj(obj)
|
|
local nextkey = core_nextkey(cobj, key)
|
|
if nextkey then
|
|
return nextkey, obj[nextkey]
|
|
end
|
|
end
|
|
|
|
function conf.box(obj)
|
|
local gcobj = core.box(obj)
|
|
return setmetatable({
|
|
__parent = false,
|
|
__obj = obj,
|
|
__gcobj = gcobj,
|
|
__key = "",
|
|
} , meta)
|
|
end
|
|
|
|
function conf.update(self, pointer)
|
|
local cobj = self.__obj
|
|
assert(isdirty(cobj), "Only dirty object can be update")
|
|
core.update(self.__gcobj, pointer, { __gcobj = core.box(pointer) })
|
|
end
|
|
|
|
function conf.flush(obj)
|
|
getcobj(obj)
|
|
end
|
|
|
|
local function clone_table(cobj)
|
|
local obj = {}
|
|
local key
|
|
while true do
|
|
key = core_nextkey(cobj, key)
|
|
if key == nil then
|
|
break
|
|
end
|
|
local v = index(cobj, key)
|
|
if type(v) == "userdata" then
|
|
v = clone_table(v)
|
|
end
|
|
obj[key] = v
|
|
end
|
|
return obj
|
|
end
|
|
|
|
local function find_node(cobj, key, ...)
|
|
if key == nil then
|
|
return cobj
|
|
end
|
|
local cobj = index(cobj, key)
|
|
if cobj == nil then
|
|
return nil
|
|
end
|
|
if type(cobj) == "userdata" then
|
|
return find_node(cobj, ...)
|
|
end
|
|
return cobj
|
|
end
|
|
|
|
function conf.copy(cobj, ...)
|
|
cobj = find_node(cobj, ...)
|
|
if cobj then
|
|
if type(cobj) == "userdata" then
|
|
return clone_table(cobj)
|
|
else
|
|
return cobj
|
|
end
|
|
end
|
|
end
|
|
|
|
return conf
|