Loading [MathJax]/extensions/TeX/AMSsymbols.js

2021年5月11日 星期二

Lua Tutorial - Coroutines

想看更多Lua教學可以看之前的文章: Learn Lua in 10 minutes 裡面有內容大綱和更多仔細地介紹

Lua的Coroutines可以說是一個能隨時停止或執行的function,官網原文是

A coroutine is a function that can suspend execution to be resumed later.

意思就是"coroutine 是個可以隨時暫停等待再次被執行的 function",我們這邊簡單舉個例子

coroutine.create

先寫個function func

function func()
{
    ....
    while()
    {
            yield()
            print("Hi")
    }
    ...
}

然後讓我們的function變成coroutine, co = coroutine.create(func)
這時候co的狀態是suspend (暫停),並不會去執行func(),並且type(co) 能得到現在的co是個thread

使用co.resume() 開始執行func,當func跑到yield()的位置時,就會離開function 

如果我們再次執行co.resume() ,就會回到剛剛func暫停的位置 ,會直接執行print("Hi")

那如果func不小心跑完的話呢? 這樣co的狀態就會變成dead(死掉),resume會失敗

coroutine 還能在resume或是yield的時候傳遞當下狀態,如底下的範例

-- 新增一個corutine
co = coroutine.create(function(n)
    print('n is ' .. n)
    for i = 1, 4 do
        print(string.format("i: %d,  %s", i, coroutine.status(co)))
        if i == 2 then
-- yield()暫停function並離開, ret能收到resume()傳進來的值
ret = coroutine.yield(i)
print('ret= ' .. ret)
        end
    end
-- function結束回傳-1
return -1
end)
-- 印出corutine的狀態和type
print(string.format("[start] %s, type %s", coroutine.status(co), type(co)))
-- 我們resume 三次 看看function 每次執行和回傳值的狀況
for times = 1, do
-- ret能知道resume有沒有成功 value是用來接收yield()裡面回傳的值
ret, value = coroutine.resume(co, times * 10)
-- 印出co的狀態 resume成功與否和回傳值
    print(string.format("[resume %d] %s, %s, %s", times, coroutine.status(co), ret, value))
end
view raw Coroutine.lua hosted with ❤ by GitHub


這邊也可以看到 只要function變成corutine,他就不會重頭執行,就算他前一次已經結束,所以我們在corutine的function中常會看到會有個while(true)的無窮迴圈

coroutine.wrap

那接下來我們來看coroutine.wrap,這個東西和coroutine.create不太一樣,wrap 回傳的type(co)是function,所以當你的function跑完的時候 ,你再去執行它,它會就死給你看,也沒有coroutine.status的功能

它的使用方法也是差不多

co = coroutine.wrap(func)

當你要使用它的時候就是co() 這樣就可以了,因為它就是個function

-- 新增corutine
co = coroutine.wrap(function(n)
    print('n is ' .. n)
    for i = 1, 4 do
        print(string.format("i: %d", i))
        if i == 2 then
-- 中途離開function使用yield(),ret 可以接收下次呼叫所帶的參數
ret = coroutine.yield(i)
            print('ret= ' .. ret)
        end
    end
-- function結束回傳-1
return -1
end)
-- 印出type(co)
print(string.format("[start] type %s", type(co)))
for times = 1, 3 do
-- 呼叫方式就是co(),但是這邊如果呼叫失敗 lua會直接報錯
value = co(times * 10)
    print(string.format("[resume %d] %s", times, value))
end
view raw Coroutine2.lua hosted with ❤ by GitHub

corutine介紹到這邊就差不多了 :)


沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。