Zoeken…


Syntaxis

  • coroutine.create (functie) retourneert een coroutine (type (coroutine) == 'thread') met de functie.

  • coroutine.resume (co, ...) hervatten, of start de coroutine. Eventuele aanvullende argumenten die worden gegeven om te hervatten, worden geretourneerd vanuit de coroutine.yield () die de coroutine eerder heeft onderbroken. Als de coroutine niet was gestart, worden de aanvullende argumenten de argumenten van de functie.

  • coroutine.yield (...) levert de momenteel lopende coroutine op. De uitvoering wordt weer opgehaald na de aanroep van coroutine.resume () waarmee die coroutine is gestart. Alle argumenten voor opbrengst worden geretourneerd uit de overeenkomstige coroutine.resume () waarmee de coroutine is gestart.

  • coroutine.status (co) geeft de status van de coroutine terug, wat kan zijn:

    • "dood": de functie in de coroutine heeft zijn einde bereikt en de coroutine kan niet meer worden hervat
    • "running": de coroutine is hervat en loopt
    • "normaal": de coroutine heeft een andere coroutine hervat
    • "geschorst": de coroutine heeft toegegeven en wacht op hervatting
  • coroutine.wrap (functie) retourneert een functie die, wanneer deze wordt aangeroepen, de coroutine hervat die zou zijn gemaakt door coroutine.create (functie).

Opmerkingen

Het coroutinesysteem is geïmplementeerd in lua om multithreading in andere talen te emuleren. Het werkt door met extreem hoge snelheid tussen verschillende functies te schakelen, zodat de menselijke gebruiker denkt dat ze tegelijkertijd worden uitgevoerd.

Maak en gebruik een coroutine

Alle functies voor interactie met coroutines zijn beschikbaar in de coroutinetabel . Een nieuwe coroutine wordt gemaakt door de functie coroutine.create te gebruiken met een enkel argument: een functie met de uit te voeren code:

thread1 = coroutine.create(function()
            print("honk")
        end)

print(thread1)
-->> thread: 6b028b8c

Een coroutine-object retourneert de waarde van het type thread , dat een nieuwe coroutine vertegenwoordigt. Wanneer een nieuwe coroutine wordt gemaakt, wordt de oorspronkelijke status opgeschort:

print(coroutine.status(thread1))
-->> suspended

Om een coroutine te hervatten of te starten, wordt de functie coroutine.resume gebruikt, het eerste gegeven argument is het threadobject :

coroutine.resume(thread1)
-->> honk

Nu voert de coroutine de code uit en eindigt, en verandert de status in dood , wat niet kan worden hervat.

print(coroutine.status(thread1))
-->> dead

Coroutines kunnen de uitvoering opschorten en later hervatten dankzij de functie coroutine.yield :

thread2 = coroutine.create(function()
        for n = 1, 5 do
            print("honk "..n)
            coroutine.yield()
        end
    end)

Zoals u kunt zien, is coroutine.yield () aanwezig in de for-lus. Wanneer we de coroutine hervatten, wordt de code uitgevoerd totdat deze een coroutine.yield bereikt:

coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2

Nadat de lus, de draad toestand dood wordt en kan niet worden hervat. Coroutines staat ook de uitwisseling tussen gegevens toe:

thread3 = coroutine.create(function(complement)
    print("honk "..complement)
    coroutine.yield()
    print("honk again "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow

Als de coroutine opnieuw wordt uitgevoerd zonder extra argumenten, blijft het complement het argument van de eerste cv, in dit geval "stackoverflow":

coroutine.resume(thread3)
-->> honk again stackoverflow

Als ten slotte een coroutine eindigt, gaan alle waarden die door zijn functie worden geretourneerd naar de bijbehorende cv:

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 worden in deze functie gebruikt om waarden diep binnen een recursieve aanroep door te geven aan een oproepende thread.

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}

Coroutines kunnen ook worden gebruikt voor luie evaluatie.

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

Coroutines kunnen worden gebruikt voor leidingconstructies zoals beschreven in Programmering in Lua . De auteur van PiL, Roberto Ierusalimschy, heeft ook een artikel gepubliceerd over het gebruik van coroutines om geavanceerdere en algemene stroomregelmechanica zoals continuaties te implementeren.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow