couroutine的一个典型的例子就是producer-consumer问题。咱们来假设有这样两个函数,一个不停的produce一些值出来(例如从一个file中不停地读),另外一个不断地consume这些值(例如,写入到另外一个file中)。这两个函数的样子应该以下:函数
function producer () while true do local x = io.read() -- produce new value send(x) -- send to consumer end end function consumer () while true do local x = receive() -- receive from producer io.write(x, "\n") -- consume new value end end
coroutine提供了解决上面问题的一个比较理想的工具resume-yield工具
function receive (prod) local status, value = coroutine.resume(prod) return value end function send (x) coroutine.yield(x) end function producer() return coroutine.create(function () while true do local x = io.read() -- produce new value send(x) end end) end function consumer (prod) while true do local x = receive(prod) -- receive from producer io.write(x, "\n") -- consume new value end end p = producer() print("after producer") consumer(p)
程序先调用consumer, 而后recv函数去resume唤醒producer,produce一个值,send给consumer,而后继续等待下一次resume唤醒。lua
运行结果:spa
after producer 1 1 2 2 3 3 4 4
增长一个filter,在producer和consumer之间作一些数据转换啥的。那么filter里都作些什么呢?咱们先看一下没加filter以前的逻辑,基本就是producer去send,send to consumer,consumer去recv,recv from producer,能够这么理解吧。加了filter以后呢,由于filter须要对data作一些转换操做,所以这时的逻辑为,producer去send,send tofilter,filter去recv,recv from producer,filter去send,send to consumer,consumer去recv,recv fromfilter。此时的代码以下:code
function receive (prod) local status, value = coroutine.resume(prod) return value end function send(x) coroutine.yield(x) end function producer() return coroutine.create(function () while true do local x = io.read() send(x) end end) end function consumer(prod) while true do local x = receive(prod) if x then io.write(x, '\n') else break end end end function filter(prod) return coroutine.create(function () for line = 1, math.huge do local x = receive(prod) x = string.format('%5d %s', line, x) send(x) end end) end p = producer() f = filter(p) consumer(f)
运行结果:orm
1 1 1 2 2 2 3 3 3 a 4 a cc 5 cc
使用pipe,每一个task得以在各自的process里执行,而是用coroutine,每一个task在各自的coroutine中执行。pipe在writer(producer)和reader(consumer)之间提供了一个buffer,所以相对的运行速度仍是至关能够的。这个是pipe很重要的一个特性,由于process间通讯,代价仍是有点大的。使用coroutine,不一样task之间的切换成本更小,基本上也就是一个函数调用,所以,writer和reader几乎能够说是齐头并进了啊。ip