iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
Software Development

30天 Lua重拾筆記系列 第 25

【30天Lua重拾筆記24】中級議題: coroutine

同步發表於個人網站

coroutine

Lua提供coroutine的函式庫,使其有能力編寫不同模式的程式。

thread create

你可以透過coroutine.create()建立一個thread

t1 = coroutine.create(function() print("Hello, World") end)
print(type(t1)) -- Output: thread

Lua並不是多執行緒的,其thread是輕量的。儘管Lua本身沒有異步(async)的寫法,但可以創造出異步的寫法。相對而言,值執行順序是明確許多的。

thread running

可以透過coroutine.resume()去觸發一個thread的執行:

coroutine.resume(t1) -- Output: Hello, World

傳入參數

可以對一個剛建立好的thread傳入參數。

function hello(name)
  while true do
    coroutine.yield("Hello, " .. name)
  end
end


t1 = coroutine.create(hello)
print(coroutine.status(t1)) -- suspended
print(coroutine.resume(t1, "Bob")) -- Output: Hello, Bob
print(coroutine.status(t1)) -- suspended
print(coroutine.resume(t1, "World")) -- Output: Hello, Bob

thread close

可以透過coroutine.clsoe()關閉thread

coroutine.close(t1) --> true
coroutine.status(t1) --> dead

※ Node: 執行完畢的t1原本就處於dead,而無法再次執行。

thread yield

返回值

可以透過coroutine.yield()可以保留執行狀態,並返回:

function genNumber(n)
  n = n or 0
  while n < 100 do
    n = n + 1
    coroutine.yield(n)
  end
end

t1 = coroutine.create(genNumber)
for i=1,3,1  do
  print(coroutine.resume(t1))
end

true 1
true 2
true 3

取得而外傳入值

coroutine.yield()也可以用於取得而外傳入參數,讓整個更靈活一些。

function genNumber(n)
  n = n or 0
  while n < 100 do
    n = coroutine.yield() or n
    n = n + 1
    coroutine.yield(n)
  end
  return 'finish'
end

t1 = coroutine.create(genNumber)
for i=1,3,1  do
  coroutine.resume(t1)
  print(coroutine.resume(t1)) --> 1, 2, 3
end

coroutine.resume(t1)
print(coroutine.resume(t1,96)) -- 97
for i=1,3,1  do
  coroutine.resume(t1)
  print(coroutine.resume(t1)) -->  98, 99, 100
end

print(coroutine.resume(t1)) --> finish
print(coroutine.status(t1)) --> dead

true 1
true 2
true 3
true 97
true 98
true 99
true 100
true finish
dead

thread wrap

thread.wrap()可以將thread包裹成函式function

t1 = coroutine.wrap(genNumber)
print(type(t1)) --> function
for i=1,3,1  do
  t1()
  print(t1()) --> 1, 2, 3
end

t1()
print(t1(96)) -- 97
for i=1,3,1  do
  t1()
  print(t1()) -->  98, 99, 100
end

print(t1()) --> finish

生產消費模式

當有客人(消費者)來的時候,主廚(生產者)就做餐給客人。

一對一

function producer()
  local i = 10
  while true do
    coroutine.yield(i)
    i = i + 10
  end
end

function consumer(p)
  for i=1,10,1 do
    local get = p()
    coroutine.yield(i, get)
  end
end

p = coroutine.wrap(producer)
c = coroutine.wrap(consumer)

-- start consumer, pass producer ---
i, p = c(p)
print("consume: i:", i, ", get:", p)


-- run until no consume --
while i do
  print("consume: i:", i, ", get:", p)
  i, p = c()
end

一對多

現在我們嘗試讓同一個生產者,服務兩個消費者:

p = coroutine.wrap(producer)
c1 = coroutine.wrap(consumer) -- consumer 1
c2 = coroutine.wrap(consumer) -- consumer 2

----- start consumer 1 with p ------
i1, get1 = c1(p)
print("consumer_1: i:", i1, "get:", get1)

----- start consumer 2 with p ------
i2, get2 = c2(p)
print("consumer_2: i:", i2, "get:", get2)

------ loop -------

while i1 or i2 do
  print("***************")
  if i1 then
    i1, get1 = c1()
    print("consumer_1: i:", i1, "get:", get1)
  end

  if i2 then
    i2, get2 = c2()
    print("consumer_2: i:", i2, "get:", get2)
  end
end
consumer_1: i:	1	get:	10
consumer_2: i:	1	get:	20
***************
consumer_1: i:	2	get:	30
consumer_2: i:	2	get:	40
***************
consumer_1: i:	3	get:	50
consumer_2: i:	3	get:	60
***************
consumer_1: i:	4	get:	70
consumer_2: i:	4	get:	80
***************
consumer_1: i:	5	get:	90
consumer_2: i:	5	get:	100
***************
consumer_1: i:	6	get:	110
consumer_2: i:	6	get:	120
***************
consumer_1: i:	7	get:	130
consumer_2: i:	7	get:	140
***************
consumer_1: i:	8	get:	150
consumer_2: i:	8	get:	160
***************
consumer_1: i:	9	get:	170
consumer_2: i:	9	get:	180
***************
consumer_1: i:	10	get:	190
consumer_2: i:	10	get:	200
***************
consumer_1: i:	nil	get:	nil
consumer_2: i:	nil	get:	nil

小後記

之前看書的時候,不覺得與Python的generator有啥差別,只知道Lua的coroutine好像更靈活。這次深入了解,有所體會。

比起Python的generator,Lua的coroutine提供更加強大的功能,可以實現更加靈活的模式。
也更難使用、更難理解?


上一篇
【30天Lua重拾筆記23】中級議題: 閉包
下一篇
【30天Lua重拾筆記25】進階議題: 模組化
系列文
30天 Lua重拾筆記36

尚未有邦友留言

立即登入留言