Lua協同プログラム
4679 ワード
Lua協同プログラム作者:楊夢鳩 校正:翟舒青 協同(coroutine)とは?
Lua協同プログラム(coroutine)はスレッドと比較して類似している:独立したスタック、独立した局所変数、独立した命令ポインタを持ち、同時に他の協同プログラムとグローバル変数と他の大部分のものを共有する.
協同は非常に強力な機能ですが、使い勝手も複雑です.
スレッドと協同プログラムの違い
スレッドと協同プログラムの主な違いは、複数のスレッドを有するプログラムが複数のスレッドを同時に実行することができ、協同プログラムは互いに協力して実行する必要があることである.
いずれかの指定された時点で1つの協同プログラムのみが実行され、この実行中の協同プログラムは、明確に要求された保留時にのみ保留されます.
協同プログラムは同期したマルチスレッドに似ていて、同じスレッドロックを待っているいくつかのスレッドは少し協同しています.
基本構文
方法
説明
coroutine.create()
coroutineを作成し、coroutineを返します.パラメータは関数で、resumeと組み合わせて使用すると関数呼び出しが呼び出されます.
coroutine.resume()
coroutineを再起動し、createと組み合わせて使用
coroutine.yield()
coroutineを掛け、coroutineを掛け状態に設定すると、resumeと組み合わせて多くの効果が得られます.
coroutine.status()
coroutineのステータスを表示注意:coroutineのステータスは3種類あります:dead、suspend、running、具体的にいつこのようなステータスがあるかは以下のプログラムを参照してください
coroutine.wrap()
coroutineを作成し、関数を返します.この関数を呼び出すとcoroutineに入り、create機能と重複します.
coroutine.running()
走っているcoroutineを返します.coroutineはスレッドで、runningを使用するとcoroutingのスレッド番号を返します.
次の例では、上記の方法の使用方法を示します.
上記の例の出力結果は、次のとおりです.
coroutine.runningではcoroutineが最下位で実装されていることがわかります.
createがcoroutineを作成すると、新しいスレッドにイベントが登録されます.
resumeを使用してイベントをトリガすると、createのcoroutine関数が実行され、yieldに遭遇すると現在のスレッドが保留され、resumeトリガイベントの再起動を待つことになります.
次に、より詳細な例を分析します.
上記の例の出力結果は、次のとおりです.
次の例を示します.はresumeを呼び出し、協同プログラムを起動し、resume操作はtrueに正常に戻り、そうでなければfalseに戻る. 協同プログラム実行; yield文に実行されます. yieldは協同プログラムを掛け、初めてresumeが戻った.(注:ここでyieldはresumeのパラメータを返します) 第2回resume、再び協同プログラムを起動する.(注:ここでresumeのパラメータでは、最初のパラメータを除いて、残りのパラメータはyieldのパラメータとして使用されます) yieldが戻る. 協同プログラムは引き続き実行する. 使用する協同プログラムが実行を継続した後にresumeメソッドを呼び出し続ける場合、出力:cannot resume dead coroutine resumeとyieldの協力の強さは、resumeがプライマリ・パスにあり、外部状態(データ)を協同プログラムの内部に伝達することである.一方yieldは内部の状態(データ)をメインパスに返す.
生産者-消費者問題
今、私はLuaの協同プログラムを使って生産者-消費者という古典的な問題を完成します.
上記の例の出力結果は、次のとおりです.
Lua協同プログラム(coroutine)はスレッドと比較して類似している:独立したスタック、独立した局所変数、独立した命令ポインタを持ち、同時に他の協同プログラムとグローバル変数と他の大部分のものを共有する.
協同は非常に強力な機能ですが、使い勝手も複雑です.
スレッドと協同プログラムの違い
スレッドと協同プログラムの主な違いは、複数のスレッドを有するプログラムが複数のスレッドを同時に実行することができ、協同プログラムは互いに協力して実行する必要があることである.
いずれかの指定された時点で1つの協同プログラムのみが実行され、この実行中の協同プログラムは、明確に要求された保留時にのみ保留されます.
協同プログラムは同期したマルチスレッドに似ていて、同じスレッドロックを待っているいくつかのスレッドは少し協同しています.
基本構文
方法
説明
coroutine.create()
coroutineを作成し、coroutineを返します.パラメータは関数で、resumeと組み合わせて使用すると関数呼び出しが呼び出されます.
coroutine.resume()
coroutineを再起動し、createと組み合わせて使用
coroutine.yield()
coroutineを掛け、coroutineを掛け状態に設定すると、resumeと組み合わせて多くの効果が得られます.
coroutine.status()
coroutineのステータスを表示注意:coroutineのステータスは3種類あります:dead、suspend、running、具体的にいつこのようなステータスがあるかは以下のプログラムを参照してください
coroutine.wrap()
coroutineを作成し、関数を返します.この関数を呼び出すとcoroutineに入り、create機能と重複します.
coroutine.running()
走っているcoroutineを返します.coroutineはスレッドで、runningを使用するとcoroutingのスレッド番号を返します.
次の例では、上記の方法の使用方法を示します.
-- coroutine_test.lua
co = coroutine.create(
function(i)
print(i);
end
)
coroutine.resume(co, 1) -- 1
print(coroutine.status(co)) -- dead
print("----------")
co = coroutine.wrap(
function(i)
print(i);
end
)
co(1)
print("----------")
co2 = coroutine.create(
function()
for i=1,10 do
print(i)
if i == 3 then
print(coroutine.status(co2)) --running
print(coroutine.running()) --thread:XXXXXX
end
coroutine.yield()
end
end
)
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
print(coroutine.status(co2)) -- suspended
print(coroutine.running())
print("----------")
上記の例の出力結果は、次のとおりです.
1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868 false
suspended
thread: 0x7fb801c04c88 true
----------
coroutine.runningではcoroutineが最下位で実装されていることがわかります.
createがcoroutineを作成すると、新しいスレッドにイベントが登録されます.
resumeを使用してイベントをトリガすると、createのcoroutine関数が実行され、yieldに遭遇すると現在のスレッドが保留され、resumeトリガイベントの再起動を待つことになります.
次に、より詳細な例を分析します.
function foo (a)
print("foo ", a)
return coroutine.yield(2 * a) -- 2*a
end
co = coroutine.create(function (a , b)
print(" ", a, b) -- co-body 1 10
local r = foo(a + 1)
print(" ", r)
local r, s = coroutine.yield(a + b, a - b) -- a,b
print(" ", r, s)
return b, " " -- b
end)
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("-- ----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("--- ---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("--- ---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("--- ---")
上記の例の出力結果は、次のとおりです.
1 10
foo 2
main true 4
-- ----
r
main true 11 -9
--- ---
x y
main true 10
--- ---
main false cannot resume dead coroutine
--- ---
次の例を示します.
生産者-消費者問題
今、私はLuaの協同プログラムを使って生産者-消費者という古典的な問題を完成します.
local newProductor
function productor()
local i = 0
while true do
i = i + 1
send(i) --
end
end
function consumer()
while true do
local i = receive() --
print(i)
end
end
function receive()
local status, value = coroutine.resume(newProductor)
return value
end
function send(x)
coroutine.yield(x) -- x , ,
end
--
newProductor = coroutine.create(productor)
consumer()
上記の例の出力結果は、次のとおりです.
1
2
3
4
5
6
7
8
9
10
11
12
13
……