2.6 -- 协程
Lua 支持协程,也叫 协同式多线程。 一个协程在 Lua 中代表了一段独立的执行线程。 然而,与多线程系统中的线程的区别在于, 协程仅在显式调用一个让出(yield)函数时才挂起当前的执行。
调用函数
coroutine.create
可创建一个协程。
其唯一的参数是该协程的主函数。
create
函数只负责新建一个协程并返回其句柄
(一个 thread 类型的对象);
而不会启动该协程。
调用
coroutine.resume
函数执行一个协程。
第一次调用
coroutine.resume
时,第一个参数应传入
coroutine.create
返回的线程对象,然后协程从其主函数的第一行开始执行。
传递给
coroutine.resume
的其他参数将作为协程主函数的参数传入。
协程启动之后,将一直运行到它终止或 让出。
协程的运行可能被两种方式终止:
正常途径是主函数返回
(显式返回或运行完最后一条指令);
非正常途径是发生了一个未被捕获的错误。
对于正常结束,
coroutine.resume
将返回 true ,
并接上协程主函数的返回值。
当错误发生时,
coroutine.resume
将返回 false
与错误消息。
通过调用
coroutine.yield
使协程暂停执行,让出执行权。
协程让出时,对应的最近 coroutine.resume
函数会立刻返回,即使该让出操作发生在内嵌函数调用中
(即不在主函数,但在主函数直接或间接调用的函数内部)。
在协程让出的情况下,
coroutine.resume
也会返回 true ,
并加上传给
coroutine.yield
的参数。
当下次重启同一个协程时,
协程会接着从让出点继续执行。
此时,此前让出点处对 coroutine.yield
的调用
会返回,返回值为传给
coroutine.resume
的第一个参数之外的其他参数。
与
coroutine.create
类似,
coroutine.wrap
函数也会创建一个协程。
不同之处在于,它不返回协程本身,而是返回一个函数。
调用这个函数将启动该协程。
传递给该函数的任何参数均当作 coroutine.resume
的额外参数。
coroutine.wrap
返回
coroutine.resume
的所有返回值,除了第一个返回值(布尔型的错误码)。
和 coroutine.resume
不同,
coroutine.wrap
不会捕获错误;
而是将任何错误都传播给调用者。
下面的代码展示了一个协程工作的范例:
function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))
当你运行它,将产生下列输出:
co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine
你也可以通过 C API 来创建及操作协程:
参见函数
lua_newthread
,
lua_resume
,
以及 lua_yield
。