Lua 協程

lua 協程

簡介

從本菜的認知角度看,協程就是一個函數能夠一段一段分開來執行,功能和時間序列聚合,執行分離。html

相關的三個函數

1. coroutine.create(cofun)

參數
-cofun 等待執行的協同函數linux

返回值
該協同程序的實例對象,該對象是一個 thread 類型的值dom

2. ret,... = coroutine.resume(co[,...])

參數
-co 須要恢復的協同程序實例對象
-... 須要傳遞給協同程序的參數,也就是協同函數的實參函數

返回值
-ret 函數執行成功返回 true,執行失敗返回 false
-... 接收傳入 yield 的實參lua

說明
resume 函數在保護模式下運行,若是協同程序運行過程當中發生了錯誤,lua並不會顯示錯誤消息,而是直接從 resume 返回,此時返回的第一個參數爲 false設計

3. ... = coroutine.yield(...)

參數
-... 傳入的參數將會由 resume 函數返回code

返回值
-... resume 函數傳入什麼,這裏就返回什麼orm

說明
yield 不能使用在元方法內部或者 pcall 內部協程

4. status = coroutine.status(co)

參數
-co 傳入須要查看狀態的協程實例對象,該參數不可省略喲htm

返回值
-status 一共running,suspended,normal,dead 四種狀態

說明
normal 狀態是指這樣一個協程,它當前正做爲調用者執行另一個協同程序。

簡單示例

1. 簡單協程對象的建立、使用與狀態查看

local co = coroutine.create(function () -- 建立一個協同程序對象 co
  print("Im in the coroutine~haha")
  coroutine.yield()         -- 第一次執行到此處掛起
  print("Im in the coroutine again !!") 
end)

coroutine.resume(co)          -- 第一次恢復協同程序 co
print(coroutine.status(co))       -- 查看當前協同程序的狀態,發現協同程序已經被掛起
coroutine.resume(co)          -- 第二次執行協同程序
print(coroutine.status(co))       -- 查看當前協同程序的狀態,發現協同程序已經死亡

-- output>> Im in the coroutine~haha
-- output>> suspended
-- output>> Im in the coroutine again !!
-- output>> dead

2. 協程中的參數傳遞

--根據字符串長度生成一個口令
local co = coroutine.create(function (basekey)
  while(1)do
    local salt = io.read()
    print("basekey:",basekey)

    local key1 = (basekey * #salt)..salt
    local yret = coroutine.yield(1,key1)
    print("yield return1:",yret)

    local key2 = salt..(basekey * #salt)
    yret = coroutine.yield(2,key2)
    print("yield return2:",yret)
  end
end)

math.randomseed(os.time())
while(1) do
  local rand = math.random(1,100)
  print("rand:",rand)
  local ret,selNo,key = coroutine.resume(co,rand)
  if ret then
    print(string.format("The %d key is %s",selNo,key))
  else
    print("generate fail")
    break
  end
end

-- output>> rand:   21
-- input  >> good
-- output>> basekey:        21
-- output>> The 1 key is 84good
-- output>> rand:   79
-- output>> yield return1:  79
-- output>> The 2 key is good84
-- output>> rand:   66
-- output>> yield return2:  66
-- input  >> job
-- output>> basekey:        21
-- output>> The 1 key is 63job
-- output>> rand:   78
-- output>> yield return1:  78
-- output>> The 2 key is job63
-- output>> rand:   83
-- output>> yield return2:  83
-- input  >> tangyikejun
-- output>> basekey:        21
-- output>> The 1 key is 231tangyikejun
-- output>> rand:   10
-- output>> yield return1:  10
-- output>> The 2 key is tangyikejun231
-- output>> rand:   68
-- output>> yield return2:  68

上面的輸出值得注意的是,basekey 的值一直都是 21 ,儘管rand 獲得的隨機數一直都在變。而 yield 的返回值則是下一次resume時傳入的參數。

以上代碼僅僅演示用法,可能並沒有任何實際意義。

生產者與消費者

本例源自 《 Lua 程序設計第二版》

-- 生產者 做爲協程
producer = coroutine.create(function()
  while true do
    local x = io.read()
    send(x)
  end
end
)

-- 消費者
function consumer()
  while true do
    local x = receive()
    io.write(x,"\n")
  end
end

-- 向生產者發起請求獲取信息
function receive()
  local status,value = coroutine.resume(producer)
  return value
end

-- 生產者將信息返回給消費者
function send(x)
  coroutine.yield(x) -- 發送數據 x 給協程調用者
end

-- 消費者驅動
consumer()

過濾器參與的生產者與消費者

本例源自 《 Lua 程序設計第二版》

有點相似於 linux 的 pipe 管道

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

function send(x)
  coroutine.yield(x) -- 發送數據 x 給協程調用者
end


-- 生產者 做爲協程
function producer()
  return coroutine.create(function()
    while true do
      local x = io.read()
      send(x)
    end
  end
  )
end

function filter(producer)
  return coroutine.create(function ()
    for line = 1,math.huge do
      local x = receive(producer)
      x = string.format("%5d %s",line,x)
      send(x)
    end
  end)
end

-- 消費者
function consumer(producer)
  while true do
    local x = receive(producer)
    io.write(x,"\n")
  end
end

local p = producer()
local f = filter(p)
consumer(f)

基於協程的迭代器

本例源自 《 Lua 程序設計第二版》

-- 一個逐一得到全排列的迭代器

-- 生成全排列
function mygen(a,n)
  if n == 1 then 
    coroutine.yield(a) 
  end

  for i=1,n do
    a[n],a[i] = a[i],a[n]    
    mygen(a,n-1)
    a[n],a[i] = a[i],a[n]
  end
end

-- 迭代器
function permutation(a)
  local co = coroutine.create(mygen)
  return function ()
    local res,t = coroutine.resume(co,a,#a,"")
    return t
  end
end

-- 使用
for a in permutation({1,2,3,4}) do
  for i,v in ipairs(a) do
    io.write(v)
  end
  io.write("\n")
end

同時發佈於博客園:http://www.cnblogs.com/tangyi...

相關文章
相關標籤/搜索