0Pricing
Lua Academy · Lezione

Stato delle coroutine

Verifichi lo stato di una coroutine con coroutine.status: running, suspended, dead.

Stato delle coroutine è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.

I quattro stati delle coroutine

Le coroutine possono trovarsi in quattro stati: sospesa (creata o sospesa con yield, in attesa di essere eseguita), in esecuzione (in esecuzione in quel momento), normale (in pausa per consentire l'esecuzione di un'altra coroutine) e terminata (conclusa o terminata a causa di un errore). Interroghi lo stato con 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

Lo stato «normale»

Una coroutine entra nello stato «normale» quando riprende un'altra coroutine. Non è in esecuzione, perché lo è l'altra coroutine, ma non è neppure sospesa: attende che la coroutine ripresa esegua yield. Questo stato è raro, ma è importante comprenderlo quando si lavora con grafi di coroutine complessi.

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

Controllo prima di resume

Controlli sempre lo stato di una coroutine prima di riprenderla, soprattutto nei cicli. Riprendere una coroutine terminata genera un errore. Anche riprendere una coroutine già in esecuzione genera un errore, perché causerebbe una ricorsione infinita.

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

Stato dopo un errore

Quando il corpo di una coroutine genera un errore non gestito, coroutine.resume restituisce false e il messaggio di errore. La coroutine passa allo stato «terminata». Non può essere riavviata: se desidera riprovare, deve creare una nuova coroutine.

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() restituisce true se la coroutine in esecuzione può eseguire yield. Restituisce false nel thread principale e nelle funzioni C che non supportano la sospensione. Se non è sicuro del contesto, controlli sempre prima di eseguire yield.

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

Monitoraggio di un insieme di coroutine

Monitori un pool di coroutine, rimuovendo quelle terminate dopo ogni ciclo di chiamate a resume. Questa è la base di uno scheduler di attività.

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

Debug delle coroutine

Utilizzi i controlli dello stato per strumentare ed eseguire il debug del codice basato sulle coroutine. Stampi le transizioni di stato per comprendere il flusso. Nei sistemi complessi, assegni nomi alle coroutine tramite una tabella wrapper per ottenere un output di debug più chiaro.

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

Riavvio delle coroutine terminate

Una volta terminata, una coroutine non può essere ripresa. Per «riavviarla», deve creare una nuova coroutine a partire dalla stessa funzione. Un modello comune consiste nell'utilizzare una factory che crei una nuova coroutine quando necessario.

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

Comportamento degli errori di coroutine.wrap

Quando una coroutine avvolta genera un errore, l'errore si propaga all'esterno della chiamata alla funzione wrapper. A differenza di coroutine.resume, che restituisce false+errore, le funzioni restituite da wrap generano direttamente l'errore. Utilizzi pcall attorno alle chiamate a wrap se deve intercettare gli errori.

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 e status a confronto

Esistono due modi per esaminare il contesto di una coroutine: coroutine.status(co) restituisce lo stato di una coroutine specifica; coroutine.isyieldable() indica se il contesto di esecuzione corrente può eseguire yield. Utilizzi status per controllare altre coroutine e isyieldable per verificare se è possibile eseguire yield in sicurezza.

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

Verifica rapida

In quale stato entra una coroutine quando termina l'esecuzione della propria funzione corpo?

Riepilogo: stato delle coroutine

Riepilogo:

  • Stati: sospesa → in esecuzione ↔ normale → terminata
  • coroutine.status(co) restituisce la stringa che indica lo stato
  • Terminata = conclusa o terminata a causa di un errore; non può essere ripresa
  • coroutine.isyieldable() verifica se il contesto corrente può eseguire yield
  • Controlli sempre lo stato prima di riprendere una coroutine nei cicli
  • Gli errori di wrap si propagano direttamente; resume restituisce false+err

Domande Frequenti

La lezione «Stato delle coroutine» è gratuita?

Sì — il testo completo di «Stato delle coroutine» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.

Cosa imparerò in «Stato delle coroutine»?

Verifichi lo stato di una coroutine con coroutine.status: running, suspended, dead. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Lua Academy?

Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Stato delle coroutine»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Lua Academy?

Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Creazione delle coroutine
  2. resume e yield
  3. Stato delle coroutine
  4. Pattern produttore-consumatore
← Torna a Lua Academy