Lua
将所有关于协同程序的函数放置在一个名为 “coroutine
” 的 table
中,函数 create
用于创建新的协同程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序所要执行的内容。
co = coroutine.create(function() print("Hello world!") end)
print(co) -- thread: 0x80719d8
一个协同进程可能处于四种状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。create函数仅仅是创建协同进程,此时并没有运行,协同程序处于挂起状态,可使用 status
函数查看状态。
print(coroutine.status(co)) -- suspended
resume
函数用于启动或者再次启动一个协同程序,由挂起状态变为运行
coroutine.resume(co) -- "Hello world!"
上面的协同程序只是简单的打印了一个 “Hello world!”,然后就结束了,此时协同程序处于死亡状态(dead),这种状态的协同程序是不能被再次唤醒的
print(coroutine.status(co)) -- dead
print(coroutine.resume(co)) -- false can not resume dead coroutine
coroutine.yield()
函数可以让程序挂起,resume
函数可以恢复程序的运行。
当一个协同程序A唤醒另一个协同程序B时,A就处于正常状态。
注意:resume
是在保护模式下运行的,也就是说,当一个协同程序发生错误时,Lua并不会显示错误消息,而是将执行权返回给 resume
调用。
Lua 的 resume-yield
数据交换机制。
yield
等待,所有 resume
传入的额外参数都将作为协同程序主函数的参数。
co = coroutine.create(function(a, b) print("co", a, b) end) coroutine.resume(co,1,2) -- co 1 2resume调用额外传入的参数,作为协同程序主函数的参数,上例中的参数 a 和 b 就是这种情况 - 在 resume 调用返回的内容中,第一个值为 true 表示没有错误,后面所有值都是对应的 yield 传入的参数
co = coroutine.create(function(a, b) coroutine.yield(a+b, a-b) end) print(coroutine.resume(co, 20, 10)) -- true 30 10
上例中resume 函数返回的值 30 和 20 ,都是 yield 函数传入的参数
co = coroutine.create(function() print("co", coroutine.yield()) end) coroutine.resume(co) coroutine.resume(co, 2, 4) -- co 4 5
yield函数返回的值,就是 resume 额外传入的参数,所以上例中 yield 函数汇返回 4 5, print 函数打印结果为 “co 4 5”
co = coroutine.create(function() return 3, 4 end) coroutine.resume(co) -- true 3 4
Lua提供的是一种“非对称的协同程序”,只有协同程序的主函数才能调用 yield 函数,让程序挂起
下面是使用协同程序实现一个去数组组合的例子,通过递归实现,并将程序写成迭代器的形式,访问所有可能的组合。
-- select k elements from set to subset
function comb(set, subset, n, k)
if n < k then
return
end
if k==0 then
-- printResult(subset)
coroutine.yield(subset)
return
else
for i=n,k,-1 do
subset[k] = set[i]
if k>0 then
comb(set, subset, i-1, k-1)
end
end
end
end
function printResult(set)
n = n or #set
for i=1,n do
io.write(set[i], " ")
end
io.write("\n")
end
---[[
function combination(set, subset, n, k)
local co = coroutine.create(function()
comb(set, subset, n, k)
end)
return function() -- 迭代器函数
local state,res = coroutine.resume(co)
return res
end
end
--]]
set = {"a", "b", "c", "d", "e"}
subset = {}
--[[
comb(set, subset, 5, 4)
--]]
---[[
for p in combination(set, subset, 5, 3) do -- subset必须构造成 table ,否则会出错,显示访问的p为空
printResult(p)
end
--]]