Saludos,
Andrés.
Buen día Andrés,
Estuve viendo la solución de la parte a, y me parece que se te presenta el siguiente problema, se hace P(com_llenar), pero nunca se hace el V(com_llenar), entonces me parece que se va poder llenar solo una botella porque en el prox ciclo el semaforo va a estar en 0, y la máquina va quedar bloqueada. Lo mismo para com_tapar.
Por otro lado, el avanzar cinta se invoca una sola vez, por lo que la cinta se desplaza una sola vez, eventualmente podría no llenarse ninguna botella. Capaz que el avanzar hace un bucle con avanzo_cinta.
Con respecto a la parte a, creo que hay que pensarlo algo parecido al problema del productor-consumidor, donde el productor es la máquina de llenar y el consumidor la maquina de tapar.
la solución que se me ocurrió es esta:
- una variable global que cuente las botellas que están llenas, cant_botellas_llenas
- un semáforo binario, para la modificación de la variable anterior
- un semáforo genérico que se libera cuando se llena una botella, (incrementando en 1, la cantidad de procesos que van a poder antender)
- como la cinta avanza a pasos pequeños, asumir que no es necesario hacer un stop de la cinta para llenar y/o tapar la cinta
Program algarroba_coca();
var
mutex: semaforo; (* semaforo binario *)
s_botella_llena: semaforo;
procedure llenar_botella()
begin
while(true)do
begin
if (puedo_llenar) then
begin
llenar_botella();
P(mutex);
cant_botellas_llenas:= cant_botellas_llenas+1;
V(mutex);
V(s_botella_llena); (* libera el semaforo (incrementando la cant de procesos que van a poder hacer el P) para que el P(s_botella_llena) siga de largo del proceso de tapar*)
end; (* if *)
end; (* while *)
end;
procedure tapar_botella()
var puedo_tapar: boolean;
begin
while(true) do
begin
puedo_tapar:=false;
P(s_botella_llena);
P(mutex);
if (cant_botellas_llenas > 0) then
begin
puedo_tapar:=true;
end;
V(mutex);
(* no importa si la variable se modifica mientras se tapa la botella, ya que importa que la cantidad sea mayor a 0 y el llenado solo incrementa*)
if (puedo_tapar) then
begin
tapar_botella();
P(mutex); (* se ejecuta dos veces el mutex , para que el llenado pueda incrementar la variable mientras la máquina está tapando*)
cant_botellas_llenas := cant_botellas_llenas - 1;
V(mutex);
end;
end; (* del while *)
end;
(* la cinta como avanza a pasos muy chicos se asume que no es necesario hacer un stop de la cinta al llenar y/o tapar la botella *)
procedure avanzar()
begin
while(true)do
avanzar_cinta();
end;
begin
init(mutex, 1); (* el primero que va hacer el P es el llenado *)
init(s_botella_llena, 0); (* de entrada bloquea al tapar botellas *)
cant_botellas_llenas := 0;
cobegin
tapar_botella();llenar_botella();avanzar();
coend;
end;
Al igual que vos, no estoy seguro si esta es una solución correcta, ni si es la más óptima, jeje,
Saludos
Pablo Gonzalez.
procedure avanzar(){
P(s)
P(s)
avanzo();
V(com_tapar);
V(com_llenar);
}
La idea es que luego de avanzar la cinta el procedimiento avanzar() habilite a poder tapar y llenar otras botellas, haciendo V(com_tapar) y V(com_llenar).
El tema de que el avanzar se ejecuta una vez tenes razon, deberia poner todo lo que esta en cobegin coend dentro de un loop infino.
Con respecto a tu solución:
(* la cinta como avanza a pasos muy chicos se asume que no es necesario hacer un stop de la cinta al llenar y/o tapar la botella *)
procedure avanzar()
begin
while(true)do
avanzar_cinta();
end;
Haciendo simplemente avanzar_cinta() no estas esperando que la bottela se llene/tape, si le sacas el cpu a mientras se esta llenando y se lo da a avanzar() podrias avanzar sin nada que te tranque, me explico?, para mi tenes que implementar algo de que antes de avanzar se fije si lleno o tapo.