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