HomeServer/lualib/skynet/sharedata/corelib.lua
2024-11-20 15:41:37 +08:00

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