协同程序和线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指针, 同时又与其他协同程序共享全局变量和其他大部分东西。


 


与线程区别:一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。


就是说一个具有多个协同程序的程序在任意时刻只能和运行一个协同程序,并且正在运行的协同程序只会在显示地要求挂起(suspend)时,它的执行才会暂停。


 


  1. 协同程序基础

Lua将所有关于协同程序的函数放置在一个名为"coroutine"的table中。 函数create用于创建新的协同程序, 它只有一个参数,就是一个函数。该函数代码就是协同程序所需执行的内容。 create会返回一个thread类型的值, 用以表示新的协同程序。 通常create的参数是一个匿名函数。


例如:


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


print( co ) --> thread: 0x8071d98


 


一个协同程序可以处于四种不同的状态:


  • 挂起(suspended)
  • 运行(running)
  • 死亡(dead)
  • 正常(normal)

 


当创建一个协同程序的时,它处于挂起状态。 也就是说协同程序不会在创建它时,自动执行其内容。


可以通过status来检查协同程序的状态


print("coroutine.status(co)) --> suspended


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


coroutine.resume(co) --> hi


在本例中,协同程序内容只是简单地打印了"hi"后便终止了, 然后它就处于死亡状态。也就再也无法返回。


print("coroutine.status(co)) -->dead


 


Lua协同程序还具有意向有用的机制,就是可以通过一对resume-yield来交换数据。


在第一次调用resume时, 并没有对应的yield来等待它, 因此所有传递给resume的额外参数都将视为协同程序主函数的参数。

co = coroutine.create(function(a, b, c) 

 

  print("co", a, b, c) 

 

  end) 

 

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


 


Lua提供的是一种“非对称的协同程序(symmetric coroutine)"。也就是说Lua提供了两个函数来控制协同程序的执行, 一个用于挂起执行,一个用于恢复执行。


而其他语言则提供了“对称的协同程序(symmetric coroutine)", 其中只有一个函数用于转让协同程序之间的执行权。


  1. 管道(pipe)
  2. 过滤器(filter)
  3. 非抢占式的多线程

require "socket"


host = "www.w3.org"


file = "/TR/REC-html32.html"


打开一个TCP连接,连接到该站点的80端口


c = assert (socket.connect(host, 80)


这步操作将返回一个连接对象,可以用它来发送文件请求。


c: = send("GET" .. file .. " HTTP/1.0\r\n\r\n") 

 

  while true do 

 

  local s, status, partial = c:receive(2^10) 

 

  io.write(s or partial) 

 

  if status== “closed" then break end 

 

  end 

 

  c:close()