Lua中協程都放在表coroutine中。函數
該函數接受一個函數做爲參數,返回一個thread類型的值。
例如:lua
local co = coroutine.create(function() print("hello") end) print(type(co))
輸出:線程
thread
參數:能夠分爲兩種狀況。
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
參數: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協程是一種非對稱協程(asymmetric coroutine),須要兩個函數來控制協程的執行,一個用於掛起協程,一個用於恢復協程。
相對於其餘語言提供的對稱協程(symmetric coroutine),只提供一個函數用於切換不一樣協程之間的控制權。
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
-- 產生全排列的迭代器 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的協程,而後返回一個調用該協程的函數。