Lua的協同程序


Lua是一種簡單,可擴展,可移植及高效的腳本語言。在嵌入式系統,移動設備,web服務器,游戲等方面都能見到它的身影。lua其中最吸引人的一點事它能很方便地與C語言或者其他語言。

這里說的是lua語言中的協同程序(coroute),也有人翻譯成為協作程序

基本函數和語法

coroutine就是lua的協同程序


先講一下coroutine的語法:

coroutine.create( )

創建coroutine,返回coroutine, 參數是一個函數,當和resume配合使用的時候就喚醒函數調用

coroutine.resume( )

重啟coroutine,和create配合使用

coroutine.yield()

掛起coroutine,將coroutine設置為掛起狀態,這個和resume配合使用能有很多有用的效果

coroutine.status( )

查看coroutine的狀態

注:coroutine的狀態有三種:dead,suspend,running,具體什么時候有這樣的狀態請參考下面的程序

coroutine.wrap(

創建coroutine,返回一個函數,一旦你調用這個函數,就進入coroutine,和create功能重復

coroutine.running()

返回正在跑的coroutine,一個coroutine就是一個線程,當使用running的時候,就是返回一個corouting的線程號

使用下面的程序來了解一下這幾個函數的基本用法:

co = coroutine.create(
    function(i)
        print(i);
    end
)

coroutine.resume(co, 1)   -- 1
print(coroutine.status(co))  -- dead

print("----------")

co = coroutine.wrap(
    function(i)
        print(i);
    end
)

co(1)

print("----------")

co2 = coroutine.create(
    function()
        for i=1,10 do
            print(i)
            if i == 3 then
                print(coroutine.status(co2))  --running
                print(coroutine.running()) --thread:XXXXXX
            end
            coroutine.yield()
        end
    end
)

coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3

print(coroutine.status(co2))   -- suspended
print(coroutine.running())   --nil

print("----------")

返回數據:

image

coroutine.running就可以看出來,coroutine在底層實現就是一個線程。當create一個coroutine的時候就是在新線程中注冊了一個事件。當使用resume觸發事件的時候,create的coroutine函數就被執行了,當遇到yield的時候就代表掛起當前線程,等候再次resume觸發事件。

分析學習coroutine的時候經常遇到的一個程序

源程序可以看這里

我稍微做了點修改,增加了一下分隔符:

function foo (a)
    print("foo", a)  -- foo 2
    return coroutine.yield(2 * a) -- return: a , b 
end

co = coroutine.create(function (a , b)
    print("co-body", a, b) -- co-body 1 10
    local r = foo(a + 1)
    
    print("co-body2", r)
    local r, s = coroutine.yield(a + b, a - b)
    
    print("co-body3", r, s)
    return b, "end"
end)
       
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("------")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("------")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("------")
print("main", coroutine.resume(co, "x", "y")) -- false cannot resume dead coroutine
print("------")

這個程序返回:

image

很神奇,也很讓人看不懂


先理解下下面幾點:

  1. resume一定是在主線程的,yield是在子線程(coroutine)的
  2. resume可以帶參數
    當coroutine是suspend狀態的時候,參數是作為coroutine的參數傳入的
    當coroutine是suspend狀態的時候,參數是作為coroutine的參數傳入的
  3. resume返回值有兩種情況
    • 當coroutine是suspend狀態的時候,返回是是bool [yield params]
      bool是這個resume操作是否成功
      yield params是當前coroutine的yield的參數
    • 當coroutine是dead狀態的時候,返回值是bool [function return]
      bool是這個resume操作是否成功
      yield params是當前coroutine的yield的參數

先對照上面幾條看一個簡單的例子:

co = coroutine.create(
    function (a , b)
        print("params", a, b)
        return coroutine.yield(3, 3)
    end
)
coroutine.resume(co, 1, 2);
print(coroutine.resume(co, 4, 5))

image

理解完上面這個程序,再看看coroutine2的程序,這里把每個輸出執行了哪些步驟列出來了:

  1. print("main", coroutine.resume(co, 1, 10)) 執行了:
    print("co-body", 1, 10)
    print("foo", 2)
    coroutine.resume(co, 1, 10) 返回 true, 4 (!!這里的4是yield的參數)
    print("main", true, 4)
  2. print("main", coroutine.resume(co, "r")) 執行了:
    foo(a) 返回了 "r" (這是由yield返回的)
    print("co-body2", "r")
    coroutine.resume(co, "r") 返回 true, 11 -9 (!!這里的a和b還是用1和10計算的)
    print("main" , true, 11 -9)
  3. print("main", coroutine.resume(co, "x", "y"))執行了:
    local r, s = coroutine.yield(a + b, a - b) r和s值為x和y
    print("co-body3", "x", "y")
    return b, "end" //此時coroutine線程結束,為dead狀態
    coroutine.resume(co, "x", "y") 返回值為 true 10 end
    print("main" , true 10 end)
  4. print("main", coroutine.resume(co, "x", "y"))執行了:
    由於coroutine.resume(co, "x", "y")已經dead了,所以這里返回false

參考文章

Luai: Lua reference manual interface: about

lua_manual

《lua程序設計》

Creative Commons License

本文基於署名-非商業性使用 3.0許可協議發布,歡迎轉載,演繹,但是必須保留本文的署名葉劍峰(包含鏈接http://www.cnblogs.com/yjf512/),且不得用於商業目的。如您有任何疑問或者授權方面的協商,請與我聯系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM