Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

举报 1.32 pairs掉线 #194

Open
w4454962 opened this issue Mar 9, 2020 · 9 comments
Open

举报 1.32 pairs掉线 #194

w4454962 opened this issue Mar 9, 2020 · 9 comments

Comments

@w4454962
Copy link

w4454962 commented Mar 9, 2020

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

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
Copy link
Owner

不要异步创建table

@w4454962
Copy link
Author

w4454962 commented Mar 9, 2020

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

@w4454962
Copy link
Author

w4454962 commented Mar 9, 2020

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

@actboy168
Copy link
Owner

string没有gchash

@w4454962
Copy link
Author

w4454962 commented Mar 9, 2020

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

@w4454962
Copy link
Author

w4454962 commented Mar 9, 2020

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

@actboy168
Copy link
Owner

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

@w4454962
Copy link
Author

w4454962 commented Mar 9, 2020

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

@w4454962
Copy link
Author

我想到了一个解决方案 在魔兽中 异步创建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 即可。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants