Lua-coroutines

提供:Dev Guides
移動先:案内検索

ルア-コルーチン

前書き

コルーチンは本質的に共同作業であり、2つ以上のメソッドを制御された方法で実行できます。 コルーチンを使用すると、常に1つのコルーチンのみが実行され、この実行中のコルーチンは明示的に中断を要求した場合にのみ実行を中断します。

上記の定義はあいまいに見えるかもしれません。 メインプログラムメソッドとコルーチンの2つのメソッドがあると仮定しましょう。 resume関数を使用してコルーチンを呼び出すと、実行が開始され、yield関数を呼び出すと、実行が中断されます。 繰り返しますが、同じコルーチンは、中断された場所から別の再開関数呼び出しで実行を継続できます。 このプロセスは、コルーチンの実行が終了するまで継続できます。

コルーチンで利用可能な機能

次の表は、Luaのコルーチンで使用可能なすべての関数と、それらに対応する使用を示しています。

Sr.No. Method & Purpose
1

coroutine.create (f)

関数fで新しいコルーチンを作成し、タイプ「スレッド」のオブジェクトを返します。

2

coroutine.resume (co [, val1, …​])

コルーチンcoを再開し、パラメーターがある場合は渡します。 操作のステータスと、その他のオプションの戻り値を返します。

3

coroutine.running ()

メインスレッドで呼び出された場合、実行中のコルーチンまたはnilを返します。

4

coroutine.status (co)

コルーチンの状態に基づいて、実行中、通常、一時停止、または停止のいずれかの値を返します。

5

coroutine.wrap (f)

coroutine.createと同様に、coroutine.wrap関数もコルーチンを作成しますが、コルーチン自体を返す代わりに、呼び出されたときにコルーチンを再開する関数を返します。

6

coroutine.yield (…​)

実行中のコルーチンを一時停止します。 このメソッドに渡されるパラメーターは、再開関数への追加の戻り値として機能します。

コルーチンの概念を理解するための例を見てみましょう。

co = coroutine.create(function (value1,value2)
   local tempvar3 = 10
   print("coroutine section 1", value1, value2, tempvar3)

   local tempvar1 = coroutine.yield(value1+1,value2+1)
   tempvar3 = tempvar3 + value1
   print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)

   local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
   tempvar3 = tempvar3 + value1
   print("coroutine section 3",tempvar1,tempvar2, tempvar3)
   return value2, "end"

end)

print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))

上記のプログラムを実行すると、次の出力が得られます。

coroutine section 1 3   2   10
main    true    4   3
coroutine section 2 12  nil 13
main    true    5   1
coroutine section 3 5   6   16
main    true    2   end
main    false   cannot resume dead coroutine

上記の例は何をしますか?

前述のように、再開機能を使用して操作を開始し、yield関数を使用して操作を停止します。 また、コルーチンの再開機能によって受信された複数の戻り値があることがわかります。

  • まず、コルーチンを作成し、変数名coに割り当てます。コルーチンはパラメーターとして2つの変数を受け取ります。
  • 最初の再開関数を呼び出すと、コルーチンの終了まで、値3と2が一時変数value1とvalue2に保持されます。
  • これを理解するために、最初は10であるtempvar3を使用しました。これは、コルーチンの実行中はvalue1が3として保持されるため、コルーチンの後続の呼び出しによって13と16に更新されます。
  • 最初のcoroutine.yieldは、2つの値4と3を再開関数に返します。これは、yieldステートメントの入力パラメーター3と2を更新することで取得できます。 また、コルーチン実行の真/偽ステータスを受け取ります。
  • 上記の例では、コルーチンに関するもう1つのことは、再開呼び出しの次のパラメーターがどのように処理されるかです。変数coroutine.yieldが次の呼び出しparamsを受け取ることがわかります。これは、既存のparam値の保持で新しい操作を実行する強力な方法を提供します。
  • 最後に、コルーチン内のすべてのステートメントが実行されると、後続の呼び出しはfalseを返し、応答として「デッドコルーチンを再開できません」ステートメントを返します。

別のコルーチンの例

yield関数とresume関数を使用して、1から5までの数を返す単純なコルーチンを見てみましょう。 利用できない場合はコルーチンを作成するか、既存のコルーチンを再開します。

function getNumber()
   local function getNumberHelper()
      co = coroutine.create(function ()
      coroutine.yield(1)
      coroutine.yield(2)
      coroutine.yield(3)
      coroutine.yield(4)
      coroutine.yield(5)
      end)
      return co
   end

   if(numberHelper) then
      status, number = coroutine.resume(numberHelper);

      if coroutine.status(numberHelper) == "dead" then
         numberHelper = getNumberHelper()
         status, number = coroutine.resume(numberHelper);
      end

      return number
   else
      numberHelper = getNumberHelper()
      status, number = coroutine.resume(numberHelper);
      return number
   end

end

for index = 1, 10 do
   print(index, getNumber())
end

上記のプログラムを実行すると、次の出力が得られます。

1   1
2   2
3   3
4   4
5   5
6   1
7   2
8   3
9   4
10  5

多くの場合、コルーチンとマルチプログラミング言語のスレッドとの比較がありますが、コルーチンはスレッドの同様の機能を備えていますが、一度に1つしか実行されず、同時に実行されないことを理解する必要があります。

特定の情報を一時的に保持することで、ニーズを満たすようにプログラム実行シーケンスを制御します。 コルーチンでグローバル変数を使用すると、コルーチンの柔軟性がさらに高まります。