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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow