1. 程式人生 > 其它 >Lua五:協程解決相互呼叫“誰擁有主迴圈”問題

Lua五:協程解決相互呼叫“誰擁有主迴圈”問題

下面用生產者和消費者問題來展示協程如何解決軟體架構中“誰擁有主迴圈”的問題。在一種設計中,程式通過呼叫消費者啟動。當消費者需要新值時就喚醒生產者,生產者向消費者返回新值後掛起,直到消費者再次將其喚醒。因此,我們將這種設計稱為消費者驅動( consumer-driven)式的設計。

同時,我們可以使用過濾器來擴充套件上述設計。過濾器位於生產者和消費者之間,用於完成一些對資料進行某種變換的任務。過濾器(filter) 既是一個消費者又是一一個生產者,它通過喚醒一個生產者來獲得新值,然後又將變換後的值傳遞給消費者。

程式碼的邏輯可以參照下文來理解:根據“consumer(filter(producer())”,先呼叫producer()函式,生成一個待啟動的協程,這個協程包含的程式碼段功能是從io流中讀取一個值(local x = io.read()),然後呼叫send ()函式,其功能是掛起正在進行的這個協程。然後從filter(producer())這個命令,函式filter()接收到呼叫producer()返回的協程,然後函式filter()呼叫receive ()函式得到producer()函式生成的新數,並和行數一塊打印出來(x = string.format("%5d %s", line, x))。最後呼叫consumer()函式,將函式filter()掛起的協程作為引數,然後重啟這個協程,得到producer()函式生成的數,寫入io流中。

程式碼如下:

function receive (prod)
  local status, value = coroutine .resume (prod)
  return value
end

function send (x)
  coroutine . yield(x)

function producer ()
  return coroutine.create(function ()
    while true do
     local x = io.read()     --產生新值
    send(x)
   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 function consumer (prod) while true do local x = receive(prod) --獲取新值 io.write(x,"\n") --消費新值
end end consumer(filter(producer())