(7)LUA程序设计-协同程序(coroutine)

来源:互联网 发布:记忆卡数据恢复 编辑:程序博客网 时间:2024/04/27 23:44

本节大概地讲一下关于协同程序的知识点。

在前面我们讲了lua的数据类型种类的时候,我们讲过thread这种类型,本节就讲这种类型是如何创建的,以及如何使用它。

协同程序(coroutine)跟多线程有相似之处,拥有自己的局部变量,栈空间,变量指针等,也拥有共享的全局变量。

但二者还是有一定的区别:多线程可以同时运行多个线程,而协同程序一个时候只能运行一个,并且只有在显式调用挂起之后,才会使协同程序暂停下来。

LUA将有关协同程序的函数都封装于coroutine这个table里边,同时,一个协同程序拥用“运行”“挂起”“正常”,以及“死亡”这四种状态

举例:

创建一个协同程序,此时

c = coroutine.create(function() print 'create the coroutine programming!!' end);

打印协同程序的返回类型

print(c) ---thread:0x12382364

打印协同程序的状态(一个刚创建的协同程序,状态都是挂起,必须通过显示调用resume,才能让挂起的协同变成运行状态)

print(coroutine.status(c)) ---suspended

通过显示调用resume,才能让挂起的协同变成运行状态,但由于程序只是打印了一个create the coroutine programming!!字符串,所以最后直接由运行状态变成死亡状态了。

coroutine.resume(c)

print(coroutine.status(c)) ---dead

协同程序的正常状态,是指当协同A程序调用了协同B程序时,A程序便处于正常状态。

LUA通过coroutine.yeild()这个强大的函数,让协同程序从运行状态变成挂起状态

---------------------------------------------------------------

下面我们重新编写协同程序的主函数,如下:

c = coroutine.create(function() for i=1,10 do print("coroutine",i)  coroutine.yield() end end);

让协同程序c跑起来(suspended->running)

coroutine.resume(c)-- coroutine 1

print(coroutine.status(c))--suspended  执行完第一条打印之后,运到coroutine.yeld(),协同程序被挂起了

coroutine.resume(c)-- coroutine 2 重启协同程序,继续之前的打印,必须每打印完一条信息,手动恢复协同程序,直到打印完10条信息为止

-------------------------------------------------------------------------------

LUA协同程序当中,resume-yield可以用来传递交换信息

情况一:

1.1当协同程序主函数没有参数时,如:

c = coroutine.create(function() print 'ONE' end)

用resume时,传入除c协同对象外,还有其他参数,其他参数将被忽略。

coroutine.resume(c,xx)

1.2当协同程序主函数有参数a,b时,如:

c = coroutine.create(function(a,b) print a..'ONE' .. b end)

调用resume时传入参数a,b时,a,b被传入主函数内

coroutine.resume(c,a,b) -- 打印a ONE b

情况二:

在讲之前,我们讲一下resume的返回值,resume函数采用了前面讲过的保护模式,即实现包含在pcall函数之内,所以其返回失败格式:false  error info 返回成功 true + 协同主函数内return返回值,或者是yeild函数的返回值

如果协同程序主函数中调用了yield函数

2.1当yield函数有参数时,如时resume传入了多余参数,yeild的参数将被作为resume的返回值,举例如下

c = coroutine.create(function(a,b) coroutine.yeild(a+b,a*b) end)

print(coroutine.resume(c,1,2)) -- true  3,2   (说明1+2=3,1*2 =2)

2.2当yield函数没有参数时,如时resume传入了多余参数,所有多余参数将被作为resume的返回值,举例如下

c = coroutine.create(function(a,b) coroutine.yeild() end)

print(coroutine.resume(c,1,2)) -- true  1,2 

情况三:

协同主函数内并没有调用yeild函数,只包含return 语句时,举例如下:

c = coroutine.create(function() return "hellor" end)

print(coroutine.resume(c)) --true hellor 返回值被resume当作返回值

-------------------------------------------------------------------------------------------------------

LUA协同程序的resume-yeild机制

举例:生产者--消费者问题

生产者读出文件单词发送给消费者,消费者接收单词,并写回另一个文件当中

function producer()

     while true do

        local x = io.read();

        send(x)

     end

end

function comsumer()

   while true do

      local x = recevice()

      io.write(x,"\n");

  end

end

上面的代码当中,生产者,消费者都以我为中心,并不能分出谁是主导,谁是被调用者。二者都以自己为主导,认为对方是被调用者。

我们将代码修改如下:

让消费者启动整个生产,消费流程。

producer = coroutine.create(function()

     while true do

        local x = io.read();

        send(x)

     end

end)

function comsumer()

   while true do

      local x = recevice()

      io.write(x,"\n");

  end

end

fucntion recevice()

    local status,value = corotine.resume(producer)

    return value;

end

fucntion send(x)

  coroutine.yeild(x);

end

好了,本节讲到这里。LUA基础教程到此为止。

更多关于协同程序的应用,欢迎加入LUA交流群~~

------------------------------------------------------------------------------------------------

(1)LUA程序设计-开篇(beginning)(2012-07-28 00:47)
(2)LUA程序设计-类型与值(type & value)(2012-07-28 23:12)
(3)LUA程序设计-表达式与语句(expression & statement)(2012-07-29 22:51)


(4)LUA程序设计-函数及深入理解(function)(2012-08-03 23:00)


(5)LUA程序设计-迭代器(state iterator & stateless iterator)(2012-08-06 23:05)
(6)LUA程序设计-编译执行与错误(compile 、run & error)处理(2012-08-11 00:05)
(7)LUA程序设计-协同程序(coroutine)(2012-09-01 00:06)

更多内容:

1LUA高级程序设计

2LUA常用库,包括string,os,math,debug等库

3LUA与C互相调用及相关API的使用。

原创粉丝点击