Lua - Coroutinen

Einführung

Coroutinen sind kollaborativer Natur, wodurch zwei oder mehr Methoden kontrolliert ausgeführt werden können. Bei Coroutinen wird zu einem bestimmten Zeitpunkt nur eine Coroutine ausgeführt, und diese laufende Coroutine setzt ihre Ausführung nur dann aus, wenn sie ausdrücklich die Unterbrechung anfordert.

Die obige Definition kann vage aussehen. Nehmen wir an, wir haben zwei Methoden, eine die Hauptprogrammmethode und eine Coroutine. Wenn wir eine Coroutine mit der Resume-Funktion aufrufen, wird sie ausgeführt, und wenn wir die Yield-Funktion aufrufen, wird die Ausführung angehalten. Wiederum kann dieselbe Coroutine mit einem anderen Funktionsaufruf zur Wiederaufnahme fortgesetzt werden, von dem aus sie angehalten wurde. Dieser Vorgang kann bis zum Ende der Ausführung der Coroutine fortgesetzt werden.

In Coroutinen verfügbare Funktionen

In der folgenden Tabelle sind alle verfügbaren Funktionen für Coroutinen in Lua und ihre entsprechende Verwendung aufgeführt.

Sr.Nr. Methode & Zweck
1

coroutine.create (f)

Erstellt eine neue Coroutine mit der Funktion f und gibt ein Objekt vom Typ "thread" zurück.

2

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

Setzt die Coroutine co fort und übergibt die Parameter, falls vorhanden. Es gibt den Betriebsstatus und optional andere Rückgabewerte zurück.

3

coroutine.running ()

Gibt die laufende Coroutine oder Null zurück, wenn sie im Hauptthread aufgerufen wird.

4

coroutine.status (co)

Gibt einen der Werte aus "Laufen", "Normal", "Angehalten" oder "Tot" basierend auf dem Status der Coroutine zurück.

5

coroutine.wrap (f)

Wie coroutine.create erstellt auch die Funktion coroutine.wrap eine Coroutine, aber anstatt die Coroutine selbst zurückzugeben, gibt sie eine Funktion zurück, die beim Aufruf die Coroutine wieder aufnimmt.

6

coroutine.yield (...)

Hält die laufende Coroutine an. Der an diese Methode übergebene Parameter dient als zusätzliche Rückgabewerte für die Wiederaufnahmefunktion.

Beispiel

Schauen wir uns ein Beispiel an, um das Konzept der Coroutinen zu verstehen.

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

Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.

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

Was macht das obige Beispiel?

Wie bereits erwähnt, verwenden wir die Wiederaufnahmefunktion, um die Operation zu starten, und die Yield-Funktion, um die Operation zu stoppen. Sie können auch sehen, dass mehrere Rückgabewerte von der Wiederaufnahmefunktion von Coroutine empfangen werden.

  • Zuerst erstellen wir eine Coroutine und weisen sie einem Variablennamen co zu. Die Coroutine nimmt zwei Variablen als Parameter auf.

  • Wenn wir die erste Wiederaufnahmefunktion aufrufen, bleiben die Werte 3 und 2 in den temporären Variablen value1 und value2 bis zum Ende der Coroutine erhalten.

  • Um dies zu verstehen, haben wir eine Tempvar3 verwendet, die anfänglich 10 ist und durch die nachfolgenden Aufrufe der Coroutinen auf 13 und 16 aktualisiert wird, da Wert1 während der Ausführung der Coroutine als 3 beibehalten wird.

  • Die erste coroutine.yield gibt zwei Werte 4 und 3 an die Resume-Funktion zurück, die wir durch Aktualisieren der Eingabeparameter 3 und 2 in der Yield-Anweisung erhalten. Es erhält auch den True / False-Status der Coroutine-Ausführung.

  • Eine andere Sache über Coroutinen ist, wie die nächsten Parameter des Wiederaufnahmeaufrufs im obigen Beispiel erledigt werden; Sie können sehen, dass die Variable coroutine.yield die nächsten Aufrufparameter empfängt. Dies bietet eine leistungsstarke Möglichkeit, neue Operationen unter Beibehaltung vorhandener Parameterwerte durchzuführen.

  • Sobald alle Anweisungen in den Coroutinen ausgeführt wurden, werden die nachfolgenden Aufrufe in false zurückgegeben und die Anweisung "tote Coroutine kann nicht fortgesetzt werden" als Antwort.

Ein weiteres Coroutine-Beispiel

Betrachten wir eine einfache Coroutine, die mit Hilfe der Ertragsfunktion und der Wiederaufnahmefunktion eine Zahl von 1 bis 5 zurückgibt. Es erstellt eine Coroutine, wenn diese nicht verfügbar ist, oder setzt die vorhandene Coroutine fort.

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

Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.

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

Es gibt oft einen Vergleich von Coroutinen mit den Threads von Multiprogrammiersprachen, aber wir müssen verstehen, dass Coroutinen ähnliche Thread-Funktionen haben, aber jeweils nur eine ausführen und niemals gleichzeitig ausgeführt werden.

Wir steuern die Programmausführungssequenz, um die Anforderungen zu erfüllen, indem bestimmte Informationen vorübergehend aufbewahrt werden. Die Verwendung globaler Variablen mit Coroutinen bietet Coroutinen noch mehr Flexibilität.