123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- 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
|