天天看點

Lua:協程,coroutine.create,coroutine.resume, coroutine.yield

​​http://cloudwu.github.io/lua53doc/manual.html#2.6​​​ Lua 支援協程,也叫 協同式多線程。 一個協程在 Lua 中代表了一段獨立的執行線程。 然而,與多線程系統中的線程的差別在于, 協程僅在顯式調用一個讓出(yield)函數時才挂起目前的執行。

調用函數 coroutine.create 可建立一個協程。 其唯一的參數是該協程的主函數。

create

函數隻負責建立一個協程并傳回其句柄 (一個 thread 類型的對象); 而不會啟動該協程。

調用 coroutine.resume 函數執行一個協程。 第一次調用 coroutine.resume 時,第一個參數應傳入 coroutine.create 傳回的線程對象,然後協程從其主函數的第一行開始執行。 傳遞給 coroutine.resume 的其他參數将作為協程主函數的參數傳入。 協程啟動之後,将一直運作到它終止或 讓出。

協程的運作可能被兩種方式終止: 正常途徑是主函數傳回 (顯式傳回或運作完最後一條指令); 非正常途徑是發生了一個未被捕獲的錯誤。 對于正常結束, coroutine.resume 将傳回 true, 并接上協程主函數的傳回值。 當錯誤發生時, coroutine.resume 将傳回 false 與錯誤消息。

通過調用 coroutine.yield 使協程暫停執行,讓出執行權。 協程讓出時,對應的最近 coroutine.resume 函數會立刻傳回,即使該讓出操作發生在内嵌函數調用中 (即不在主函數,但在主函數直接或間接調用的函數内部)。 在協程讓出的情況下, coroutine.resume 也會傳回 true, 并加上傳給 coroutine.yield 的參數。 當下次重新開機同一個協程時, 協程會接着從讓出點繼續執行。 此時,此前讓出點處對 coroutine.yield 的調用 會傳回,傳回值為傳給 coroutine.resume 的第一個參數之外的其他參數。

與 coroutine.create 類似, coroutine.wrap 函數也會建立一個協程。 不同之處在于,它不傳回協程本身,而是傳回一個函數。 調用這個函數将啟動該協程。 傳遞給該函數的任何參數均當作 coroutine.resume 的額外參數。 coroutine.wrap 傳回 coroutine.resume 的所有傳回值,除了第一個傳回值(布爾型的錯誤碼)。 和 coroutine.resume 不同, coroutine.wrap 不會捕獲錯誤; 而是将任何錯誤都傳播給調用者。

下面的代碼展示了一個協程工作的範例:

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

     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)

     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))      

當你運作它,将産生下列輸出:

co-body 1 10
foo 2
main  true  4
co-body r
main    true  11  -9
co-body x y
main  true  10  end
main   false  cannot resume dead coroutine      

你也可以通過 C API 來建立及操作協程: 參見函數 lua_newthread, lua_resume, 以及 lua_yield。

解析:print(“main”, coroutine.resume(co, 1, 10))

1.print(“co-body”, a, b)

2.print(“foo”, a)

3.return coroutine.yield(2*a) 傳回了true,和傳入coroutine.yield裡面的值且執行到yield挂起

在協程讓出的情況下, coroutine.resume 也會傳回 true, 并加上傳給 coroutine.yield 的參數

解析:print(“main”, coroutine.resume(co, “r”))

  1. 當下次重新開機同一個協程時, 協程會接着從讓出點繼續執行。 此時,此前讓出點處對 coroutine.yield 的調用 會傳回,傳回值為傳給 coroutine.resume 的第一個參數之外的其他參數,第一個參數是co,相當于把 r 是 coroutine.yield的傳回值了。。。是以print(“co-body”, r)列印的是r
  2. coroutine.yield(a+b, a-b) 運作到這,傳回 true ,11 -9