lua coroutine

Lua中協程都放在表coroutine中。函數

Lua協程的四個狀態

  1. 掛起(suspended):一個協程被建立的時候,處於掛起狀態,不會自動運行。
  2. 運行(running):coroutine.resume()用於啓動或者再次啓動一個協程,使其變成運行狀態。
  3. 正常(normal):協程A喚醒協程B的時候,協程B處於運行狀態,協程A就處於正常狀態。
  4. 死亡(dead):協程中包含的函數執行完畢,協程就變成了死亡狀態。

Lua協程的操做函數:

建立協程:coroutine.create(func)

該函數接受一個函數做爲參數,返回一個thread類型的值。

例如:lua

local co = coroutine.create(function() print("hello") end)
print(type(co))

輸出:線程

thread

啓動協程:coroutine.resume(co, arg1, arg2, ...)

參數:能夠分爲兩種狀況。

1.協程中不包含yield():第一個參數是被啓動的協程,後面的參數傳遞給協程封裝的函數做爲參數。

例如:code

local co = coroutine.create(
    function(a, b) 
        print("a + b =", a + b) 
    end
)
coroutine.resume(co, 1, 2)

輸出:orm

a + b = 3

2.協程中包含yield():第一個參數仍是被啓動的線程,在首次調用resume時,後面的參數傳遞給協程封裝的函數做爲參數;而再次調用(非首次)resume()時,後面的參數將做爲yield()的返回值。
例如:協程

local co = coroutine.create(
    function(x) 
        print("co1", x) 
        print("co2", coroutine.yield()) 
    end
)
coroutine.resume(co, "hello")
coroutine.resume(co, "world")

輸出:it

co1 hello
co2 world

返回值:分爲三種狀況。
1.協程沒有結束,resume()第一個返回值是true,後面的返回值是yield(...)中的參數。

2.協程結束時,resume()第一個返回值是true,後面的返回值是協程中函數的返回值。

3.協程結束後,此時不該該繼續調用resume,若是調用了,resume()第一個返回值是false,表示調用失敗,第二個返回值是報錯信息。

例如:io

local co = coroutine.create(
    function()
        coroutine.yield("hello", "world")
        return "hello", "lua"
    end
)
print(coroutine.resume(co))
print(coroutine.resume(co))
print(coroutine.resume(co))

輸出:function

true    hello   world
true    hello   lua
false   cannot resume dead coroutine

值得注意的是,resume運行在保護模式中,若是協程在執行過程當中遇到了錯誤,Lua不會打印錯誤信息,而是把錯誤信息做爲resume()的返回值。class

掛起協程:coroutine.yield(arg1, arg2, ...)

參數:yield()將做爲本次喚醒協程的resume()的返回值。

返回值:下次喚醒協程的resume()的參數,將做爲yield()的返回值。
例如:

local co = coroutine.create(
    function()
        local ret = coroutine.yield("hello")
        print(ret)
    end
)
local state, ret = coroutine.resume(co)
print(state)
print(ret)
coroutine.resume(co, "world")

輸出:

true
hello
world

Lua協程的特色

Lua協程是一種非對稱協程(asymmetric coroutine),須要兩個函數來控制協程的執行,一個用於掛起協程,一個用於恢復協程。
相對於其餘語言提供的對稱協程(symmetric coroutine),只提供一個函數用於切換不一樣協程之間的控制權。

Lua協程的一些應用

1.生產者消費者問題:

1.消費者驅動型

-- 消費者驅動型 consumer-driven
producer_co = coroutine.create(
    function()
        for i = 1, 5 do
            print("produce:", i)
            coroutine.yield(i)
        end
    end
)

function consumer()
    while true do
        local status, value = coroutine.resume(producer_co)
        print("producer:", coroutine.status(producer_co))
        if not value then
            break
        end
        print("consume:", value)
    end
end

consumer()

輸出:

produce:    1
producer:   suspended
consume:    1
produce:    2
producer:   suspended
consume:    2
produce:    3
producer:   suspended
consume:    3
produce:    4
producer:   suspended
consume:    4
produce:    5
producer:   suspended
consume:    5
producer:   dead

2.生產者驅動型

-- 生產者驅動型 producer-driven
function producer()
    for i = 1, 5 do
       print("produce:", i)
       coroutine.resume(consumer_co, i)
       print("consumer:", coroutine.status(consumer_co))
    end
    coroutine.resume(consumer_co)
end

consumer_co = coroutine.create(
    function(x)
       while true do
         print("consume:", x)
         x = coroutine.yield()
         if not x then
          break
         end
       end
    end
)

producer()
print("consumer:", coroutine.status(consumer_co))

輸出:

produce:    1
consume:    1
consumer:   suspended
produce:    2
consume:    2
consumer:   suspended
produce:    3
consume:    3
consumer:   suspended
produce:    4
consume:    4
consumer:   suspended
produce:    5
consume:    5
consumer:   suspended
consumer:   dead

2.將協程用做迭代器:

-- 產生全排列的迭代器
function permutation_gen(a, n)
    n = n or #a
    if n < 1 then
        coroutine.yield(a)
    else
        for i = 1, n do
            a[n], a[i] = a[i], a[n]
            permutation_gen(a, n - 1)
            a[n], a[i] = a[i], a[n]
        end
    end
end

function permutations(a)
    local co = coroutine.create(function() permutation_gen(a) end)
    return function()
        local code, res = coroutine.resume(co)
        return res
    end
end

function permutations_wrap(a)
    return coroutine.wrap(function() permutation_gen(a) end)
end

for p in permutations({1, 2, 3}) do
    for i = 1, #p do io.write(p[i], " ") end
    io.write("\n")
end
print("----")
for p in permutations_wrap({1, 2, 3}) do
    for i = 1, #p do io.write(p[i], " ") end
    io.write("\n")
end

輸出:

2 3 1 
3 2 1 
3 1 2 
1 3 2 
2 1 3 
1 2 3 
----
2 3 1 
3 2 1 
3 1 2 
1 3 2 
2 1 3 
1 2 3

其中coroutine.warp(func)方法就是建立一個封裝func的協程,而後返回一個調用該協程的函數。

相關文章
相關標籤/搜索