next up previous
Next: El almacén de las Up: Examen de Programación Concurrente Previous: Examen de Programación Concurrente

Subsecciones


Controlador de un ascensor

\fbox{\parbox{0.98\textwidth}{\textbf{Nota importante:} el texto de
descripción...
...rcicio. La segunda pregunta es nueva,
y debe realizarse durante este examen.} }

Tenemos un ascensor que atiende P pisos, numerados del 1 al P; se supone la existencia de un tipo $TipoNumPlanta = \{1..P\}$. En cada piso hay un único botón de llamada al ascensor, y en la cabina del ascensor hay un botón para cada piso. En cada piso, a media altura respecto de la puerta del ascensor, hay un sensor que detecta la llegada de la cabina; el sensor no conoce en qué dirección va el ascensor, y tampoco da ninguna señal que nos indique que el ascensor abandona el piso: se limita a recoger cambios de estado de no haber ascensor a haber ascensor (ver la figura [*]).

Figura: Esquema del ascensor
\includegraphics[width=0.3\textwidth]{im/ascensor}

Se trata de diseñar un controlador del ascensor que atienda a las llamadas desde los pisos o la cabina, haciendo que el ascensor suba o baje en función de las mismas, y ocupándose también de que el ascensor se detenga en los pisos en que se haya solicitado parada y se abran y cierren las puertas. Los dispositivos físicos que el controlador debe manejar son las puertas y el motor que mueve el ascensor.

El controlador recibirá la información de los sensores para determinar la posición del ascensor y deberá ocuparse de la parada del mismo cuando corresponda, siempre en función de las llamadas pendientes. Si el ascensor debe detenerse en un piso $p$ se debe ordenar la parada en el momento en que se detecte el paso por el sensor correspondiente a ese piso.

Las puertas deben abrirse automáticamente al llegar a un piso en que realice una parada. Las puertas se cierran automáticamente cuando se pulsa un botón de petición de piso desde el panel del ascensor, o, si no se pulsa ningún botón dentro del ascensor, cuando hayan transcurrido T segundos desde la apertura de las puertas. De haber alguna petición pendiente, el ascensor debe ponerse en marcha inmediatamente después del cierre de las puertas. Una llamada desde un piso cuando el ascensor está detenido con las puertas abiertas no debe cerrarlas, pero debe quedar registrada. El ascensor no debe estar en movimiento a menos que haya alguna petición pendiente.

Interfaz con los dispositivos externos

Se dispone de los siguientes procedimientos ya implementados para actuar sobre los distintos dispositivos involucrados:

Control del motor:

MOTOR.Subir()
Pone en marcha el motor causando la subida del ascensor. El ascensor debe encontrarse detenido cuando se llama a esta operación.

MOTOR.Bajar()
Ídem para bajar.

MOTOR.Parar()
Para el motor, deteniendo el movimiento de la cabina. El ascensor se para automáticamente en el piso inmediatamente próximo según la dirección que llevase en el momento de la llamada. Es decir, si un sensor de un piso N detecta el paso del ascensor (ya sea subiendo o bajando) y en ese momento se llama a MOTOR.Parar, el ascensor tiene capacidad para detenerse en el piso N, y lo hará.

El controlador debe asegurarse de que en ningún momento se llama a dos o más de estas operaciones simultáneamente, pues su implementación no garantiza la exclusión mutua. Cada una de ellas retorna cuando el ascensor se ha puesto en marcha o se ha detenido.

Control de las puertas:

PUERTA.Abrir()
Abre las puertas del ascensor. Retorna cuando las puertas están completamente abiertas. La cabina debe estar detenida y las puertas completamente cerradas en el momento de llamar a esta operación.
PUERTA.Cerrar()
Cierra las puertas del ascensor. Retorna cuando las puertas están completamente cerradas. La cabina debe estar detenida y las puertas completamente abiertas en el momento de llamar a esta operación.

De nuevo se requiere garantizar que no habrá dos operaciones simultáneamente activas; la exclusión mutua no está dada por las operaciones en sí. El tiempo necesario para abrir o cerrar las puertas está acotado, y es relativamente corto, pero no podemos hacer suposiciones acerca de su duración con respecto a la de otros sucesos de este problema.

