LuaのCoroutine-コヒーレンスのマルチ「スレッド」同時モデルについて簡単に述べる
9030 ワード
『Programming in Lua』のコンコースプログラムの運用を見てみると、なんだか霧の中で花を見ているような気がしてポイントがつかめず、どうやって運用すればいいのかわからなかったのですが、お風呂に入っている間にひらめいて、いきなりReactor(反応時同期時間分派)モードを使っているだけではないかということがわかりました.ここでブログを書いて皆さんと拙見を共有します.
前によくわからなかったソースを貼っておきます
まず見てみましょう
dispatcher関数は実際にReactorモードのselectとpoll/epollとして機能する
getというファクトリ関数は,ディスペンサに「スレッド」(協同プログラム)を登録する役割を果たす.
downloadとreceiveの2つの関数はReactorモードで共通して1つのスレッドの役割を果たす
異なる点は、1、以上のLuaコードでは、Reactorモードのディスペンサ検出システムリソースの代わりに、追加のリカバリ/保留操作によってスレッドがアクティブかどうかを決定する
2、ディスペンサと各「スレッド」(協同プログラム)の実行は実際には1つのスレッドで実行されるため、システムを利用して真のスレッド間で時間を分けて切り替えることはできず、手動で切り替える必要がある.
Coroutine-コンカレントモデルの利点は、次のとおりです.
1、コンテキストを切り替えるコストは比較的小さい.
2、同期の問題を考慮する必要はありません.
実際にReactorモードでマルチコプロセッサを使うのは簡単です
グローバルなディスペンサを実装し、「スレッド」を登録するインタフェースを開くだけです.必要な協同プログラム(割り込み条件を含む必要があります)を書き込み、ディスペンサに登録します.
ディスペンサを実行すると、簡単なマルチスレッド同時実行が可能になります.もちろん、これは最も簡単なモデルにすぎません.少なくとも1つのスレッドにデータ読み取り可能なデータがある場合にのみ実行できます.各スレッドがアイドル状態にある場合、ディスペンサはスレッド状態をポーリングし続け、時間がかかります.
前によくわからなかったソースを貼っておきます
function download (host, file) -->
local c = assert(socket.connect(host, 80))
local count = 0 -- counts number of bytes read
c:send("GET " .. file .. " HTTP/1.0\r
\r
")
while true do
local s, status = receive©
count = count + string.len(s)
if status == "closed" then break end
end
c:close()
print(file, count)
end
function receive (connection) --> " "
connection:timeout(0) --> do not block
local s, status = connection:receive(2^10)
if status == "timeout" then
coroutine.yield(connection)
end
return s, status
end
threads = {} --> list of all live threads
function get (host, file) -->
local co = coroutine.create(function ()
download(host, file)
end)
table.insert(threads, co) --> insert it in the list
end
function dispatcher () -->
while true do
local n = table.getn(threads)
if n == 0 then break end
for i=1,n do
local status, res = coroutine.resume(threads[i])
if not res then
table.remove(threads, i)
break
end
end
end
end
まず見てみましょう
dispatcher関数は実際にReactorモードのselectとpoll/epollとして機能する
getというファクトリ関数は,ディスペンサに「スレッド」(協同プログラム)を登録する役割を果たす.
downloadとreceiveの2つの関数はReactorモードで共通して1つのスレッドの役割を果たす
異なる点は、1、以上のLuaコードでは、Reactorモードのディスペンサ検出システムリソースの代わりに、追加のリカバリ/保留操作によってスレッドがアクティブかどうかを決定する
2、ディスペンサと各「スレッド」(協同プログラム)の実行は実際には1つのスレッドで実行されるため、システムを利用して真のスレッド間で時間を分けて切り替えることはできず、手動で切り替える必要がある.
Coroutine-コンカレントモデルの利点は、次のとおりです.
1、コンテキストを切り替えるコストは比較的小さい.
2、同期の問題を考慮する必要はありません.
実際にReactorモードでマルチコプロセッサを使うのは簡単です
グローバルなディスペンサを実装し、「スレッド」を登録するインタフェースを開くだけです.必要な協同プログラム(割り込み条件を含む必要があります)を書き込み、ディスペンサに登録します.
ディスペンサを実行すると、簡単なマルチスレッド同時実行が可能になります.もちろん、これは最も簡単なモデルにすぎません.少なくとも1つのスレッドにデータ読み取り可能なデータがある場合にのみ実行できます.各スレッドがアイドル状態にある場合、ディスペンサはスレッド状態をポーリングし続け、時間がかかります.