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

相關文章
相關標籤/搜索