Anuncios Google

[LuaDEV] Corrutinas

Hola a todos, necesito que algún coder me explique bien como se usan las corrutinas y la multitarea por procesos (threadman)

 

Saludos y gracias!


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de DeViaNTe

corutinas

Las corutinas son simplemente funciones, "pero", que se puede salir y entrar de ellas en cualquier punto, no sólo al final con un return. Además, tienen control de errores, por lo que si fallan, no da error en lua, simplemente la corutina muere.

Realmente no seria multiproceso, pq no podemos lanzarla y imaginarnos que va sola y en paralelo con otra funcion, si no que tenemos que "re-lanzarla" cada vez.

Es decir, nos proporciona las herramientas para que nosotros nos hagamos nuestro propio planificador.

Para poner un ejemplo medio sencillo, vamos a hacer un modulo de audio para nuestro juego, como los de juegos tipo burnout y demas, donde el reproductor esta activo pero no afecta al juego.

Primero tendriamos que crear el sistema de audio, como si éste fueran funciones normales lua.

function audiomanager ( ... )
   -- Aqui inicializamos algunas cosas que sólo
   -- seran necesarias ejecutarlas una vez.
   local input = { ... };
   local output = { };
   local currentsong = nil;
   local currentindex = 1;
 
   local audiofiles = {
      "snd/bla.mp3",
      "snd/ble.mp3",
      "snd/bli.mp3"
   };
 
   -- A partir de aqui es lo que se ejecutará a cada ciclo.
   while true do
      -- if no song, load and play.
      if ( currentsong == nil ) then
         currentsong = sound.load(audiofiles[currentindex]);
         currentsong:play(5); -- canal 5.
      end
 
      -- if finished, next song.
      if ( currentsong:percent() > 98 ) then
          currentindex = currentindex + 1;
          currentsong:stop();
          currentsong:free();
          currentsong = nil;
      end
 
     -- if player wants next song.
     if ( controls.released("r") ) then
         currentindex = currentindex + 1;
         currentsong:stop();
         currentsong:free();
         currentsong = nil;
     end
 
     -- controlar rango de currentindex.
     if ( currentindex > #audiofiles ) then
        currentindex = 0;
     end
     if ( currentindex < 1 ) then
        currentindex = #audiofiles;
     end
 
     -- salir de la corutina ( y volver a entrar luego por aqui ).
      input = { coroutine.yield(output) };
   end
 
 
end
 

Con esto, tenemos una funcion que simplemente llamandola una vez atascaría el programa, debido a el bucle, pero si lo convertimos en corutina, ese bucle se ejecutará una vez por llamada a la corutina, por que tiene el punto de interrupcion dentro del while.

Ahora, imaginamos que el juego ya lo tenemos hecho y no queremos tocar nada, y queremos que se implemente solito... Todo bien

Dado que en lua podemos redirigir funciones y machacarlas, borrarlas o lo que sea ( cosa no recomendable xD ), si bien podemos aprovecharnos de este comportamiento con un poco de eficacia:

-- nos guardamos el screen flip.
old_screen_flip = screen.flip;
corutina_audiomanager = nil;
 
-- machacamos un nuevo screen.flip para añadir funciones
-- que vayamos a ejecutar a cada ciclo, y no queremos tocar
-- el resto del programa...
function screen.flip( )
   -- si no hay corutina, crearla.
   if (corutina_audiomanager == nil) then
     corutina_audiomanager = coroutine.create(audiomanager);
   end
 
   -- vigilar si no esta muerta.
   if ( coroutine.status(corutina_audiomanager) == "dead" ) then
       -- hay algun error, y murió, la borraremos para que vuelva
       -- a nacer en el proximo screen.flip.
       corutina_audiomanager = nil;
   else
      -- la corutina sigue viva, pero a la espera, o sin primera ejecucion
      coroutine.resume(corutina_audiomanager);
   end
 
 
   -- por ultimo, hacemos el viejo screen flip
   old_screen_flip();
end

Añadiendo esto al inicio del todo de nuestra app / juego, tendriamos audiomanager sin haber tocado el resto del programa.

Las corutinas no sirven bien bien para esto, pero es tan solo para poneros un ejemplo de como se usa.

Si me preguntais que son los tres puntos ..., son parametros de entrada,  que no se cuantos seran, los guardo en inputs (tabla), asi input[0] sera el primer parametro, input[1] el segundo, #input el numero de argumentos. (vararg power).
output son los resultados que se devolverian en un coroutine.resume, pero en este caso desde fuera, en el screen.flip no paso argumentos ni recibo, por lo que no me preocupan, pero si requiriese de entrada y salida de datos usaria esas variables.

Espero se entienda un poco, y si no, al manual oficial de lua ;).

Un saludo. 


Actualmente desarrollando nuestra web y UXCode : http://www.gcrew.es

Jefe esto no es C xD"input[0]

Jefe esto no es C xD
"input[0] sera el primer parametro, input[1] el segundo" quieres decir "input[1] sera el primer parametro, input[2] el segundo" 

Imagen de DeViaNTe

... xD

os estaba poniendo a prueba ;) xDDDDDDDDDD

Imagen de NEKERAFA

XD

Imagen de zerozelta

:o... significa que si es

:o... significa que si es humano y no una maquina de programacion XD

Jajajajajajjaja +1

xDDD No me hagas reir que casi escupo la computadora de gaseosa xDDDDD

Que buen off-topic xD

 

Saludos!!

Imagen de zerozelta

Segun tengo entendido, el

