DAY 25
0
Software Development

# coroutine

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

``````t1 = coroutine.create(function() print("Hello, World") end)
``````

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

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

### 傳入參數

``````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
``````

``````coroutine.close(t1) --> true
``````

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

### 返回值

``````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
``````

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

`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
``````

30天 Lua重拾筆記36