Lectura de peticiones de pisos:

BOTON.LeerCabina(VAR numPlanta: TipoNumPlanta)
La llamada se bloquea y retorna cuando desde el interior de la cabina se pulsa el botón correspondiente a un piso, devolviendo éste en el parámetro de salida del procedimiento. Supondremos que no se pulsan varios botones simultáneamente.
BOTON.LeerPlanta(numPlanta: TipoNumPlanta)
La llamada retorna cuando se pulsa el botón de llamada de la planta numPlanta. El parámetro numPlanta es entrada, no de salida.

No se puede suponer ningún límite de tiempo para el retorno de ninguna de estas llamadas. En particular no se puede suponer que en algún momento alguien hará una petición para un piso dado.

Detección de paso del ascensor por los sensores:

SENSOR.DetectarPaso(VAR numPlanta: TipoNumPlanta)
La llamada se queda bloqueada y retorna cuando el sensor detecta la llegada del ascensor a una planta, y devuelve el número de planta por la que está pasando.

Control del tiempo:

TIEMPO.ahora(): CARDINAL
Devuelve la hora actual en segundos contados desde un momento en el pasado.
TIEMPO.espera(lapso: CARDINAL)
Se bloquea durante el tiempo, expresado en segundos, determinado por su argumento.

De cara a la especificación, las llamadas a operaciones que actúan sobre un dispositivo externo pueden ponerse como POST(Subir), si ello es necesario. Las operaciones que devuelven un resultado se supondrán especificadas como acciones.

Aclaración: el algoritmo del ascensor

Aunque no es estrictamente necesario, se sugiere utilizar el llamado algoritmo del ascensor, aplicado frecuentemente en el acceso a discos. La idea de este algoritmo es que el ascensor sube y baja alternativamente. Mientras va en una dirección se efectúan las paradas necesarias en esa dirección. Cuando no quedan más peticiones en la dirección actual, se invierte el sentido de la marcha. Si no hay ninguna petición pendiente, el ascensor se detiene.

Resultados a entregar

  1. Este apartado es exactamente igual al ya dejado para su realización. Sobre el problema anteriormente descrito, se pide:

  2. Este apartado es nuevo. Corregir el diseño anterior, adaptándolo a la siguiente situación:

    En lugar de un solo ascensor, se controlarán conjuntamente N ascensores. Para ello se modifica el interfaz con los módulos MOTOR, PUERTA, BOTON y SENSOR de manera que tengan un parámetro que indique el ascensor al que se refieren, de tipo TipoNumAscensor (TYPE TipoNumAscensor = [1..N]):

    MOTOR.Subir/Bajar/Parar(k: TipoNumAscensor)
    PUERTA.Abrir/Cerrar(k: TipoNumAscensor)
    BOTON.LeerCabina(k: TipoNumAscensor; VAR numPlanta: TipoNumPlanta)
    SENSOR.DetectarPaso(k: TipoNumAscensor; VAR numPlanta: TipoNumPlanta)

    El controlador debe asegurar que no se dan dos órdenes simultáneas para el mismo ascensor, pero sí se admiten órdenes simultáneas si van dirigidas a ascensores diferentes.

    Se mantiene un solo botón de llamada en cada piso, pero se simplifica la operación de lectura de esos botones para hacerla similar a la lectura de los botones de una cabina:

    BOTON.LeerPlanta(VAR numPlanta: TipoNumPlanta)
    La llamada se bloquea y retorna cuando se haya pulsado algún botón de llamada desde un piso, devolviendo éste en el parámetro de salida del procedimiento. Supondremos que no se pulsan varios botones al mismo tiempo.

    Con estos supuestos, se pide:

Solución propuesta -- Parte 1

Para determinar qué procesos se necesitan, se puede analizar qué operaciones no instantáneas puede que tengan que realizarse al mismo tiempo. Esto ocurre con las siguientes:

La comunicación y sincronización entre los procesos puede hacerse mediante un recurso compartido que gestione las peticiones pendientes y el estado del ascensor en un momento dado. Este recurso contendrá información sobre:

Esta última información podría plantearse también como correspondiente a un recurso separado que gestione solamente la temporización de la apertura y cierre de las puertas.

