Lua五:协程解决相互调用“谁拥有主循环”问题

       下面用生产者和消费者问题来展示协程如何解决软件架构中“谁拥有主循环”的问题。在一种设计中,程序通过调用消费者启动。当消费者需要新值时就唤醒生产者,生产者向消费者返回新值后挂起,直到消费者再次将其唤醒。因此,我们将这种设计称为消费者驱动( consumer-driven)式的设计。

       同时,我们可以使用过滤器来扩展上述设计。过滤器位于生产者和消费者之间,用于完成一些对数据进行某种变换的任务。过滤器(filter) 既是一个消费者又是一一个生产者,它通过唤醒一个生产者来获得新值,然后又将变换后的值传递给消费者。

       代码的逻辑可以参照下文来理解:根据“consumer(filter(producer())”,先调用producer()函数,生成一个待启动的协程,这个协程包含的代码段功能是从io流中读取一个值(local x = io.read()),然后调用send ()函数,其功能是挂起正在进行的这个协程。然后从filter(producer())这个命令,函数filter()接收到调用producer()返回的协程,然后函数filter()调用receive ()函数得到producer()函数生成的新数,并和行数一块打印出来(x = string.format("%5d %s", line, x))。最后调用consumer()函数,将函数filter()挂起的协程作为参数,然后重启这个协程,得到producer()函数生成的数,写入io流中。

代码如下:

function receive (prod)
  local status, value = coroutine .resume (prod)
  return value
end

function send (x)
  coroutine . yield(x)

function producer ()
  return coroutine.create(function ()
    while true do
     local x = io.read()     --产生新值
    send(x)
   end
 end)
end

function filter (prod)
  return coroutine . create(function ()
    for line = 1, math.huge do
     local x = receive(prod) -- 接收新值
     x = string.format("%5d %s", line, x)
     send(x)  --发送给消费者
    end
   end)
end

function consumer (prod)
  while true do
    local x = receive(prod)   --获取新值
      io.write(x,"\n")     --消费新值
    end
end
consumer(filter(producer())

 

上一篇:Lua元表(Metatable)


下一篇:AIR101-打印内存占用