corelib.lua 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. local core = require "skynet.sharedata.core"
  2. local type = type
  3. local rawset = rawset
  4. local conf = {}
  5. conf.host = {
  6. new = core.new,
  7. delete = core.delete,
  8. getref = core.getref,
  9. markdirty = core.markdirty,
  10. incref = core.incref,
  11. decref = core.decref,
  12. }
  13. local meta = {}
  14. local isdirty = core.isdirty
  15. local index = core.index
  16. local needupdate = core.needupdate
  17. local len = core.len
  18. local core_nextkey = core.nextkey
  19. local function findroot(self)
  20. while self.__parent do
  21. self = self.__parent
  22. end
  23. return self
  24. end
  25. local function update(root, cobj, gcobj)
  26. root.__obj = cobj
  27. root.__gcobj = gcobj
  28. local children = root.__cache
  29. if children then
  30. for k,v in pairs(children) do
  31. local pointer = index(cobj, k)
  32. if type(pointer) == "userdata" then
  33. update(v, pointer, gcobj)
  34. else
  35. children[k] = nil
  36. end
  37. end
  38. end
  39. end
  40. local function genkey(self)
  41. local key = tostring(self.__key)
  42. while self.__parent do
  43. self = self.__parent
  44. key = self.__key .. "." .. key
  45. end
  46. return key
  47. end
  48. local function getcobj(self)
  49. local obj = self.__obj
  50. if isdirty(obj) then
  51. local newobj, newtbl = needupdate(self.__gcobj)
  52. if newobj then
  53. local newgcobj = newtbl.__gcobj
  54. local root = findroot(self)
  55. update(root, newobj, newgcobj)
  56. if obj == self.__obj then
  57. error ("The key [" .. genkey(self) .. "] doesn't exist after update")
  58. end
  59. obj = self.__obj
  60. end
  61. end
  62. return obj
  63. end
  64. function meta:__newindex(key, value)
  65. error ("Error newindex, the key [" .. genkey(self) .. "]")
  66. end
  67. function meta:__index(key)
  68. local obj = getcobj(self)
  69. local v = index(obj, key)
  70. if type(v) == "userdata" then
  71. local children = self.__cache
  72. if children == nil then
  73. children = {}
  74. rawset(self, "__cache", children)
  75. end
  76. local r = children[key]
  77. if r then
  78. return r
  79. end
  80. r = setmetatable({
  81. __obj = v,
  82. __gcobj = self.__gcobj,
  83. __parent = self,
  84. __key = key,
  85. }, meta)
  86. children[key] = r
  87. return r
  88. else
  89. return v
  90. end
  91. end
  92. function meta:__len()
  93. return len(getcobj(self))
  94. end
  95. function meta:__pairs()
  96. return conf.next, self, nil
  97. end
  98. function conf.next(obj, key)
  99. local cobj = getcobj(obj)
  100. local nextkey = core_nextkey(cobj, key)
  101. if nextkey then
  102. return nextkey, obj[nextkey]
  103. end
  104. end
  105. function conf.box(obj)
  106. local gcobj = core.box(obj)
  107. return setmetatable({
  108. __parent = false,
  109. __obj = obj,
  110. __gcobj = gcobj,
  111. __key = "",
  112. } , meta)
  113. end
  114. function conf.update(self, pointer)
  115. local cobj = self.__obj
  116. assert(isdirty(cobj), "Only dirty object can be update")
  117. core.update(self.__gcobj, pointer, { __gcobj = core.box(pointer) })
  118. end
  119. function conf.flush(obj)
  120. getcobj(obj)
  121. end
  122. local function clone_table(cobj)
  123. local obj = {}
  124. local key
  125. while true do
  126. key = core_nextkey(cobj, key)
  127. if key == nil then
  128. break
  129. end
  130. local v = index(cobj, key)
  131. if type(v) == "userdata" then
  132. v = clone_table(v)
  133. end
  134. obj[key] = v
  135. end
  136. return obj
  137. end
  138. local function find_node(cobj, key, ...)
  139. if key == nil then
  140. return cobj
  141. end
  142. local cobj = index(cobj, key)
  143. if cobj == nil then
  144. return nil
  145. end
  146. if type(cobj) == "userdata" then
  147. return find_node(cobj, ...)
  148. end
  149. return cobj
  150. end
  151. function conf.copy(cobj, ...)
  152. cobj = find_node(cobj, ...)
  153. if cobj then
  154. if type(cobj) == "userdata" then
  155. return clone_table(cobj)
  156. else
  157. return cobj
  158. end
  159. end
  160. end
  161. return conf