También es posible realizar la temporización directamente en el proceso que ordena el movimiento del ascensor, si el tiempo se va contando por periodos pequeños, y no con una espera única hasta el tiempo límite.

A continuación se describe la solución que usa un proceso separado para temporizar, y un recurso único que gestiona las peticiones y el permiso para cerrar las puertas. El diagrama de procesos y recursos se muestra en la figura  [*]

Figura: Diagrama de procesos y recursos -- primer supuesto
\includegraphics[width=\textwidth]{im/adis}

Código de las tareas


\begin{lstlisting}{}
TASK BotonCabina;
VAR p: TipoNumPlanta;
BEGIN
LOOP
BOTON.LeerCabina(p);
GESTOR.PulsadoCabina(p);
END
END BotonCabina;
\end{lstlisting}


\begin{lstlisting}{}
TASK BotonPlanta(p: TipoNumPlanta);
BEGIN
LOOP
BOTON.LeerPlanta(p);
GESTOR.PulsadoPlanta(p);
END
END BotonPlanta;
\end{lstlisting}


\begin{lstlisting}{}
TASK Temporizador;
VAR t: CARDINAL;
BEGIN
LOOP
GESTOR.In...
...- TIEMPO.Ahora);
GESTOR.TerminarEspera;
END
END Temporizador;
\end{lstlisting}


\begin{lstlisting}{}
TASK Ascensor;
VAR p: TipoNumPlanta;
movimiento: TipoMovi...
...r;
PUERTA.Abrir;
GESTOR.ParadoEnPlanta(p);
END
END Ascensor;
\end{lstlisting}

Especificación del recurso


C-TADSOL TipoGestor 

C-Operaciones
ACCION PulsadoCabina: TipoGestor \ensuremath{\times} TipoNumPlanta[ent]
ACCION PulsadoPlanta: TipoGestor \ensuremath{\times} TipoNumPlanta[ent]
ACCION HayPeticion: TipoGestor \ensuremath{\times} TipoNumPlanta[ent] \ensuremath{\times} \ensuremath{\mathcal{B}}[sal]
ACCION ParadoEnPlanta: TipoGestor \ensuremath{\times} TipoNumPlanta[ent]
ACCION IniciarEspera: TipoGestor\ensuremath{\times} \ensuremath{\mathcal{N}}[sal]
ACCION TerminarEspera: TipoGestor
ACCION ElegirMovimiento: TipoGestor \ensuremath{\times} TipoMovimiento[sal]

TRANSACCIONES
PulsadoCabina
PulsadoPlanta
HayPeticion
ParadoEnPlanta
IniciarEspera
TerminarEspera
ElegirMovimiento

CONCURRENCIA
ninguna

Dominio
Tipo: TipoGestor = (peticion: Secuencia(\ensuremath{\mathcal{B}}) \ensuremath{\times} sentido: TipoMovimiento \ensuremath{\times} posicion: TipoNumPlanta \ensuremath{\times}
pulsadaCabina: \ensuremath{\mathcal{B}} \ensuremath{\times} tiempoActual: \ensuremath{\mathcal{N}}\ensuremath{\times} tiempoLimite: \ensuremath{\mathcal{N}})
TipoNumPlanta = 1..P
TipoMovimiento = (SUBIR $\vert$ BAJAR)

Invariante: $\forall t \in\emph{TipoGestor}\ensuremath{\bullet}\textsf{Longitud}(t.peticion) = P$

CPRE: cierto
PulsadoCabina(g, p)
POST: Anota la petici'on y marca pulsaci'on desde cabina
POST: $g^{ent} = g^{sal} / g\ensuremath{^{sal}}.peticion_p \wedgeg\ensuremath{^{sal}}.pulsadaCabina$

CPRE: cierto
PulsadoPlanta(g, p)
POST: Anota la petici'on
POST: $g^{ent} = g^{sal} / g\ensuremath{^{sal}}.peticion_p$

CPRE: cierto
HayPeticion(g, p, hay)
POST: Indica si hay petici'on para esa planta
POST: $g^{ent} = g^{sal} \wedge hay^{sal} = peticion_p$

