local mod = ...
local m = {}
_G[mod] = m
package.loaded[mod] = m
m.main = function()
while coroutine.status(m.co) ~= [[dead]] do
io.read()
coroutine.resume(m.co)
end
end
m.co = coroutine.create(
function()
for i = 1, 10 do
print("co", i)
coroutine.yield()
end
end
)
coroutine.resume(m.co2, 1, 2, 3)
coroutine.resume(m.co2, 10, 20, 30)
m.co2 = coroutine.create(
function(a, b, c)
while true do
print("co", a, b, c)
coroutine.yield()
end
end
)
co 1 2 3
co 1 2 3
从输出结果可以看出,第一次调用 resume 时,参数的值传给了 a,b,c,第二次调用时则不会
print(coroutine.resume(m.co2, 1, 2, 3))
print(coroutine.resume(m.co2, 10, 20, 30))
m.co2 = coroutine.create(
function(a, b, c)
while true do
print("co", a, b, c)
coroutine.yield(a + b, a + c, b + c)
end
end
)
co 1 2 3
true 3 4 5
co 1 2 3
true 3 4 5
print(coroutine.resume(m.co2, 1, 2, 3))
print(coroutine.resume(m.co2, 10, 20, 30))
m.co2 = coroutine.create(
function(a, b, c)
while true do
print("co", coroutine.yield())
end
end
)
true
co 10 20 30
true
第一次调用 resume 时,传入的参数 1,2,3 被参数 a,b,c 接收了,然后协程在 yield 函数中挂起,第二次调用 resume,传入的 10,20,30 作为 yield 的返回值,yield 返回到协程继续执行,输出 co 10 20 30
print(coroutine.resume(m.co2, 1, 2, 3))
print(coroutine.resume(m.co2, 10, 20, 30))
m.co2 = coroutine.create(
function(a, b, c)
coroutine.yield()
return a + b + c
end
)
true
true 6
生产者-消费者是一个经典的协同程序,生产者不停地生产值,然后发送给消费者;消费者不停地接收值,然后催促生产者生产;两者都有自己的主循环,都把自己当作调用的主动方,但实际程序只能有一方是主动方,而另一方则必须由主动方来唤醒,执行一次之后挂起,下面就是一个 消费者驱动 的例子
-- 生产者设计成协程
m.producer = coroutine.create(
function()
while true do
local value = tonumber(io.read())
if value == -1 then
break
end
-- 生产者生产值之后挂起
coroutine.yield(value)
end
end
)
-- 消费者驱动
m.customer = function()
while true do
-- 消费者唤醒生产者
local status, value = coroutine.resume(m.producer)
if status == false or coroutine.status(m.producer) == "dead" then
break
end
io.write(value, "\n")
end
end
可以在生产者和消费者之前加一个过滤器。生产者是一个协程,过滤器也是一个协程;然后消费者唤醒过滤器,过滤器再唤醒生产者,生产者产生值之后就挂起自己,过滤器接收生产的值后也挂起自己,最后消费者接收生产的值后继续唤醒过滤器
-- 生产者设计成协程
m.producer = function()
return coroutine.create(
function()
while true do
local value = io.read()
if value == "-1" then
break
end
-- 生产者生产值之后挂起
coroutine.yield(value)
end
end
)
end
-- 过滤器设计成协程
m.filter = function(producer)
return coroutine.create(
function()
for line = 1, math.huge do
-- 唤醒生产者
local status, value = coroutine.resume(producer)
-- 生产者死亡
if status == false or coroutine.status(producer) == "dead" then
break
end
x = string.format("%-5d %s", line, value)
-- 过滤器得到生产值之后挂起
coroutine.yield(x)
end
end
)
end
-- 消费者驱动
m.customer = function(filter)
while true do
-- 唤醒过滤器
local status, value = coroutine.resume(filter)
-- 过滤器死亡
if status == false or coroutine.status(filter) == "dead" then
break
end
io.write(value, "\n")
end
end