viernes, 16 de septiembre de 2011

Corutinas en Lua [Parte 2]

En el anterior post escribí una corutina creada con la función "coroutine.wrap()". Ahora toca hacerlo con "coroutine.create()":

function Print(valor1, valor2)
  while true do
    valor1, valor2 = coroutine.yield(valor1, valor2);
  end
end

PrintCo = coroutine.create(Print);
print(PrintCo);-->thread 0xXXXXXX
local a, b, c = coroutine.resume(PrintCo,"Hola", "mundo!")
print(a, b, c);-->true, Hola, mundo!
a, b, c = coroutine.resume(PrintCo,"Cómo", "estas?!");
print(a, b, c);-->true, Cómo, estas?!

Así es como se vería el mismo código pero creado con la función "coroutine.create()", la cual retorna un tipo definido como "thread". Para resumir una corutina creada con éste método debemos usar la función "coroutine.resume()", la cual retornará un valor booleano en el primer argumento y en el resto de los argumentos los valores que la función de la corutina regrese.

La principal diferencia de crearla así (en lugar de hacerlo con coroutine.wrap) es que podemos obtener el estado de ejecución de la misma (suspended, normal, dead) y además podemos manejar los errores sin propagarlos al invocador (con wrap el error se propaga directo al invocador).

Es importante volver a mencionar que todo lo que se escriba dentro del paréntesis de "coroutine.yield()" es lo que se retornará (ó en su defecto un simple return que finalizaría la corutina) al invocador de "coroutine.resume()" o a la función creada con wrap. El contenido del paréntesis no indican los nuevos valores a recibir/evaluar, así que podemos tenerlo vacío y aún así seguir recibiendo valores dentro de la corutina:


function Print(valor1, valor2)
  while true do
    print(valor1, valor2);
    valor1, valor2 = coroutine.yield();
  end
end

PrintCo = coroutine.create(Print);
print(PrintCo);-->thread 0xXXXXXX
local a = coroutine.resume(PrintCo,"Hola", "mundo!")
---->Hola, mundo!
print(a);-->true
a= coroutine.resume(PrintCo,"Cómo", "estas?!");
---->Cómo, estas?!
print(a);-->true

Todo esto es algo que, como ya mencioné en la publicación anterior, no esta muy bien documentado en los manuales de lua.

Ahora bien, la principal cualidad de una corutina es la de poder controlar varias corutinas desde 1 principal (resumiendo otras, pausando, etc.) logrando lo que se llama "multitasking" (multitareas) y no una función tan simple como la expuesta en los ejemplos. Pero, la finalidad de estos ejemplos es explicar de forma más detallada el uso básico de las corutinas.

NOTA: Todas éstas funciones pueden ser probadas para verificarlas en el demo online que ofrece el sitio de lua.org (http://www.lua.org/cgi-bin/demo).

No hay comentarios:

Publicar un comentario