Suche…
Syntax
coroutine.create (function) gibt eine Coroutine (type (coroutine) == 'thread') zurück, die die Funktion enthält.
coroutine.resume (co, ...) fortsetzen oder Coroutine starten. Alle weiteren Argumente, die zum Fortsetzen gegeben werden, werden von der Coroutine.yield () zurückgegeben, die zuvor die Coroutine angehalten hat. Wenn die Coroutine nicht gestartet wurde, werden die zusätzlichen Argumente zu den Argumenten der Funktion.
coroutine.yield (...) liefert die aktuell laufende Coroutine. Die Ausführung wird nach dem Aufruf von coroutine.resume (), mit dem diese Coroutine gestartet wurde, wiederhergestellt. Alle Argumente, die gegeben werden, werden von der entsprechenden coroutine.resume (), die die Coroutine gestartet hat, zurückgegeben.
coroutine.status (co) gibt den Status der Coroutine zurück. Dies kann sein:
- "dead": Die Funktion der Coroutine hat ihr Ende erreicht und die Coroutine kann nicht mehr fortgesetzt werden
- "running": Die Coroutine wurde fortgesetzt und läuft
- "normal": Die Coroutine hat eine weitere Coroutine wieder aufgenommen
- "suspendiert": Die Coroutine hat nachgegeben und wartet darauf, wieder aufgenommen zu werden
coroutine.wrap (function) gibt eine Funktion zurück, die beim Aufruf der Coroutine, die von coroutine.create (function) erstellt worden wäre, fortsetzt.
Bemerkungen
Das Coroutine-System wurde in Lua implementiert, um das Multithreading in anderen Sprachen zu emulieren. Es wechselt mit extrem hoher Geschwindigkeit zwischen verschiedenen Funktionen, sodass der Benutzer glaubt, dass sie gleichzeitig ausgeführt werden.
Erstellen und verwenden Sie eine Coroutine
Alle Funktionen für die Interaktion mit Coroutinen stehen in der Coroutine- Tabelle zur Verfügung. Eine neue Coroutine wird erstellt, indem die Funktion coroutine.create mit einem einzigen Argument verwendet wird: eine Funktion mit dem auszuführenden Code:
thread1 = coroutine.create(function()
print("honk")
end)
print(thread1)
-->> thread: 6b028b8c
Ein Coroutine-Objekt gibt den Wert des Typs thread zurück , der eine neue Coroutine darstellt. Wenn eine neue Coroutine erstellt wird, wird der ursprüngliche Status ausgesetzt:
print(coroutine.status(thread1))
-->> suspended
Um eine Coroutine fortzusetzen oder zu starten, wird die Funktion coroutine.resume verwendet. Als erstes Argument wird das Thread-Objekt angegeben:
coroutine.resume(thread1)
-->> honk
Jetzt führt die Coroutine den Code aus und beendet den Status, wobei der Status auf " tot" gesetzt wird, der nicht wieder aufgenommen werden kann.
print(coroutine.status(thread1))
-->> dead
Koroutinen kann seine Ausführung unterbrechen und später dank der coroutine.yield Funktion wieder aufnehmen:
thread2 = coroutine.create(function()
for n = 1, 5 do
print("honk "..n)
coroutine.yield()
end
end)
Wie Sie sehen können, ist coroutine.yield () in der for-Schleife vorhanden. Wenn Sie nun die Coroutine fortsetzen, wird der Code ausgeführt, bis er eine coroutine.yield erreicht:
coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2
Nach Beendigung der Schleife wird der Threadstatus " tot" und kann nicht fortgesetzt werden. Coroutines ermöglichen auch den Austausch zwischen Daten:
thread3 = coroutine.create(function(complement)
print("honk "..complement)
coroutine.yield()
print("honk again "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow
Wenn die Coroutine ohne zusätzliche Argumente erneut ausgeführt wird, bleibt das Komplement immer das Argument des ersten Lebenslaufs, in diesem Fall "stackoverflow":
coroutine.resume(thread3)
-->> honk again stackoverflow
Wenn eine Coroutine endet, gehen alle von ihrer Funktion zurückgegebenen Werte zum entsprechenden Lebenslauf:
thread4 = coroutine.create(function(a, b)
local c = a+b
coroutine.yield()
return c
end)
coroutine.resume(thread4, 1, 2)
print(coroutine.resume(thread4))
-->> true, 3
Coroutines werden in dieser Funktion verwendet, um Werte aus einem rekursiven Aufruf von tief aus an einen aufrufenden Thread zurückzugeben.
local function Combinations(l, r)
local ll = #l
r = r or ll
local sel = {}
local function rhelper(depth, last)
depth = depth or 1
last = last or 1
if depth > r then
coroutine.yield(sel)
else
for i = last, ll - (r - depth) do
sel[depth] = l[i]
rhelper(depth+1, i+1)
end
end
end
return coroutine.wrap(rhelper)
end
for v in Combinations({1, 2, 3}, 2) do
print("{"..table.concat(v, ", ").."}")
end
--> {1, 2}
--> {1, 3}
--> {2, 3}
Coroutinen können auch für die faule Beurteilung verwendet werden.
-- slices a generator 'c' taking every 'step'th output from the generator
-- starting at the 'start'th output to the 'stop'th output
function slice(c, start, step, stop)
local _
return coroutine.wrap(function()
for i = 1, start-1 do
_ = c()
end
for i = start, stop do
if (i - start) % step == 0 then
coroutine.yield(c())
else
_ = c()
end
end
end)
end
local alphabet = {}
for c = string.byte('a'), string.byte('z') do
alphabet[#alphabet+1] = string.char(c)
end
-- only yields combinations 100 through 102
-- requires evaluating the first 100 combinations, but not the next 5311633
local s = slice(Combinations(alphabet, 10), 100, 1, 102)
for i in s do
print(table.concat(i))
end
--> abcdefghpr
--> abcdefghps
--> abcdefghpt
Coroutinen können für Piping-Konstrukte verwendet werden, wie in Programmieren in Lua beschrieben . Der Autor von PiL, Roberto Ierusalimschy, hat auch einen Artikel über die Verwendung von Coroutinen veröffentlicht, um fortschrittlichere und allgemeine Flusssteuerungsmechanismen wie Fortsetzungen zu implementieren.