zoukankan      html  css  js  c++  java
  • Lua的协同程序

    Lua是一种简单,可扩展,可移植及高效的脚本语言。在嵌入式系统,移动设备,web服务器,游戏等方面都能见到它的身影。lua其中最吸引人的一点事它能很方便地与C语言或者其他语言。

    这里说的是lua语言中的协同程序(coroute),也有人翻译成为协作程序

    基本函数和语法

    coroutine就是lua的协同程序


    先讲一下coroutine的语法:

    coroutine.create()

    创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用

    coroutine.resume()

    重启coroutine,和create配合使用

    coroutine.yield()

    挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果

    coroutine.status()

    查看coroutine的状态

    注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序

    coroutine.wrap(

    创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复

    coroutine.running()

    返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

    使用下面的程序来了解一下这几个函数的基本用法:

    co = coroutine.create(
        function(i)
            print(i);
        end
    )
    
    coroutine.resume(co, 1)   -- 1
    print(coroutine.status(co))  -- dead
    
    print("----------")
    
    co = coroutine.wrap(
        function(i)
            print(i);
        end
    )
    
    co(1)
    
    print("----------")
    
    co2 = coroutine.create(
        function()
            for i=1,10 do
                print(i)
                if i == 3 then
                    print(coroutine.status(co2))  --running
                    print(coroutine.running()) --thread:XXXXXX
                end
                coroutine.yield()
            end
        end
    )
    
    coroutine.resume(co2) --1
    coroutine.resume(co2) --2
    coroutine.resume(co2) --3
    
    print(coroutine.status(co2))   -- suspended
    print(coroutine.running())   --nil
    
    print("----------")

    返回数据:

    image

    coroutine.running就可以看出来,coroutine在底层实现就是一个线程。当create一个coroutine的时候就是在新线程中注册了一个事件。当使用resume触发事件的时候,create的coroutine函数就被执行了,当遇到yield的时候就代表挂起当前线程,等候再次resume触发事件。

    分析学习coroutine的时候经常遇到的一个程序

    源程序可以看这里

    我稍微做了点修改,增加了一下分隔符:

    function foo (a)
        print("foo", a)  -- foo 2
        return coroutine.yield(2 * a) -- return: a , b 
    end
    
    co = coroutine.create(function (a , b)
        print("co-body", a, b) -- co-body 1 10
        local r = foo(a + 1)
        
        print("co-body2", r)
        local r, s = coroutine.yield(a + b, a - b)
        
        print("co-body3", r, s)
        return b, "end"
    end)
           
    print("main", coroutine.resume(co, 1, 10)) -- true, 4
    print("------")
    print("main", coroutine.resume(co, "r")) -- true 11 -9
    print("------")
    print("main", coroutine.resume(co, "x", "y")) -- true 10 end
    print("------")
    print("main", coroutine.resume(co, "x", "y")) -- false cannot resume dead coroutine
    print("------")

    这个程序返回:

    image

    很神奇,也很让人看不懂


    先理解下下面几点:

    1. resume一定是在主线程的,yield是在子线程(coroutine)的
    2. resume可以带参数
      当coroutine是suspend状态的时候,参数是作为coroutine的参数传入的
      当coroutine是suspend状态的时候,参数是作为coroutine的参数传入的
    3. resume返回值有两种情况
      • 当coroutine是suspend状态的时候,返回是是bool [yield params]
        bool是这个resume操作是否成功
        yield params是当前coroutine的yield的参数
      • 当coroutine是dead状态的时候,返回值是bool [function return]
        bool是这个resume操作是否成功
        yield params是当前coroutine的yield的参数

    先对照上面几条看一个简单的例子:

    co = coroutine.create(
        function (a , b)
            print("params", a, b)
            return coroutine.yield(3, 3)
        end
    )
    coroutine.resume(co, 1, 2);
    print(coroutine.resume(co, 4, 5))

    image

    理解完上面这个程序,再看看coroutine2的程序,这里把每个输出执行了哪些步骤列出来了:

    1. print("main", coroutine.resume(co, 1, 10)) 执行了:
      print("co-body", 1, 10)
      print("foo", 2)
      coroutine.resume(co, 1, 10) 返回 true, 4 (!!这里的4是yield的参数)
      print("main", true, 4)
    2. print("main", coroutine.resume(co, "r")) 执行了:
      foo(a) 返回了 "r" (这是由yield返回的)
      print("co-body2", "r")
      coroutine.resume(co, "r") 返回 true, 11 -9 (!!这里的a和b还是用1和10计算的)
      print("main" , true, 11 -9)
    3. print("main", coroutine.resume(co, "x", "y"))执行了:
      local r, s = coroutine.yield(a + b, a - b) r和s值为x和y
      print("co-body3", "x", "y")
      return b, "end" //此时coroutine线程结束,为dead状态
      coroutine.resume(co, "x", "y") 返回值为 true 10 end
      print("main" , true 10 end)
    4. print("main", coroutine.resume(co, "x", "y"))执行了:
      由于coroutine.resume(co, "x", "y")已经dead了,所以这里返回false

    参考文章

    Luai: Lua reference manual interface: about

    lua_manual

    《lua程序设计》

    Creative Commons License

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

    实时了解作者更多技术文章,技术心得,请关注微信公众号“轩脉刃的刀光剑影”

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

  • 相关阅读:
    【CentOS 7】关于php留言本网站的搭建
    linux系统的初化始配置(临时生效和永久生效)
    时间同步ntp服务的安装与配置(作为客户端的配置)
    CentOS 7设置服务的开机启动
    辅助模型——通信图
    一.面向对象概论
    辅助模型——包图
    构建图
    部署图
    辅助模型——状态机图
  • 原文地址:https://www.cnblogs.com/yjf512/p/2521412.html
Copyright © 2011-2022 走看看