码迷,mamicode.com
首页 > 其他好文 > 详细

lua协程

时间:2015-07-29 14:14:34      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

    协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又跟其他协同程序共享全局变量和其他大部分东西。从概念上来讲,线程与协同程序的主要区别在于:一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示的要求挂起时,它的执行才会暂停。

    lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中,函数create用于创建新的血统程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序需要执行的内容。create会返回一个thread类型的值,用于表示新的协同程序,一般create的参数是一个匿名函数,如:

local co = coroutine.create(function()
    print("hi)
end)

    一个协同程序有四种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当新创建一个协同程序时,它处于挂起状态,也就是说,协同程序不会在创建它的时候自动运行。我们可以通过函数status来检查协同程序的状态。

local co = coroutine.create(function()
    print("hi")
end)
print(coroutine.status(co))    --suspended

    函数coroutine.resume用于启动或再次启动一个协同程序的执行,并将其状态由挂起改为运行。

local co = coroutine.create(function()
    print("hi")
end)
print(coroutine.status(co))    --suspended
coroutine.resume(co)    --hi

    上面的代码中调用来resume函数,将协同程序co由suspended改为running状态,当打印了hi之后,co就处于死亡状态了。

    我们现在来看一下协程函数的yield,该函数可以让一个运行中的协同程序挂起,而之后可以再恢复它的运行。看下面的例子:

local co = coroutine.create(function()
	for i=1,5 do 
		print(i)
		coroutine.yield()
	end
end)

print(coroutine.status(co))
coroutine.resume(co)

print(coroutine.status(co))
coroutine.resume(co)

print(coroutine.status(co))
coroutine.resume(co)
coroutine.resume(co)
coroutine.resume(co)
--coroutine.resume(co)注意这句话
print(coroutine.status(co))
coroutine.resume(co)

   输出:

suspended
1
suspended
2
suspended
3
4
5
suspended    --当把上面的注释打开,这是输出为:dead

    在最后一次调用resume时,协同程序的内容已经执行完毕,并已经返回。因此,这时协同程序处于死亡状态。当在协同程序的执行中发生任何错误,Lua是不会显示错误消息的,而是将执行权返回给resume调用。当coroutine.resume的第一个返回值为false时,就表明协同程序在运行过程中发生了错误;当值为true时,则表明协同程序运行正常。

    当一个协同程序A唤醒另一个协同程序B时,协同程序A就处于一个特殊状态,既不是挂起状态(无法继续A的执行),也不是运行状态(是B在运行)。所以将这时的状态称为“正常”状态。

    Lua的协同程序还具有一项有用的机制,就是可以通过一对resume-yield来交换数据。在第一次调用resume时,并没有对应的yield在等待它,因此所有传递给resume的额外参数都视为协同程序主函数的参数。

    当协同程序中没有yield时,第一次调用resume,所有传递给resume的额外参数都将视为协同程序主函数的参数,如以下代码:

local co = coroutine.create(function (a, b, c)
     print("co", a, b, c)
end)

coroutine.resume(co, 1, 2, 3)     -- co 1 2 3

    在resume调用返回的内容中,第一个值为 true则表示没有错误,而后面所有的值都是对影yield传入的参数:

local co = coroutine.create(function(a,b)
	coroutine.yield(a+b,a-b)
end)
print(coroutine.resume(co,20,10))

    输出:

true	30	10

    于此对应的时,yield返回的额外值就是对应resume传入的参数:

local co = coroutine.create(function()
	print(coroutine.yield())
end)
coroutine.resume(co)
coroutine.resume(co,4,5)

    输出:

4

    最后,当一个协同程序结束时,它的主函数所返回的值都将作为对应resume的返回值:

local co = coroutine.create(function()
	return 6,7
end)
print(coroutine.resume(co))

    输出:

true	6

lua协程

标签:

原文地址:http://my.oschina.net/u/815187/blog/485109

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!