Latest web development tutorials

Luaのコルーチン(コルーチン)

相乗(コルーチン)とは何ですか?

Luaのコルーチン(コルーチン)スレッド比較的類似:独立したスタック、ローカル変数を分離、独立した命令ポインタだけでなく、共有グローバル変数、および他のほとんどのものと他の共同プログラム。

Synergyは非常に強力ですが、また、使用することは非常に複雑。

スレッドとコルーチンとの間の差

プログラムが協調プログラムが別のコラボレーションについて必要があるだろうしながら、同時に複数のスレッドを実行できる複数のスレッドを持っているスレッドとコルーチンとの主な違い。

任意の時点で一つだけの協力プログラムが実行され、実行中のコルーチンのみが中断されます一時停止時間をクリアする必要があります。

ロック複数のスレッド多少似コラボレーションを待っている同じスレッドで複数のスレッドを同期するために多少似共同プログラム。

基本的な構文

ウェイ 説明
coroutine.create() コルーチンを作成し、コルーチンを返す、と組み合わせて使用​​する引数は、関数であり、ときにウェイクアップ機能の呼び出しを再開
coroutine.resume() コルーチンを再起動しての使用と作成
coroutine.yield() 一時停止コルーチン、有用な効果の多くを持っているために、このを使用した保留状態と履歴書にコルーチン
coroutine.status() コルーチンメモのステータスをチェックします。コルーチン状態を、3があります。死んで、サスペンド、このような状態が存在する場合に、特に、以下の手順を参照してください、実行しています
coroutine.wrap() コルーチンを作成し、一度あなたが、この関数を呼び出しコルーチンを入力し、繰り返し関数を作成関数を返します
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を見ることができる、コルーチン実装は、下部のスレッドです。

イベントは新しいスレッドで登録されている場合ときにコルーチンを作成します。

レジュームイベントがトリガされるとコルーチン関数が実行されたときに、作成し、代わって歩留まりに直面したとき、再びイベント待ちをトリガー再開するために、現在のスレッドを中断します。

次に、我々はより詳細な例を分析します:

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
---分割线---

例としては、次のとおり引き継ぎました:

  • コール履歴書は、そうでない場合はfalseを返し、真の動作に成功リターンを再開し、ウェイクアップを調整します。
  • 共同プログラムの実行;
  • 文を生成するために実行します。
  • (:収量リターンをここでのパラメータはパラメータです再開することに注意してください)。収量はコルーチン最初再開リターンを中断しました
  • 第二に、再開、再び目を覚ますには、コルーチン;(注:このレジュームパラメータを、最初の引数に加えて、残りのパラメータは、パラメータとして生成します)
  • 収量が戻ります。
  • 共同プログラムは実行を続けます。
  • あなたが協力的なプログラムを実行し続ける方法は、出力の完了後に再開を呼び出すために続けて使用している場合:死者コルーチンを再開することはできません

その履歴書や歩留まりのある場所の電源、メインプログラムで再開、それは状態(データ)の外になりますが、内部の調整手続きに渡され、内部状態(データ)をもたらすメイン処理に戻ります。


生産 - 消費者問題

この古典的な問題の消費者は - 私は今、生産者が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
……