actboy168 / YDWE

A Tool to Help the Creation of Warcraft III Map
GNU General Public License v3.0
463 stars 139 forks source link

举报 1.32 pairs掉线 #194

Open w4454962 opened 4 years ago

w4454962 commented 4 years ago

重现代码如下 打出来的日志 根本不一致

jass.TimerStart(jass.CreateTimer(), 0.1, true, function () local map = {} for i = 1, 100 do local object = { id = i, } map[object] = math.random(1, 10000) end

if jass.GetLocalPlayer() == jass.Player(math.random(12)) then 
    for i = 1, 100 do
        local object = {}
    end
end 

for object, num in pairs(map) do 
    print('table', object.id, num)
end

local map = {}
for i = 1, 100 do 
    local str = 'string' .. i
    map[str] = math.random(1, 10000)
end

for str, num in pairs(map) do 
    print('string', str, num)
end

end)

掉线日志以及地图.zip

从前就一直怀疑你修复的有问题 今天测了一下 发现是真的有问题 被我逮到了吧

actboy168 commented 4 years ago

不要异步创建table

w4454962 commented 4 years ago

异步的原因是 你 初始化给每个object 一个gchash 然后pairs 时加入到哈希算法里 一旦gchash出现异步 接下来 再new 的对象 就会出现不一样的gchash 在pairs 时 就会乱序了 你为了保证hash函数的随机性 导致的。

w4454962 commented 4 years ago

这个不可能 那string呢。 只要异步string gchash同样会异步

actboy168 commented 4 years ago

string没有gchash

w4454962 commented 4 years ago

在魔兽里 避免异步table 比 避免pairs更难。

w4454962 commented 4 years ago

其实把 根据gchash 加入哈希算法 改成 根据gchash 遍历 就可以避免掉table 遍历异步的问题 只是损失的是那点不可靠的随机性

actboy168 commented 4 years ago

这个解决方案和不用pairs或者自己实现pairs等价

w4454962 commented 4 years ago

研读了一下源码, 发现重写pairs是简单的, 但是重写next 相对困难许多, pairs异步的地方正是在于next 只重写pairs并不彻底。

w4454962 commented 4 years ago

我想到了一个解决方案 在魔兽中 异步创建table 有2种可能
1 在异步回调的函数里 这个几乎可以无视 2 是在本地玩家的if里

主要解决的是在 本地玩家if 里的问题 那么很显然 只要gchash 关联lua栈 例如 下面伪代码 function test() local gchash = 1000 local t = {gchash = gchash} gchash = gchash + 1

if 玩家 == 本地玩家 then 
    local gchash = 2000
    local t = {gchash = gchash}
   gchash = gchash + 1

    local t2 = {gchash = gchash}
    gchash = gchash + 1

end
 local t2 = {gchash = gchash}
 gchash = gchash + 1

 local map = {}

map[t] = 1
map[t2] = 2
for tbl, num in pairs(map) do   --此时 if中异步创建的table 不会影响到其他地方。
       print(tbl, num)
end

end

那么要解决的是 在lua申请栈空间的时候 多申请一个int 记录一个 不会冲突的数字, 然后创建table时取该数字不断+1 即可。