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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow