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的协程,而后返回一个调用该协程的函数。