Segun tengo entendido, el modulo no esta terminado y no es funcional del todo, pero se puede simular el uso de threads en un solo hilo usando un modulo improvisado que hace la funcion de threader

Thread = {}	-- Se crea la tabla del modulo hilo
 
-- Se crea un nuevo hilo que contiene la funcion "func"
function Thread.new(id,func)
	local thr = {	-- Creamos un nuevo objeto thread
		id = id,
		type = "Thread",
		data = {},
	}
 
	table.insert(thr.data,func)	-- Insertamos la nueva funcion al hilo
 
	return thr
end
 
-- Añade un hilo a otro hilo
function Thread.add(thr_fat,thr_son)
	table.insert(thr_fat.data,thr_son)
end
 
-- Corre todos los hilos del objeto Thread pasado como argumento
function Thread.run(thr)
	for i = 1,#thr.data do
		local t = thr.data[i]
		if type(t) == "function" then
			t()	-- Corremos la funcion del thread
		elseif type(t) == "Table" and t.type == "Thread" then
			Thread.run(t) 	-- Ejecutamos todos los hilos dentro del hilo principal
end
	end	
end

No es necesario hacer tanto codigo para hacer qeu tu programa tenga multi proceso, pero si buscas un mayor control de los hilos esto te va a servir, aunqeu le faltan algunas funciones que no me dieron tiempo de llenar como estas:

function Thread.get(id)
 
end
 
function Thread.kill(id)
 
end
 
function Thread.stop(id)
 
end
 
function Thread.clone(id)
 
end

Entre otros, espero qeu te sirva de ayuda :)

Saludos¡¡


Imagen de NEKERAFA

LOL

Y yo hice una cosa supercomplicada que va a medias y me tira errores XD. Si no te importa me voy a basar en la tuya, que me gustó mucho la forma de como lo haces en Fishell.

Saludos ^-^.


NekeOS, el nuevo shell para PSP

PS4 500GB OFW, PS3 320GB OFW, PS3 500GB OFW, PSP 6.39 PRO-C Fix4.

Sony Xperia Z1 Compact con Android 5.1.1

Portatil Lenovo z50-70 Intel® Core™ i7-4510U y NVIDIA GeForce 840M con Elementary OS 0.3.2 Freya (64 bits) y Windows 10 (64 bits).

Bien

Bien, ya entiendo como funciona la multitarea por procesos, pero sigo sin entender del todo lo de las corrutinas, por ahora, esto es todo lo que visto que las use:

Generador de números primos en Lua:

function gen (n)
return coroutine.wrap(function ()
for i=2,n do coroutine.yield(i) end
end)
end
 
 
function filter (p, g)
return coroutine.wrap(function ()
while 1 do
local n = g()
if n == nil then return end
if math.mod(n, p) ~= 0 then coroutine.yield(n) end
end
end)
end
 
N=N or 1000
x = gen(N)
while 1 do
local n = x()
if n == nil then break end
print(n)
x = filter(n, x)
end

 

Saludos!

Imagen de zerozelta

toma las corrutinas como si

toma las corrutinas como si fuesen callbacks, te sirve para hacer 2 procesos al mismo tiempo, su uso es algo mas complicado y debido a que esta incompleto no me he dado tiempo de entender bien su uso, pero lo que si se es que puedes hacer practicamente lo mismo con las corrutinas que con el metodo que te presente antes.

para que piensas usar las corrutinas si se puede saber? (para ver si podrias usar metodos mas faciles y practicos)


Pues...

Quería saber usarlas por lo siguiente:

  1. Por curiosidad
  2. Para ver cual es el mejor método para hacer multitarea, y el que es compatible con cualquier plataforma que tenga intérprete Lua
  3. Porqué igual en un futuro pueda acabar usandolas...

Saludos!

Imagen de zerozelta

aaa ok, es muy bueno querer

aaa ok, es muy bueno querer aprender cosas diferentes, pero me referia a para que proyecto la necesitas hacer? (un explorador de archivos, shell, juego?)

puede que haya algun otro metodo que te sirva mas que la corrutina y que podrias preferir usar mas


Bueno, por ahora

Bueno, por ahora no creo que las use con mis primeros aportes, en concreto, este ha sido mi primer aporte y ahora mismo estoy programando un reproductor de Mp3 con visualizaciones, listas de reproducción, funciones como ahorro energía y cosas así. Por ahora lo tengo en fase Alpha y aún no funciona muy bien, no creo, sinceramente, que llegue a usar las corrutinas en este projecto, pero quizás en otros sí, ya que no será mi último aporte.

 

Saludos!

Imagen de NEKERAFA

Mmm...

Ahora que me acuerdo, ¿habeis mirado la documentación oficial de Lua? A lo mejor os resuelve vuestras dudas (Y las mias): http://www.lua.org/manual/5.1/es/manual.html#2.11

Ah!, y acordaros de este tutorial: http://psp.scenebeta.com/tutorial/multitarea-en-lua


NekeOS, el nuevo shell para PSP

PS4 500GB OFW, PS3 320GB OFW, PS3 500GB OFW, PSP 6.39 PRO-C Fix4.

Sony Xperia Z1 Compact con Android 5.1.1

Portatil Lenovo z50-70 Intel® Core™ i7-4510U y NVIDIA GeForce 840M con Elementary OS 0.3.2 Freya (64 bits) y Windows 10 (64 bits).

Sinceramente

Sinceramente, me he leido esa documentación por lo menos 10 veces, y una de las pocas cosas que no me ha quedado clara son las corrutinas...

 

Saludos!

Imagen de NEKERAFA

Mmm

Pues entonces mira el tutorial, que creo que si lo explican muy bien.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.