coroutine
协程(coroutine),即协同程序,它与线程差不多,也就是一条执行序列,拥有自己独立的栈、
局部变量和指令指针,同时又与其他协程共享全局变量和其他大部分东西。从概念上讲,线程与协程
的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协程却需要彼此协作地运行。
也就是说,一个具有多个协程的程序在任意时刻只能运行一个协程,并且正在运行的协同程序只会在其
显示地要求挂起时,它的执行才会暂停。
Lua 将所有关于协程的函数放置在一个名为 “ coroutine ”的 table 中。
下面介绍该 table 中操作协程的几个函数:
1、create 函数:创建 coroutine ,它只有一个参数,即一个函数。
该函数的代码就是协程所需执行的内容。create 会返回一个 thread 类型的值,用以表示新的协程。
通常 create 的参数是一个匿名函数,如:
co = coroutine.create ( function ( ) print " hi, co " end )
print ( co ) ----> thread: 0x8071d98
2、status 函数:检查协程的状态
一个协程可以处于四种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和
正常(normal)。当创建一个新的协程时,它处于挂起状态,需要手动启动一个协程。
3、resume函数:用于启动或再次启动一个协程的执行,并将其状态由挂起改为运行:
coroutine.resume ( co ) -----> hi, co
协程执行之后便终止了,然后它就处于死亡状态,也就再也无法返回了。
print ( coroutine.status ( co ) ) ---> dead
resume 还可以传不定参数:resume ( co [ , val1, ... ] )
Starts or continues the execution of coroutine co
.
The first time you resume a coroutine, it starts running its body.
The values val1
, ··· are passed as the arguments to the body function.
第一次启动协程,参数会传给所要执行的函数体。
If the coroutine has yielded, resume
restarts it; the values val1
, ··· are passed
as the results from the yield.
如果协程已经 yield 了,再次启动该协程时,会把 yield 函数中返回的结果当作
参数传入 resume 函数。
If the coroutine runs without any errors, resume
returns true plus any values
passed to yield
(if the coroutine yields) or any values returned by the
body function (if the coroutine terminates).
当一个协程结束时,它的主函数所返回的值都将作为对应 resume 的返回值:
co = coroutine.create ( function ( ) return 6, 7 end )
print ( coroutine.resume( co ) ) ----> true 6 7
If there is any error, resume
returns false plus the error message.
4、yield 函数:让一个运行中的协程挂起,之后还可以恢复它的运行。
Suspends the execution of the calling coroutine.
The coroutine cannot be running a C function, a metamethod, or an iterator.
Any arguments to yield
are passed as extra results to resume
.
5、running 函数
Returns the running coroutine, or nil when called by the main thread.
能得到正在运行的协程,如:
co = coroutine.create(function() print(coroutine.running()) end )
coroutine.resume(co123)
thread: 003CD978
例子:
- function foo (a)
- print("foo", a) -- foo 2
- return coroutine.yield(2 * a) -- return: a , b
- end
- co = coroutine.create(function (a , b)
- print("co-body", a, b) -- co-body 1 10
- 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("main", coroutine.resume(co, 1, 10)) -- true, 4
- print("------")
- print("main", coroutine.resume(co, "r")) -- true 11 -9
- print("------")
- print("main", coroutine.resume(co, "x", "y")) -- true 10 end
- print("------")
- print("main", coroutine.resume(co, "x", "y")) -- false cannot resume dead coroutine
- print("------")
- >lua -e "io.stdout:setvbuf 'no'" "cur.lua"
- co-body 1 10
- foo 2
- main true 4
- ------
- co-body2 r
- main true 11 -9
- ------
- co-body3 x y
- main true 10 end
- ------
- main false cannot resume dead coroutine
- ------
- >Exit code: 0
Creates a new coroutine, with body f
. f
must be a Lua function.
Returns a function that resumes the coroutine each time it is called.
Any arguments passed to the function behave as the extra arguments to resume
.
Returns the same values returned by resume
, except the first boolean.
In case of error, propagates the error.
这个函数和 create 类似,都是创建一个协程,不同的是wrap 函数创建的协程会返回一个
函数,这个函数会启动一次该协程。
例如,编写一个迭代器:
function permgen ( a, n )
n = n or # a
if n <= 1 then
coroutine.yield( a )
else
for i = 1,n do
a[n], a[i] = a[i] , a[n]
permgen( a, n - 1 )
a[n], a[i] = a[i] , a[n]
end
end
end
function permutations ( a )
local co = coroutine.create( function ( ) permagen ( a ) end )
return function ( )
local code, res = coroutine.resume( co )
return res
end
end
permutations 函数可以用 wrap 函数来写:
function permutations ( a )
return coroutine.wrap( function ( ) permgen ( a ) end )
end