Lua Academy · leksjon

Coroutine-status

Kontroller coroutine-ens tilstand med coroutine.status: running, suspended, dead.

Leksjon 3 av 412 trinn

Coroutine-status er en gratis leksjon i Lua Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Lua Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Lua Academy inneholder totalt 4 leksjoner.

Fire korutinetilstander

Korutiner har fire mulige tilstander: suspendert (opprettet eller satt på pause, venter på å kjøre), kjører (kjører for øyeblikket), normal (satt på pause for å la en annen korutine kjøre) og død (avsluttet eller har fått en feil). Spør med coroutine.status(co).

local co = coroutine.create(function()
  print(coroutine.status(coroutine.running()))  -- running
  coroutine.yield()
end)

print(coroutine.status(co))  -- suspended
coroutine.resume(co)          -- prints: running
print(coroutine.status(co))  -- suspended
coroutine.resume(co)
print(coroutine.status(co))  -- dead

Tilstanden «normal»

En korutine går inn i tilstanden «normal» når den gjenopptar en annen korutine. Den kjører ikke (det gjør den andre korutinen), men den er heller ikke suspendert – den venter på at den gjenopptatte korutinen skal utføre yield. Denne tilstanden er sjelden, men viktig å forstå i komplekse korutinegrafer.

local inner, outer

inner = coroutine.create(function()
  print("outer status:", coroutine.status(outer))  -- normal
  coroutine.yield()
end)

outer = coroutine.create(function()
  coroutine.resume(inner)
end)

coroutine.resume(outer)
-- prints: outer status: normal

Kontroll før gjenopptakelse

Kontroller alltid en korutinens status før De gjenopptar den, spesielt i løkker. Det er en feil å gjenoppta en død korutine. Det er også en feil å gjenoppta en korutine som allerede kjører (det ville føre til uendelig rekursjon).

local function safeResume(co, ...)
  local status = coroutine.status(co)
  if status == "dead" then
    return false, "cannot resume dead coroutine"
  end
  if status == "running" then
    return false, "cannot resume running coroutine"
  end
  return coroutine.resume(co, ...)
end

Status etter feil

Når korutinens hoveddel utløser en uhåndtert feil, returnerer coroutine.resume false og feilmeldingen. Korutinen går over i tilstanden «død». Den kan ikke startes på nytt – De må opprette en ny korutine hvis De vil prøve igjen.

local co = coroutine.create(function()
  error("something went wrong")
end)

local ok, err = coroutine.resume(co)
print(ok, err)                      -- false  ...: something went wrong
print(coroutine.status(co))         -- dead

-- Cannot resume dead coroutine:
local ok2, err2 = coroutine.resume(co)
print(ok2, err2)  -- false  cannot resume dead coroutine

coroutine.isyieldable

coroutine.isyieldable() returnerer true hvis korutinen som kjører, kan utføre yield. Den returnerer false i hovedtråden og i C-funksjoner som ikke støtter yield. Kontroller alltid dette før De utfører yield hvis De er usikker på konteksten.

local co = coroutine.create(function()
  print("isyieldable:", coroutine.isyieldable())  -- true
  coroutine.yield()
end)

coroutine.resume(co)

-- In main thread:
print("isyieldable:", coroutine.isyieldable())  -- false
-- coroutine.yield()  -- ERROR in main thread

Overvåke et sett med korutiner

Følg med på en pulje med korutiner, og fjern døde korutiner etter hver runde med gjenopptakelser. Dette er grunnlaget for en oppgaveplanlegger.

local function makeWorker(n, name)
  return coroutine.create(function()
    for i = 1, n do
      print(name, "step", i)
      coroutine.yield()
    end
  end)
end

local workers = {
  makeWorker(2, "fast"),
  makeWorker(4, "slow"),
}

