Sök…
Syntax
coroutine.create (funktion) returnerar en coroutine (typ (coroutine) == 'tråd') som innehåller funktionen.
coroutine.resume (co, ...) återuppta, eller starta coroutine. Eventuella ytterligare argument som återupptas returneras från coroutine.yield () som tidigare pausade coroutine. Om koroutinen inte hade startats blir de ytterligare argumenten argumentens funktion.
coroutine.yield (...) ger den nuvarande körningen. Utförandet plockas tillbaka efter samtalet till coroutine.resume () som startade den koroutinen. Alla argument som ges för att ge tillbaka returneras från motsvarande coroutine.resume () som startade coroutine.
coroutine.status (co) returnerar statusen för coroutine, vilket kan vara:
- "död": funktionen i koroutinen har nått sitt slut och koroutinen kan inte återupptas längre
- "kör": koroutinen har återupptagits och körs
- "normalt": koroutinen har återupptagit en annan koroutin
- "avstängd": koroutinen har gett sig och väntar på att återupptas
coroutine.wrap (funktion) returnerar en funktion som när den kallas återupptar den coroutine som skulle ha skapats av coroutine.create (funktion).
Anmärkningar
Koroutinsystemet har implementerats i lua för att emulera multithreading som finns på andra språk. Det fungerar genom att växla med extremt hög hastighet mellan olika funktioner så att den mänskliga användaren tror att de körs samtidigt.
Skapa och använda en koroutin
Alla funktioner för att interagera med koroutiner är tillgängliga i koroutintabellen . En ny coroutine skapas genom att använda funktionen coroutine.create med ett enda argument: en funktion med koden som ska köras:
thread1 = coroutine.create(function()
print("honk")
end)
print(thread1)
-->> thread: 6b028b8c
Ett coroutine-objekt returnerar värdet på typtråd , vilket representerar en ny coroutine. När en ny koroutin skapas avbryts dess ursprungliga tillstånd:
print(coroutine.status(thread1))
-->> suspended
För att återuppta eller starta en coroutine används funktionen coroutine.resume , det första argumentet som givits är trådobjektet:
coroutine.resume(thread1)
-->> honk
Nu kör koroutinen koden och avslutas och ändrar dess tillstånd till död , vilket inte kan återupptas.
print(coroutine.status(thread1))
-->> dead
Coroutines kan avbryta genomförandet och återuppta det senare tack vare funktionen coroutine.yield :
thread2 = coroutine.create(function()
for n = 1, 5 do
print("honk "..n)
coroutine.yield()
end
end)
Som ni ser är coroutine.yield () närvarande i for-loopen, nu när vi återupptar coroutine kommer den att köra koden tills den når en coroutine.yield:
coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2
Efter avslutad slinga blir trådstatusen död och kan inte återupptas. Coroutines tillåter också utbyte mellan data:
thread3 = coroutine.create(function(complement)
print("honk "..complement)
coroutine.yield()
print("honk again "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow
Om koroutinen körs igen utan extra argument, kommer komplementet fortfarande att argumentera från den första CV, i detta fall "stackoverflow":
coroutine.resume(thread3)
-->> honk again stackoverflow
Slutligen, när en koroutin slutar, går alla värden som returneras med dess funktion till motsvarande 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 används i denna funktion för att skicka värden tillbaka till en samtalstråd djupt i ett rekursivt samtal.
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 kan också användas för lat utvärdering.
-- 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 kan användas för rörkonstruktioner som beskrivs i Programming In Lua . Författaren till PiL, Roberto Ierusalimschy, har också publicerat ett dokument om att använda koroutiner för att implementera mer avancerad och allmän flödeskontrollmekanik som fortsättningar.