CPRE: cierto
ParadoEnPlanta(g, p)
POST: Anota que se ha atendido la petici'on de esa planta, y comienza el plazo de apertura de puertas
POST: $g^{ent} = g^{sal} / \neg g\ensuremath{^{sal}}.peticion_p \wedge g\ensuremath{^{sal}}.posicion = p \wedge \neg g\ensuremath{^{sal}}.pulsadaCabina \wedge$
$g\ensuremath{^{sal}}.abierto \wedge g\ensuremath{^{sal}}.tiempoActual = TIEMPO....
...wedge g\ensuremath{^{sal}}.tiempoLimite = g\ensuremath{^{sal}}.tiempoActual + T$

CPRE: g\ensuremath{^{ent}}.tiempoActual $<$ g\ensuremath{^{ent}}.tiempoLimite
IniciarEspera(g, t)
POST: Indica el tiempo l'imite hasta el que hay que esperar
POST: $g^{ent} = g^{sal} \wedge t^{sal} =$g\ensuremath{^{ent}}.tiempoLimite

CPRE: cierto
TerminarEspera(g)
POST: Anota el nuevo tiempo actual
POST: $g^{ent} = g^{sal} / \emph{g\ensuremath{^{sal}}.tiempoActual} =$TIEMPO.Ahora

CPRE: Hay peticiones para otra planta y se han mantenido laspuertas abiertas el tiempo suficiente
CPRE: $\exists p \in \emph{TipoNumPlanta}\ensuremath{\bullet}p \not=g\ensuremath{^{ent...
...nsuremath{^{ent}}.peticion}_p \wedge p\not=g\ensuremath{^{ent}}.posicion \wedge$
$(\emph{g\ensuremath{^{ent}}.pulsadaCabina} \vee \emph{g\ensuremath{^{ent}}.tiempoActual} <\emph{g\ensuremath{^{ent}}.tiempoLimite})$
ElegirMovimiento(g, mov)
POST: Indica que hay que subir si hay peticiones superiores y, o bien est'a subiendo o no hay peticiones inferiores.
Indica que hay que bajar en caso contrario. Adem'as anota el nuevo sentido de movimiento y que
las puertas est'an cerradas. y anula peticiones para el piso en que estaba.
POST: $g^{ent} = g^{sal} / \emph{g\ensuremath{^{sal}}.sentido} = g\ensuremath{^{sal}}....
...\neg g\ensuremath{^{sal}}.abierto \wedge g\ensuremath{^{sal}}.peticion_p \wedge$
$g\ensuremath{^{sal}}.mov = \left\{ \begin{array}{ll} \mathrm{SUBIR} & \exists p...
...sicion} \wedge \emph{peticion}_k)  \mathrm{BAJAR} & e.o.c. \end{array}\right.$

Solución propuesta -- Parte 2

Se puede mantener en esencia el diseño anterior, con los siguientes cambios.

El diagrama de procesos y recursos se muestra en la figura [*].

Código de las tareas


\begin{lstlisting}{}
TASK BotonCabina(a: TipoNumAscensor);
VAR p: TipoNumPlanta...
...- TIEMPO.Ahora);
GESTOR.TerminarEspera;
END
END Temporizador;
\end{lstlisting}

\begin{lstlisting}{}
TASK Ascensor(a: TipoNumAscensor);
VAR p: TipoNumPlanta;
...
...ERTA.Abrir(a);
GESTOR.ParadoEnPlanta(a, p);
END
END Ascensor;
\end{lstlisting}

Figura: Diagrama de procesos y recursos -- segundo supuesto
\includegraphics[width=\textwidth]{im/adis-2}

Especificación del recurso


C-TADSOL TipoGestor 

C-Operaciones
ACCION PulsadoCabina: TipoGestor \ensuremath{\times} TipoNumAscensor[ent] \ensuremath{\times} TipoNumPlanta[ent]
ACCION PulsadoPlanta: TipoGestor \ensuremath{\times} TipoNumPlanta[ent]
ACCION HayPeticion: TipoGestor \ensuremath{\times} TipoNumAscensor[ent] \ensuremath{\times} TipoNumPlanta[ent] \ensuremath{\times} \ensuremath{\mathcal{B}}[sal]
ACCION ParadoEnPlanta: TipoGestor \ensuremath{\times} TipoNumAscensor[ent] \ensuremath{\times} TipoNumPlanta[ent]
ACCION IniciarEspera: TipoGestor \ensuremath{\times} \ensuremath{\mathcal{N}}[sal]
ACCION TerminarEspera: TipoGestor
ACCION ElegirMovimiento: TipoGestor\ensuremath{\times} TipoNumAscensor[ent] \ensuremath{\times} TipoMovimiento[sal]

