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.