Buscar..


Sintaxis

  • coroutine.create (function) devuelve una coroutine (type (coroutine) == 'thread') que contiene la función.

  • coroutine.resume (co, ...) reanudar, o iniciar la coroutine. Cualquier argumento adicional dado para reanudar se devuelve desde coroutine.yield () que previamente pausó la coroutine. Si no se ha iniciado la rutina, los argumentos adicionales se convierten en los argumentos de la función.

  • coroutine.yield (...) produce la coroutine actualmente en ejecución. La ejecución se recupera después de la llamada a coroutine.resume () que inició esa coroutine. Cualquier argumento dado para ceder se devuelve del coroutine.resume () correspondiente que inició la coroutine.

  • coroutine.status (co) devuelve el estado de la coroutine, que puede ser:

    • "muerto": la función en la coroutine ha llegado a su fin y la coroutine ya no se puede reanudar.
    • "running": el coroutine se ha reanudado y se está ejecutando
    • "normal": la coroutine ha reanudado otra coroutine.
    • "suspendido": la corutina ha cedido, y está esperando para ser reanudada
  • coroutine.wrap (función) devuelve una función que, cuando se le llama, reanuda la coroutina que habría sido creada por coroutine.create (función).

Observaciones

El sistema coroutine ha sido implementado en lua para emular multiproceso existente en otros idiomas. Funciona cambiando a una velocidad extremadamente alta entre diferentes funciones para que el usuario humano piense que se ejecutan al mismo tiempo.

Crea y utiliza una coroutina.

Todas las funciones para interactuar con coroutines están disponibles en la tabla de coroutine . Se crea una nueva coroutine usando la función coroutine.create con un solo argumento: una función con el código a ejecutar:

thread1 = coroutine.create(function()
            print("honk")
        end)

print(thread1)
-->> thread: 6b028b8c

Un objeto de coroutine devuelve el valor del tipo thread , que representa una nueva coroutine. Cuando se crea una nueva coroutine, su estado inicial se suspende:

print(coroutine.status(thread1))
-->> suspended

Para reanudar o iniciar una rutina, se utiliza la función coroutine.resume , el primer argumento dado es el objeto de hilo:

coroutine.resume(thread1)
-->> honk

Ahora el coroutine ejecuta el código y termina, cambiando su estado a muerto , que no se puede reanudar.

print(coroutine.status(thread1))
-->> dead

Coroutines puede suspender su ejecución y reanudarla más tarde gracias a la función coroutine.yield :

thread2 = coroutine.create(function()
        for n = 1, 5 do
            print("honk "..n)
            coroutine.yield()
        end
    end)

Como puede ver, coroutine.yield () está presente dentro del bucle for, ahora, cuando reanudamos la coroutine, ejecutará el código hasta que alcance un coroutine.yield:

coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2

Después de terminar el bucle, el estado del hilo se convierte en muerto y no se puede reanudar. Coroutines también permite el intercambio entre datos:

thread3 = coroutine.create(function(complement)
    print("honk "..complement)
    coroutine.yield()
    print("honk again "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow

Si la rutina se ejecuta de nuevo sin argumentos adicionales, el complemento seguirá siendo el argumento de la primera reanudación, en este caso "stackoverflow":

coroutine.resume(thread3)
-->> honk again stackoverflow

Finalmente, cuando finaliza una rutina, cualquier valor devuelto por su función va al currículum correspondiente:

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

En esta función, se utilizan Coroutines para devolver los valores a un hilo de llamada desde lo profundo de una llamada recursiva.

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 también se puede utilizar para la evaluación perezosa.

-- 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 se puede usar para construcciones de tuberías como se describe en Programming In Lua . El autor de PiL, Roberto Ierusalimschy, también ha publicado un artículo sobre el uso de las coroutinas para implementar mecanismos de control de flujo más avanzados y generales, como las continuaciones.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow