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唤醒。

运行结果:

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。此时的代码如下:

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)

运行结果:

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几乎可以说是齐头并进了啊。

转载于:https://my.oschina.net/u/2326611/blog/842918

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值