Lua协程(coroutine)程序运行分析

2023-12-05 0 583

这是一段分析 lua 协程(协同程序,coroutine)的代码,来自 Lua reference manual interface (略有修改):
复制代码 代码如下:
function foo (a)
print(\”foo\”, a)
return coroutine.yield(2*a)
end

co = coroutine.create(function (a,b)
print(\”co-body1\”, a, b)
local r = foo(a+1)
print(\”co-body2\”, r)
local r, s = coroutine.yield(a+b, a-b)
print(\”co-body3\”, r, s)
return b, \”end\”
end)

print(\”1—-\”)
print(\”main\”, coroutine.resume(co, 1, 10))
print(\”2—-\”)
print(\”main\”, coroutine.resume(co, \”r\”))
print(\”3—-\”)
print(\”main\”, coroutine.resume(co, \”x\”, \”y\”))
print(\”4—-\”)
print(\”main\”, coroutine.resume(co, \”x\”, \”y\”))

运行效果如下:
复制代码 代码如下:
1——
co-body1 1 10
foo 2
main true 4
2——
co-body2 r
main true 11 -9
3——
co-body3 x y
main true 10 end
4——
main false cannot resume dead coroutine

这里一共调用了 4 次 resume ,让我们来看看它是怎么运行的。

第一次:
复制代码 代码如下:
print(\”main\”, coroutine.resume(co, 1, 10))

1.执行 print(\”co-body1\”, a, b) ,a 和 b 的值为 resume 提供,a=1, b=10 ;
2.计算 a+1=2 ,进入 foo(a) ,同时将刚才的计算结果通过 a 参数传递,执行 print(\”foo\”, a);
3.考虑 return coroutine.yield(2*a) ;
4.计算 2*a=4 ,碰到 yield,挂起 foo(a) 调用,将 4 返回给 resume 。注意,foo 的 return 还没有执行;
5.resume 执行成功,返回 true, 4 。

第二次:
复制代码 代码如下:
print(\”main\”, coroutine.resume(co, \”r\”))

1.从上一次挂起的 foo(a) 调用开始执行,接着执行没有完成的 return 调用;
2.因为 yield 返回 resume 的调用参数,此时 foo(a+1) 返回的值就是字符串 \”r\”。这里比较难理解。
因为大家可能会顺理成章地认为 local r 这个变量的值应该是 yield(2*a) 中的 2*a 的值。
需要注意的是, yield 的返回值 与 yield 参数的值 是不同的。
前者你可以将其保存在一个变量中,或者 return 它,或者不使用它(不保存 yield 的返回结果);后者则是 resume 的返回值。
3.执行 print(\”co-body2\”, r) ,r 的值为 \”r\” ;
4.考虑 local r, s = coroutine.yield(a+b, a-b) ;
5.计算 a+b=11, a-b=-9 ,碰到 yield ,挂起 co 的调用,将 11 和 9 返回给 resume 。注意,此时 local r, s 的赋值还没有开始。
这里不太好理解的是,为什么 a 的值不是 \”r\” ?因为 \”r\” 已经被上面的 yield 的返回值给消费掉了。
6.resume 执行成功,返回 true, 11, -9 。

第三次:
复制代码 代码如下:
print(\”main\”, coroutine.resume(co, \”x\”, \”y\”))

1.从上一次 yield 的地方开始执行,接着执行没有完成的 local r, s = 赋值。上面提到, yield 会返回 resume 的调用参数,因此 r 和 s 的值就是 \”x\” 和 \”y\” ;
2.执行 print(\”co-body3\”, r, s) 进行打印;
3.考虑 return b, \”end\” ;
4.b 的值一直都是 10 没有变,这里直接返回了,同时返回的还有 \”end\” 这个字符串;
5.由于协程函数返回的时候,它的所有返回值都作为 resume 的返回值返回。因此这里的 resume 执行成功,返回 10, \”end\” 。

第四次:
复制代码 代码如下:
print(\”main\”, coroutine.resume(co, \”x\”, \”y\”))

由于 co 函数已经返回,它处于 dead 状态,不能 resume ,因此第 4 次 resume 失败。

您可能感兴趣的文章:

  • Lua的协程(coroutine)简介
  • Lua之协同程序coroutine代码实例
  • Lua协同程序(COROUTINE)运行步骤分解
  • Lua协同程序函数coroutine使用实例
  • Lua编程示例(七):协同程序基础逻辑
  • 举例详解Lua中的协同程序编程
  • Lua中的协同程序详解
  • Lua中的协同程序之resume-yield间的数据返回研究
  • Lua中的协同程序探究
  • Lua协同程序coroutine的简介及优缺点

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 Lua Lua协程(coroutine)程序运行分析 https://www.u-9.cn/jiaoben/lua/101437.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务