TRANSACCIONES
PulsadoCabina
PulsadoPlanta
HayPeticion
ParadoEnPlanta
IniciarEspera
TerminarEspera
ElegirMovimiento

CONCURRENCIA
ninguna

DOMINIO
TIPO: TipoGestor = (petPlanta: Secuencia(TipoPeticion) \ensuremath{\times} peticion: Secuencia(Secuencia(\ensuremath{\mathcal{B}})) \ensuremath{\times}
asignada: Secuencia(\ensuremath{\mathcal{N}}) \ensuremath{\times} sentido: Secuencia(TipoMovimiento) \ensuremath{\times}
posicion: Secuencia(TipoNumPlanta) \ensuremath{\times} pulsadaCabina: Secuencia(\ensuremath{\mathcal{B}}) \ensuremath{\times}
tiempoActual: \ensuremath{\mathcal{N}}\ensuremath{\times} tiempoLimite: Secuencia(\ensuremath{\mathcal{N}}))
TipoNumPlanta = (1..P)
TipoMovimiento = (SUBIR $\vert$ BAJAR)
TipoPeticion = (INACTIVA, PEDIDA, ASIGNADA)

INVARIANTE: $\forall g \inTipoGestor\ensuremath{\bullet}\textsf{Longitud}(p.petPlanta) = P \wedge \textsf{Longitud}(g.sentido) = NumAscensores \wedge $
$\textsf{Longitud}(g.asignada) = NumAscensores \wedge \textsf{Longitud}(g.posicion) = NumAscensores \wedge $
$\textsf{Longitud}(g.pulsadaCabina) = NumAscensores \wedge $
$\textsf{Longitud}(g.tiempoActual) = NumAscensores \wedge $
$\textsf{Longitud}(g.tiempoLimite) = NumAscensores \wedge $
$\forall i\in\{1..NumAscensores\}\ensuremath{\bullet}\mathsf{Longitud}(g.peticion_i) = P$

CPRE: cierto
PulsadoCabina(g, a, p)
POST: Anota la petici'on y marca pulsaci'on desde cabina

CPRE: cierto
PulsadoPlanta(g, p)
POST: Anota la petici'on, si no lo estaba todav'ia

CPRE: cierto
HayPeticion(g, a, p, hay)
POST: Indica si hay petici'on desde cabina o planta paraese ascensor y planta. Si hay petici'on PEDIDA
para esa planta, sele asigna a ese ascensor,deshaciendo la asignaci'on anterior, si la hubiera.

CPRE: cierto
ParadoEnPlanta(g, a, p)
POST: Anota que se ha atendido la petici'on de cabina y/o planta ASIGNADA de esa planta,
y comienza el plazo de apertura de puertas

CPRE: Hay alguna temporizaci'on pendiente
CPRE: $\exists a \in \emph{TipoNumAscensor}\ensuremath{\bullet}\emph{g.tiempoActual} < \emph{g.tiempoLimite}_a$
IniciarEspera(g, t)
POST: Indica el m'inimo tiempo l'imite hasta el que hayque esperar

CPRE: cierto
TerminarEspera(g)
POST: Anota el nuevo tiempo actual

CPRE: Hay alguna petici'on para atender por ese ascensor(desde cabina, o bien desde planta, no asignada)
y se ha cumplido el plazo para mantener las puertas abiertas.
ElegirMovimiento(g, a, mov)
POST: Indica que hay que subir si hay peticiones superiores y, o bien est'a subiendo o no hay peticiones inferiores.
Indica que hay que bajar en caso contrario. Adem'as anota el nuevo sentido de movimiento.
La asignaci'on de petici'on desde una planta a ese ascensor se hace si no hay peticiones de cabina
pero s'i peticiones de planta en el sentido de su movimiento.


next up previous
Next: El almacén de las Up: Examen de Programación Concurrente Previous: Examen de Programación Concurrente
Manuel Carro
2001-03-01