lua的coroutine 协同程序pipes和filters

pipes和filters

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