zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Lua协同程序(COROUTINE)运行步骤分解

运行 步骤 lua 分解 coroutine 协同程序
2023-06-13 09:15:40 时间

这是一段分析lua协程(协同程序,coroutine)的代码,来自Luareferencemanualinterface(略有修改):

复制代码代码如下:


functionfoo(a)
   print("foo",a)
   returncoroutine.yield(2*a)
end

co=coroutine.create(function(a,b)
  print("co-body1",a,b)
  localr=foo(a+1)
  print("co-body2",r)
  localr,s=coroutine.yield(a+b,a-b)
  print("co-body3",r,s)
  returnb,"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
foo2
main   true   4
2------
co-body2   r
main   true   11 -9
3------
co-body3   x  y
main   true   10 end
4------
main   false  cannotresumedeadcoroutine

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

第三次:

复制代码代码如下:
print("main",coroutine.resume(co,"x","y"))

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

第四次:

复制代码代码如下:
print("main",coroutine.resume(co,"x","y"))

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