while #workers > 0 do
  local alive = {}
  for _, co in ipairs(workers) do
    coroutine.resume(co)
    if coroutine.status(co) ~= "dead" then
      alive[#alive+1] = co
    end
  end
  workers = alive
end

Feilsøking av korutiner

Bruk statuskontroller til å instrumentere og feilsøke korutinebasert kode. Skriv ut statusoverganger for å forstå flyten. I komplekse systemer kan De tilordne korutiner navn via en wrapper-tabell for å få bedre feilsøkingsutdata.

local function namedCo(name, fn)
  local co = coroutine.create(fn)
  return {
    co = co,
    name = name,
    resume = function(self, ...)
      print("[" .. self.name .. "] resume")
      local results = table.pack(coroutine.resume(self.co, ...))
      print("[" .. self.name .. "] status: " .. coroutine.status(self.co))
      return table.unpack(results, 1, results.n)
    end
  }
end

local worker = namedCo("worker1", function()
  coroutine.yield()
end)
worker:resume()
worker:resume()

Starte døde korutiner på nytt

Når en korutine er død, kan den ikke gjenopptas. For å «starte den på nytt» må De opprette en ny korutine fra den samme funksjonen. Et vanlig mønster er en fabrikk som oppretter en ny korutine ved behov.

local function makeCounter(start, step)
  return coroutine.wrap(function()
    local n = start or 0
    while true do
      coroutine.yield(n)
      n = n + (step or 1)
    end
  end)
end

local count = makeCounter(0, 2)
for i = 1, 5 do io.write(count() .. " ") end
print()  -- 0 2 4 6 8

-- "Restart" by creating a new one
count = makeCounter(100)
print(count())   -- 100

Feilatferd for Coroutine.wrap

Når en innpakket korutine får en feil, forplanter feilen seg ut av wrapper-funksjonskallet. I motsetning til coroutine.resume, som returnerer false+error, utløser funksjoner som returneres av wrap, feilen direkte. Bruk pcall rundt wrap-kall hvis De må fange feil.

local gen = coroutine.wrap(function()
  coroutine.yield(1)
  error("oops")
  coroutine.yield(2)  -- never reached
end)

print(gen())   -- 1 (ok)
local ok, err = pcall(gen)
print(ok, err) -- false  ...: oops
-- Subsequent call: dead coroutine
ok, err = pcall(gen)
print(ok, err) -- false  cannot resume dead coroutine

isyieldable kontra status

Det finnes to måter å undersøke korutinekonteksten på: coroutine.status(co) angir tilstanden til en bestemt korutine, mens coroutine.isyieldable() forteller om den gjeldende kjøringskonteksten kan utføre yield. Bruk status for å kontrollere andre korutiner, og isyieldable for å kontrollere om De trygt kan utføre yield.

local function maybeYield()
  if coroutine.isyieldable() then
    coroutine.yield()
  else
    -- in main thread or non-yieldable context
    print("cannot yield here")
  end
end

maybeYield()  -- prints "cannot yield here" (main thread)

local co = coroutine.create(maybeYield)
coroutine.resume(co)   -- yields successfully

Hurtigsjekk

Hvilken tilstand går en korutine inn i når den er ferdig med å kjøre funksjonen sin?

Oppsummering: Korutinestatus

Oppsummering:

  • Tilstander: suspendert → kjører ↔ normal → død
  • coroutine.status(co) returnerer tilstandsstrengen
  • Død = avsluttet eller har fått en feil; kan ikke gjenopptas
  • coroutine.isyieldable() kontrollerer om den gjeldende konteksten kan utføre yield
  • Kontroller alltid status før De gjenopptar i løkker
  • wrap-feil forplanter seg direkte; resume returnerer false+err
Gratis å komme i gang

Lær deg Lua med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
40
Leksjoner
159

Ofte stilte spørsmål

Er leksjonen «Coroutine-status» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Lua Academy, inkludert «Coroutine-status», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Lua Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Coroutine-status»?

Kontroller coroutine-ens tilstand med coroutine.status: running, suspended, dead. Du øver på Lua Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Lua Academy?

Ingen tidligere erfaring er nødvendig. Lua Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Coroutine-status»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Lua Academy-leksjonen?

Ja. Alle Lua Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Opprette coroutine-er
  2. resume og yield
  3. Coroutine-status
  4. Produsent–konsument-mønsteret
← Tilbake til Lua Academy