duno
发表于 2009-5-31 18:56:30
yield挂起当前所在代码段的 thread
设计思路是先起 递归 thread (2),然后yield当前 thread (1),等递归(2)结束,再resume(1)
问题出现在yield的执行时间点是不可控的,所以可能出现如下状态:
先进入递归,调用 resume (2),但是没有继续执行(1),即没有 yield(1)而是沿着(2)继续运行,直到(2)结束。
此时认为递归(2)结束,应返回(1),于是resume(1),但(1)的 yield 语句尚未执行,当继续执行 yield(1)时,从(2)返回的resume(1)已经执行过,没有其他部分可以激活 (1)
所以,死在(1)的 yield 语句
duno
发表于 2009-5-31 18:59:31
俺头一回见识coroutine,不知道有没有同步机制,类似synchronize的
用最笨的,外层递归轮循监视内层递归是否完成,若完成则继续,否则等待
这已经离所谓的并发越来越远了。。。囧
taoyuan,beijing,huyidao,wudang测试通过
temp_thread_path = {}
function exec_alias(s)
temp_thread_path=coroutine.create(function (s)
Note ("create coroutine : ", s)
local p_temp = Split(s,";");
for i,v in ipairs(p_temp) do
if alias_table then
exec_alias (alias_table, s)
Note ("before yield")
while temp_thread_path] do
Note ("before yield ", temp_thread_path])
DoAfterSpecial (1, "resume_coroutine(\""..s.."\")", 12)
coroutine.yield ()
end
elseif nil~=string.find(v,"#%d+ ") then
world.Send(do_table..string.sub(v,string.find(v," .+")));
elseif nil~=string.find(v,"#wa") then
world.DoAfterSpecial(string.sub(v,string.find(v,"%d+")) / 2000,"resume_coroutine(\""..s.."\")",12);
coroutine.yield();
else
world.Send(v);
end
end
Note ("coroutine end : ", s)
temp_thread_path = nil
end)
coroutine.resume(temp_thread_path,s);
end
function resume_coroutine (thread_name)
Note ("resume_coroutine : ", thread_name)
coroutine.resume(temp_thread_path);
end
[ 本帖最后由 duno 于 2009-5-31 07:01 PM 编辑 ]
ddid
发表于 2009-5-31 19:30:25
yield出没,请注意!
ddid
发表于 2009-5-31 19:32:30
coroutine里可以加入wait.time(),以控制时间。
ddid
发表于 2009-5-31 20:53:34
实际核对了一遍table的数据,只有以下5个是既有路径alias又有#wa的:
gumu
taoyuan
tiandihui
guiquan
xiangyang
针对这个问题,最简单的办法还是回到table里,用真实路径字符串替代那5个alias……
不过,另一面,很难的看到LUA的coroutine的实际应用,研究一下,也涨不少知识呢……
muxiao
发表于 2009-5-31 20:59:22
确实偏离了,还没测试这段代码.呵呵.
等吃过饭分析一下,并不一定死在挂起操作上,简单问题复杂化.
ddid
发表于 2009-5-31 21:42:34
找到一个gammon关于coroutine的例子,估计是这个plugin的原型
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4956
ddid
发表于 2009-5-31 21:48:02
wait.lua的功能很强大啊,貌似不用coroutine了……
maper
发表于 2009-5-31 22:17:49
好复杂啊,要慢慢看!
duno
发表于 2009-5-31 22:18:15
俺认为这里yield的问题是并发控制和原子性操作的问题,靠指定挂起等待时间不能完全解决
resume(2)和yield(1)两步在thread(1)中应该是不可分的
wait.lua是在模拟#wa的功能
在防止指令太快服务器不响应方面,#wa功能可以通过Execute的Delay代替,delay比#wa更简洁
wait.lua的应用举例也说得是各种有busy操作之间连贯和衔接,“all that achieves is to "hang" the entire PC for a while”