corelib.lua
3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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