Practico 5 - ejercicio 7

Practico 5 - ejercicio 7

de Nicolas Nocetti Lago -
Número de respuestas: 2

Hola, se me ocurrio esta solución para este ejercicio y quisiera saber si tiene errores. Gracias


Program ejercicio_7

var cont_autos: integer
var cont_barcos: integer
var puente_inactivo: bool
var mutex_auto: semaforo
var mutex_barco: semaforo
var puente_vacio: semaforo
var bloqueo_barcos: semaforo
var bloqueo_autos: semaforo
var auto_entrada: semaforo
var auto_salida: semaforo
var barco_entrada: semaforo
var barco_salida: semaforo

Procedure auto
begin
    loop
        P(mutex_auto)
        cont_autos:=cont_autos+1;
        if cont_barcos <> 0 then P(bloqueo_autos) end if
        V(mutex_auto)
        if puente_inactivo then V(puente_vacio) end if
        P(auto_entrada)
        delay(X)
        V(auto_salida)
        anda_por_ahi()
    end loop
end

Procedure barco
begin
    loop
        P(mutex_barco)
        cont_barcos:=cont_barcos+1;
        if cont_barcos = 1 then P(bloqueo_barcos);
        V(mutex_barco)
        if puente_inactivo then V(puente_vacio) end if
        P(barco_entrada)
        delay(X)
        V(barco_salida)
        navega_por_ahi()
    end loop
end

Procedure puente
var puente_bajo: bool
begin
    puente_bajo:=true
    loop
        if puente_inactivo then
            P(puente_vacio)
            puente_inactivo:=false
        end if
        if puente_bajo then
            if cont_barcos <> 0 and cont_autos = 0 then
                puente_bajo:=false
                levantar_puente()
                V(bloqueo_barcos)
            else
                P(auto_salida)
                P(mutex_auto)
                cont_autos:=cont_autos-1;
                V(mutex_auto)
                V(auto_entrada)
            end if
        else
            P(barco_salida)
            P(mutex_barco)
            cont_barcos:=cont_barcos-1;
            if cont_barcos = 0 then
                puente_bajo:=true
                bajar_puente()
                V(bloqueo_autos)
            end if
            V(mutex_barco)
            V(barco_entrada)
        end if
        if cont_autos=0 and cont_barcos=0 then puente_inactivo=true end if
    end loop
end

begin
    cont_autos:=0;
    cont_barcos:=0;
    puente_inactivo=true;
    init(mutex_auto, 1)
    init(mutex_barco, 1)
    init(puente_vacio, 0)
    init(bloqueo_barcos, 0)
    init(bloqueo_autos, 0)
    init(auto_entrada, MAX_AUTOS_PUENTE)
    init(auto_salida, 0)
    init(barco_entrada, 1)
    init(barco_salida, 0)
    cobegin
        puente;
        auto; ...
        barco; ...
    coend
end
En respuesta a Nicolas Nocetti Lago

Re: Practico 5 - ejercicio 7

de Martin Pacheco -

Inicialmente le veo dos problemas en auto y barco.

En auto estas leyendo la variable cont_barcos sin mutoexcluirlo [ usar mutex_barcos para asegurara la mutoexclusion de la varaible ].

En auto y en barco estas te estas bloqueando sin liberar el mutex de mutex_auto, mutex_barco respectivamente. Es decir, te bloqueas con P(bloqueo_autos) o P(bloqueo_autos), hasta que no te llegue un V para liberar eso, tenes trancado tambien apropiado mutex. Esto te puede trancar alguna logica que hagas en puente.

Lo ideal segun entiendo, es usar una lógica un poco parecida a la que se usa cuando elegis que codigo pertenece a las citas en ADA, intentando que sea el menos posible.


Respecto a la solución en general, me costó un poco entender donde controlas cada cosa, pero respecto a lo que yo razoné de este ejercicio, es mas simple si le dejas toda la lógica al puente y en auto y barco solo incrementas la variable cantidad.

Si buscas en el eva, hay varias otras soluciones de este ejercicio y comentarios sobre la misma que capaz te ayuden a ver por donde encaminarte.

En respuesta a Martin Pacheco

Re: Practico 5 - ejercicio 7

de Nicolas Nocetti Lago -

Gracias Martin por verlo y comentar.

Si, quise utilizar el mutex  para bloquear los autos y los barcos que vinieran luego de que el primero quedara bloqueado y no me di cuenta que también quedaba bloqueado el procedimiento puente. Además como el primer auto luego de que llego un barco se bloquea luego de incrementar la variable cont_autos, la variable nunca llegara a 0 por lo que nunca bajara el puente.

En cuanto a dejar toda la lógica en el puente, no se me ocurre muy bien como. ¿Podes colgar la solución que se te ocurrió a vos?

Con las modificaciones la soución que se me ocurrió quedaría así, aunque no me convence mucho.


Program ejercicio_7

var cont_autos: integer
var cont_barcos: integer
var puente_inactivo: bool
var mutex: semaforo
var puente_vacio: semaforo
var bloqueo_barcos: semaforo
var bloqueo_primer_auto: semaforo
var bloqueo_mas_autos: semaforo
var auto_entrada: semaforo
var auto_salida: semaforo
var barco_entrada: semaforo
var barco_salida: semaforo

Procedure auto
begin
loop
P(bloqueo_mas_autos)
P(mutex)
if cont_barcos <> 0 then
auto_bloqueado:=true
V(mutex)
P(bloqueo_primer_auto)
else
V(mutex)
end if
V(bloqueo_mas_autos)
P(mutex)
cont_autos:=cont_autos+1;
if puente_inactivo then
V(puente_vacio)
end if
V(mutex)
P(auto_entrada)
delay(X)
V(auto_salida)
anda_por_ahi()
end loop
end

Procedure barco
begin
loop
P(mutex)
cont_barcos:=cont_barcos+1;
if puente_inactivo then
V(puente_vacio)
end if
if cont_barcos = 1 then
V(mutex)
P(bloque_barco)
else
V(mutex)
end if
P(barco_entrada)
delay(X)
V(barco_salida)
navega_por_ahi()
end loop
end

Procedure puente
var puente_bajo: bool
begin
puente_bajo:=true
loop
P(mutex)
if cont_autos=0 and cont_barcos=0 then
puente_inactivo:=true
V(mutex)
P(puente_vacio)
puente_inactivo:=false
else
V(mutex)
end if
if puente_bajo then
if cont_barcos <> 0 and cont_autos = 0 then
puente_bajo:=false
levantar_puente()
V(bloqueo_barcos)
else
P(auto_salida)
P(mutex)
cont_autos:=cont_autos-1;
V(mutex)
V(auto_entrada)
end if
else
P(barco_salida)
P(mutex)
cont_barcos:=cont_barcos-1;
if cont_barcos = 0 then
puente_bajo:=true
bajar_puente()
if auto_bloqueado then
V(bloqueo_primer_auto)
end if
end if
V(mutex)
V(barco_entrada)
end if
end loop
end

begin
cont_autos:=0;
cont_barcos:=0;
puente_inactivo:=false;
init(mutex, 1)
init(puente_vacio, 0)
init(bloqueo_barcos, 0)
init(bloqueo_primer_auto, 0)
init(bloqueo_mas_autos, 1)
init(auto_entrada, MAX_AUTOS_PUENTE)
init(auto_salida, 0)
init(barco_entrada, 1)
init(barco_salida, 0)
cobegin
puente;
auto; ...
barco; ...
coend
end