0Pricing
Lua Academy · Lección

Estado de las coroutines

Compruebe el estado de una coroutine con coroutine.status: running, suspended, dead.

Estado de las coroutines es una lección gratuita de Lua Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Lua Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Lua Academy incluye 4 lecciones en total.

Los cuatro estados de una corrutina

Las corrutinas tienen cuatro estados posibles: suspendida (creada o detenida mediante yield, a la espera de ejecutarse), en ejecución (se está ejecutando), normal (pausada para permitir que se ejecute otra corrutina) y muerta (ha terminado o se ha producido un error). Consulte el estado 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

El estado «normal»

Una corrutina entra en el estado «normal» cuando reanuda otra corrutina. No está en ejecución (la otra corrutina lo está), pero tampoco está suspendida: espera a que la corrutina reanudada produzca un yield. Este estado es poco frecuente, pero es importante comprenderlo en grafos complejos de corrutinas.

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

Comprobar antes de reanudar

Compruebe siempre el estado de una corrutina antes de reanudarla, especialmente en bucles. Reanudar una corrutina muerta es un error. Reanudar una corrutina que ya está en ejecución también es un error (provocaría una recursión 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

Estado después de un error

Cuando el cuerpo de una corrutina produce un error no capturado, coroutine.resume devuelve false y el mensaje de error. La corrutina pasa al estado «muerta». No se puede reiniciar; si desea volver a intentarlo, debe crear una corrutina nueva.

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() devuelve true si la corrutina en ejecución puede producir un yield. Devuelve false en el hilo principal y en las funciones de C que no admiten yield. Si no está seguro del contexto, compruébelo siempre antes de producir un 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

Supervisar un conjunto de corrutinas

Realice el seguimiento de un pool de corrutinas y elimine las que estén muertas después de cada ronda de reanudaciones. Esta es la base de un planificador de tareas.

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

Depuración de corrutinas

Use comprobaciones de estado para instrumentar y depurar código basado en corrutinas. Imprima las transiciones de estado para comprender el flujo. En sistemas complejos, asigne nombres a las corrutinas mediante una tabla envolvente para obtener una salida de depuración más clara.

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

Reiniciar corrutinas muertas

Una vez muerta, una corrutina no se puede reanudar. Para «reiniciarla», debe crear una corrutina nueva a partir de la misma función. Un patrón habitual consiste en usar una factory que cree una corrutina nueva cuando sea necesario.

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

Comportamiento de los errores de coroutine.wrap

Cuando una corrutina envuelta produce un error, este se propaga fuera de la llamada a la función envolvente. A diferencia de coroutine.resume, que devuelve false+error, las funciones devueltas por wrap producen el error directamente. Use pcall alrededor de las llamadas a wrap si necesita capturar los errores.

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 frente a status

Hay dos formas de consultar el contexto de una corrutina: coroutine.status(co) proporciona el estado de una corrutina específica; coroutine.isyieldable() indica si el contexto de ejecución actual puede producir un yield. Use status para comprobar otras corrutinas e isyieldable para comprobar si puede producir un yield de forma segura.

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

Comprobación rápida

¿A qué estado pasa una corrutina cuando termina de ejecutar su función de cuerpo?

Resumen: estado de las corrutinas

Resumen:

  • Estados: suspendida → en ejecución ↔ normal → muerta
  • coroutine.status(co) devuelve la cadena correspondiente al estado
  • Muerta = ha terminado o se ha producido un error; no se puede reanudar
  • coroutine.isyieldable() comprueba si el contexto actual puede producir un yield
  • Compruebe siempre el estado antes de reanudar en bucles
  • Los errores de wrap se propagan directamente; resume devuelve false+err

Preguntas frecuentes

¿La lección «Estado de las coroutines» es gratis?

Sí — el texto completo de «Estado de las coroutines» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Lua Academy, actualiza a CoddyKit PRO. El curso de Lua Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Estado de las coroutines»?

Compruebe el estado de una coroutine con coroutine.status: running, suspended, dead. Practicas Lua Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Lua Academy?

No se requiere experiencia previa. Lua Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Estado de las coroutines»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Lua Academy?

Sí. Cada lección de Lua Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Creación de coroutines
  2. resume y yield
  3. Estado de las coroutines
  4. Patrón productor-consumidor
← Volver a Lua Academy