Practico 6 - Ejercicio 6

Practico 6 - Ejercicio 6

de Diego Kiedanski Estrugo -
Número de respuestas: 8

Funciona? Se aceptan criticas, sugerencias y comentarios


EJERCICIO 6:


PROGRAM EMBOTELLADORA


TASK Cinta IS

    ENTRY Llenado;

    ENTRY Tapado;

END Cinta


TASK BODY Cinta IS

begin

while(true){

    ACCEPT Llenado;

    ACCEPT Tapado;

    avanzo_cinta();

    Tapar.Puedo();

    Llenar.Puedo(); // Esto no se si esta bien, de alguna forma es secuencial pero no se me ocurre como hacer para que TASK Cinta avise a los otros dos de forma concurrente.

}

end

END Cinta


TASK Tapar IS

    ENTRY Puedo;

END Tapar


TASK BODY Tapar IS

begin

while(true){

    if(puedo_tapar)

        tapar_botella;

    cinta.Tapado();

    ACCEPT Puedo;

}

end

END Tapar



TASK Llenar IS

    ENTRY Puedo;

END Llenar


TASK BODY Llenar IS

begin

while(true){

    if(puedo_llenar)

        llenar_botella;

    cinta.Llenado();

    ACCEPT Puedo;

}

end

END Llenar


BEGIN


/* cosas o while(true) */


END


Desde ya, muchas gracias

En respuesta a Diego Kiedanski Estrugo

Re: Practico 6 - Ejercicio 6

de Jorge Merlino -

Esto funciona, pero si quisieras que se despierten los dos a la vez lo que podrías hacer es hacer un accept adentro de otro. Tampoco precisas dos entradas diferentes, así que suponiendo que tenés una sola que se llama fin podés hacer en la cinta:

accept fin do
   accept fin do
       avanzo_cinta()
   end fin
end fin

Y las dos máquinas solamente llamarían a la entrada fin cuando terminan de trabajar.

Otra cosa es que no precisas un while true en el programa principal, un programa de Ada no termina mientras haya tasks corriendo. Podría quedar vacío y podrías no ponerlo si este es el caso.

En respuesta a Diego Kiedanski Estrugo

Re: Practico 6 - Ejercicio 6

de Sebastian Daloia Servetti -

Comparto una versión con un enfoque diferente a la solución(del 2015) presentada en este tópico, la idea es que existen tres tareas tapar, llenar, avanzar con una estructura similar, lo único que cambia en ellas son las  guardas de la selección, que les parece?


TASK tapar IS
  ENTRY tapar();
END tapar;
TASK BODY tapar IS
  LOOP
    SELECT

     WHEN puedo_tapar = >
       ACCEPT tapar() DO
        pongo_tapa;
       END
    ELSE
  END LOOP
END
tapar;

TASK llenar IS
  ENTRY llenar();
END llenar;
TASK BODY llenar IS
  LOOP
    SELECT
    WHEN
puedo_llenar = >
       ACCEPT llenar() DO
         llenar_botella;
       END
    ELSE
  END LOOP
END
llenar;


TASK avanzar IS
  ENTRY avanzar_cinta();
END avanzar;
TASK BODY avanzar IS
  LOOP
    SELECT

     WHEN NOT puedo_llenar AND NOT puedo_tapar = >
       ACCEPT avanzar_cinta() DO
         avanzar_cinta;
       END
    ELSE
  END LOOP

END llenar;


En respuesta a Sebastian Daloia Servetti

Re: Practico 6 - Ejercicio 6

de Gustavo Brown -

Sebastián,

  La solución que planteas no es correcta. Tiene busy waiting en todas las tareas, y además deja de avanzar la cinta en cuanto pueda llenar o pueda tapar (esas funciones retornan 'true' si la botella está abajo de la tapadora o llenadora independientemente de si ya tapó y/o llenó).

Saludos,
  Gustavo

En respuesta a Gustavo Brown

Re: Practico 6 - Ejercicio 6

de Sebastian Daloia Servetti -

Correcto en las observaciones, gracias!

Lo que me animé a proponer luego de esto fue lo siguiente, mas semejante a la solución dada en el primer mensaje del tópico:

TASK llenado IS
  ENTRY rutina_llenado();
END llenado;
TASK BODY llenado IS
  LOOP
    ACCEPT
rutina_llenado;
     IF puedo_llenar
     THEN
       llenar_botella;
     END IF
     cinta.mover();
  END LOOP
END
llenado;

TASK tapado IS
  ENTRY rutina_tapado();
END tapado;
TASK BODY tapado IS
  LOOP
    ACCEPT rutina_tapado;
    IF puedo_tapar
    THEN
      pongo_tapa;
    END IF
    cinta.mover();
  END LOOP
END tapado;


TASK cinta IS
  ENTRY mover();
END cinta;
TASK BODY cinta IS
  tapado.rutina_tapado();
  llenado.rutina_llenado();
  LOOP
    ACCEPT
mover() DO
       ACCEPT mover() DO
         avanzo_cinta;
         tapado.rutina_tapado();
         llenado.rutina_llenado();
       END
    END
  END LOOP
END
cinta;

En respuesta a Sebastian Daloia Servetti

Re: Practico 6 - Ejercicio 6

de Gustavo Brown -

Estas complicando la solución. Y quedás en deadlock. Al poner los ACCEPT de mover() anidados estás dejando trancados en dichos encuentros a las tareas TAPADO y LLENADO, por lo que cuando pones el pedido a RUTINA_TAPADO() ya se queda todo en deadlock.

Saludos,
  Gustavo

En respuesta a Sebastian Daloia Servetti

Re: Practico 6 - Ejercicio 6

de Marco Nicolas Rodriguez Alvariza -

Hola Sebastian y Gustavo.

Creo que la solución que sugería Jorge en 2015 es la siguiente:

Program AlgarroboCola

Task Cinta is

    Entry avanzar();

End Cinta

Task Body Cinta is

Begin

    Loop

        Accept avanzar() do

            Accept avanzar() do

                avanzar_cinta();

            End avanzar

        End avanzar

    End Loop

End Cinta

Task Tapadora;

Task Body Tapadora is

Begin

    Loop

        If (puedo_tapar())

            pongo_tapa();

        End If

        Cinta.avanzar();

    End Loop

End Tapadora

La tarea 'Llenadora' en similar a la 'Tapadora' y el cuerpo del programa principal es vacío.

La idea es que el primero que llame a Cinta.avanzar() queda bloqueado (junto con la tarea Cinta) en el segundo Accept, hasta que la otra tarea solicite Cinta.avanzar(), luego de lo cual se desbloquean todos, la cinta avanza y continua la ejecución.