18.01.2015 Views

Programación Concurrente Prácticas 1, 2 y 3 - Profe Saul

Programación Concurrente Prácticas 1, 2 y 3 - Profe Saul

Programación Concurrente Prácticas 1, 2 y 3 - Profe Saul

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Programación <strong>Concurrente</strong><br />

Prácticas 1, 2 y 3<br />

Dpto. LSIIS — Unidad de Programación Convocatoria de Febrero — curso 2006/2007<br />

Normas<br />

La fecha límite de entrega de la práctica 1 es el 11 de diciembre de 2006 a las 21:00.<br />

La fecha límite de entrega de la práctica 2 es el 8 de enero de 2007 a las 21:00.<br />

La fecha límite de entrega de la práctica 3 es el 22 de enero de 2007 a las 21:00.<br />

Deberá mencionarse explícitamente el uso de recursos (código, algoritmos específicos, esquemas<br />

de implementación, etc.) que no hayan sido desarrollados por el alumno o proporcionados<br />

como parte de asignaturas de la carrera. La falta de esta mención podrá impedir<br />

aprobar las prácticas.<br />

Os recordamos que todas las prácticas entregadas pasan por un proceso automático de detección<br />

de copias. Los involucrados en la copia de una práctica corren el riesgo de suspenderlas<br />

suspenderlas para el año académico en curso, independientemente de la calidad o<br />

adecuación del código.<br />

1. Pastas de té<br />

Una fábrica de pastas de té tiene tres hornos que producen pastas de diferentes pesos. Procedentes<br />

de los hornos, las pastas se van situando en una cinta transportadora común.<br />

Las pastas tienen que ser empaquetadas en cajas. Para ello, uno o varios robots empaquetadores<br />

toman pastas de la cinta y las introducen en la caja tal y como muestra la siguiente figura:<br />

Cada caja puede contener un número diferente de pastas siempre y cuando no se sobrepase<br />

un peso límite. Por este motivo, antes de incluir una pasta en la caja, cada empaquetador debe<br />

asegurarse de que con su inclusión no se sobrepasa el peso máximo. Si no se sobrepasa el peso se


2 Programación <strong>Concurrente</strong><br />

incluye la pasta en la caja; en otro caso, un operario debe retirar la caja que se estaba llenando y<br />

sustituirla por otra vacía.<br />

El objetivo consiste en llenar cada caja lo más posible. Esto puede ser conseguido por cualquiera<br />

de los robots empaquetadores que intentan depositar simultáneamente alguna pasta. Se nos<br />

asegura que no puede haber interferencias físicas entre brazos robot que intentan soltar pastas al<br />

mismo tiempo en la caja. Se pretende que haya la máxima concurrencia posible entre los brazos<br />

robot, es decir, que varios de ellos puedan retirar simultáneamente pastas de la cinta transportadora<br />

y, también simultáneamente, dejarlas en la caja. Hay que evitar, por otro lado, que se sobrepase<br />

el peso máximo admitido por la caja y que se intenten dejar pastas cuando no hay caja o cuando<br />

se está reponiendo.<br />

Para desarrollar el software de control se dispone de un paquete en Ada –ya programado–<br />

que proporciona, entre otros, los siguientes procedimientos de acceso a los robots y dispositivos<br />

mecánicos (se ignoran los hornos y la cinta; no es asunto del software de control):<br />

with Basicos;<br />

use Basicos;<br />

package Cadena is<br />

---------------------------------------------------------------------<br />

N_EMPAQUETADORES : constant Positive := 10;<br />

---------------------------------------------------------------------<br />

-- PESO_MAXIMO : constant Peso;<br />

-- function "=" (A, B : Peso) return Boolean;<br />

-- function "


Curso 2006/2007 — Convocatoria de Febrero 3<br />

2. Diseño<br />

Tras el análisis del problema, se incluye un diseño propuesto: grafo de recursos y procesos,<br />

código de los procesos y especificación del recurso. Asumimos que el recurso está contenido en<br />

una variable Cont_Caja accesible por los procesos cuyo tipo es Control_Caja<br />

Tomar_Pasta<br />

(E,P)<br />

Reponer_Caja<br />

Caja<br />

Empaquetadores<br />

(E)<br />

Comunicar_Peso<br />

(Caja, P)<br />

Incrementar_Peso<br />

(Caja, P)<br />

Notificar_Reposicion<br />

Brazo<br />

Notificar_Pasta_En_Caja<br />

(Caja)<br />

Preparar_Reposicion<br />

Soltar_Pasta<br />

(E)<br />

Retirar_Caja<br />

Declaración de recurso:<br />

Cont_Caja : Control_Caja;<br />

Controlador de empaquetador:<br />

loop<br />

Tomar_Pasta (E, Peso_Pasta);<br />

Put_Line ("Emp." & Id_Empaquetador’Image (E) &<br />

" tomó pasta " & Tipo_Peso’Image (Peso_Pasta));<br />

Comunicar_Peso (Cont_Caja, Peso_Pasta);<br />

Incrementar_Peso (Cont_Caja, Peso_Pasta);<br />

Soltar_Pasta (E);<br />

Put_Line ("Emp." & Id_Empaquetador’Image (E) &<br />

" soltó pasta " & Tipo_Peso’Image (Peso_Pasta));<br />

Notificar_Pasta_En_Caja (Cont_Caja);<br />

end loop;<br />

Controlador de reponedor:<br />

loop<br />

Preparar_Reposicion (Cont_Caja);<br />

Put_Line ("+++ Retiramos caja");<br />

Retirar_Caja;<br />

Put_Line ("+++ Reponemos caja");<br />

Reponer_Caja;<br />

Notificar_Reposicion (Cont_Caja);<br />

end loop;<br />

Especificación del recurso:<br />

C-TADSOL Control Caja<br />

OPERACIONES<br />

ACCIÓN Preparar Reposicion: Control Caja[io]<br />

ACCIÓN Notificar Reposicion: Control Caja[io]<br />

ACCIÓN Comunicar Peso: Control Caja[io] × Peso[i]<br />

ACCIÓN Incrementar Peso: Control Caja[io] × Peso[i]<br />

ACCIÓN Notificar Pasta En Caja: Control Caja[io]<br />

SEMÁNTICA<br />

DOMINIO:


4 Programación <strong>Concurrente</strong><br />

TIPO: Control Caja= (peso: Peso × estado: Estado × accediendo: N)<br />

Estado = preparada | a reponer | reponiendo<br />

INICIAL(c): c = (0, preparada, 0)<br />

CPRE: c = ( , a reponer, 0)<br />

Preparar Reposicion(c)<br />

POST: c sal = (c ent .peso, reponiendo, 0)<br />

CPRE: verdad<br />

Notificar Reposicion(c)<br />

POST: c sal = (0, preparada, 0)<br />

CPRE: c.estado ≠ reponiendo<br />

Comunicar Peso(c, p)<br />

POST: c ent = (pin, , a) ∧ (pin + p > P ESO MAXIMO → c sal =<br />

(pin, a reponer, a)) ∧<br />

(pin + p ≤ P ESO MAXIMO → c sal = (pin, preparada, a))<br />

CPRE: c.peso + p ≤ P ESO MAXIMO ∧ c.estado ≠ reponiendo<br />

Incrementar Peso(c, p)<br />

POST: c ent = (pin, e, a) ∧ c sal = (pin + p, e, a + 1)<br />

CPRE: verdad<br />

Notificar Pasta En Caja(c)<br />

POST: c ent = (pin, e, a) ∧ c sal = (pin, e, a − 1)<br />

Notas informales sobre el funcionamiento del recurso<br />

La reposición pasa por tres fases: preparada (se pueden dejar pastas), a reponer (se debe reponer<br />

una caja, porque hay un robot que puede sobrepasar su capacidad) y reponiendo (se ha<br />

iniciado la secuencia de reposición). El estado a reponer no es irreversible, pues sólo señala que<br />

un brazo robot necesita una caja nueva, pero puede haber otro brazo que lleve una pasta de peso<br />

inferior al necesario para exceder el peso máximo de la caja. Si la señal de este segundo brazo<br />

llega a tiempo puede eliminar la petición de recambio y dejar una pasta que aún cabe en la caja.<br />

El estado reponiendo sí es irreversible, pues indica que el brazo reponedor ha recibido la necesidad<br />

de reposición e iniciará el proceso de cambio de caja.<br />

Para que haya un buen comportamiento en caso de varios robots, el peso de caja se guarda en<br />

el recurso, lo que garantiza su acceso atómico. La CPRE de Incrementar Peso asegura que:<br />

Ningún robot puede exceder el peso máximo (c.peso + p ≤ P ESO MAXIMO), pues se<br />

comprueba justo antes de intentar dejar la pasta y su POST incrementa (atómicamente)<br />

dicho peso antes de que este sea efectivo en la caja, con lo que el recurso contiene un avance<br />

del futuro de la caja y las decisiones tomadas según este valor son seguras.<br />

Ningún robot dejará una pasta mientras se está reponiendo la caja (c.estado ≠ reponiendo).<br />

Pero un robot cuya pasta no causa exceso de peso puede dejar la mercancía aunque haya<br />

otro robot bloqueado por su pasta mientras no se haya iniciado la secuencia de reposición.<br />

En este último caso, el robot que ha adelantado a los demás elimina la señal de reposición.<br />

Será este mismo (u otro, si hay más no bloqueados) el que la reactive, si es necesario, en el<br />

momento en que, tras dejar su pasta, adquiera otra del horno e intente depositarla en la caja. Esto<br />

intenta maximizar el peso final de la caja. De no hacerlo así, una solución extrema, correcta, pero<br />

evidentemente indeseable, es poner siempre una sola pasta y reponer la caja.


Curso 2006/2007 — Convocatoria de Febrero 5<br />

Una solucion que maximiza el peso en lo posible es esperar a todos los robots en una barrera,<br />

calcular qué combinación de pastas de entre las disponibles daría un mejor resultado, elegir la<br />

mejor de las pastas, depositar sólo esa pasta repetir el ciclo. Sin embargo esta solución tiene una<br />

concurrencia muy baja, ya que tiende a que en cada momento sólo un robot acceda a la caja y al<br />

mostrador.<br />

El conteo de número de brazos robot accediendo a la caja es necesario para implementar una<br />

exclusión parcial (como en los problemas de Lectores y Escritores) que impida que se inicie una<br />

reposición de la caja mientras un brazo robot accede a la misma. Ello podría suceder si mientras<br />

se deposita (físicamente) una pasta, otro robot excede el peso máximo y pide un cambio de caja<br />

que se inicia mientras el anterior está aún dejando la pasta. Por otra parte, se permite que varios<br />

brazos robots dejen simultáneamente pastas en la caja.<br />

3. Prácticas<br />

3.1. Primera práctica<br />

La entrega de la primera práctica constará de una implementación del recurso en Ada 95 usando<br />

objetos protegidos, basada en la especificación dada en el enunciado. La implementación a realizar<br />

debe estar contenida en un fichero llamado cajas de pastas.adb (ver el apartado 4).<br />

3.2. Segunda práctica<br />

La entrega de la segunda práctica constará de una implementación del recurso compartido en Ada<br />

95 mediante rendez-vous y/o paso de mensajes y basada en la especificación entregada en el enunciado.<br />

La implementación deberá estar contenida en un fichero llamado cajas de pastas.adb<br />

(ver el apartado 4).<br />

3.3. Tercera práctica<br />

Supongamos una variación del problema original en la que los robots empaquetadores no<br />

registran el peso de las pastas, sino que la plataforma en que está la caja tiene una balanza y en el<br />

paquete Cadena se dispone de una operación<br />

Peso_Balanza(P: out Peso)<br />

que es no bloqueante y de ejecución prácticamente inmediata.<br />

La entrega de la tercera práctica constará de una memoria en papel con un nuevo diseño que<br />

debe cumplir en lo posible los mismos requisitos que se tenían para el problema inicial. Puede<br />

modificarse todo lo que sea necesario, tanto en el diseño del recurso como en el código de las<br />

tareas. Debe entregarse el grafo de procesos y recursos (si ha variado), la especificación formal<br />

del recurso necesario para la sincronización de los procesos y el código de los procesos en función<br />

de la interfaz del recurso especificado.


6 Programación <strong>Concurrente</strong><br />

4. Información general<br />

El texto de estas prácticas se encuentra en<br />

http://lml.ls.fi.upm.es/pc/practicas/<br />

La entrega del código se realizará vía WWW en la dirección<br />

http://lml.ls.fi.upm.es/entrega/<br />

Las memorias pedidas (en la práctica 3) se entregarán en papel al profesor del grupo en el que<br />

se esté matriculado (se habilitará un buzón a la entrada de la unidad para ello). El código que<br />

entreguéis (para objetos protegidos o para paso de mensajes) no debe realizar ninguna operación<br />

de entrada / salida.<br />

Para facilitar la realización de la práctica se suministran varias unidades completas de compilación,<br />

de las que destacamos:<br />

fabrica: programa principal que arranca todas las demás tareas junto con el recurso compartido.<br />

cadena: simulación de las operaciones de una cadena como la descrita en el enunciado.<br />

Estas unidades están disponibles en http://lml.ls.fi.upm.es/pc/practicas/codigo.<br />

En la misma dirección se puede encontrar el interfaz (cajas_de_pastas.ads) del paquete con<br />

el tipo que representa el recurso compartido y un esqueleto de código (cajas_de_pastas.adb)<br />

que debéis completar (y posteriormente entregar) con la implementación del recurso compartido<br />

mediante objetos protegidos y mediante paso de mensajes.<br />

El código que entreguéis debe poder compilarse y ejecutar sin errores junto con el resto de<br />

los paquetes entregados sin modificar estos últimos, aunque los cambiéis y ajustéis para hacer<br />

pruebas durante el desarrollo. Podéis utilizar las librerías auxiliares que están disponibles en<br />

http://lml.ls.fi.upm.es/pc/lib/. Si os veis en la necesidad de usar algún otro paquete<br />

adicional que no venga con GNAT y que no os estemos proporcionando, hacédnoslo saber con<br />

antelación suficiente para evaluar la petición.<br />

El programa de recepción de prácticas podrá rechazar entregas que:<br />

Tengan errores de compilación.<br />

Utilicen otras librerías o paquetes aparte de los estándar de Ada y los que se han mencionado<br />

anteriormente.<br />

No estén suficientemente comentadas. Alrededor de un tercio de las líneas deben ser comentarios<br />

significativos. No se tomarán en consideración para su evaluación prácticas que tengan<br />

comentarios ficticios con el único propósito de rellenar espacio.<br />

Estén escritas con un estilo incorrecto: los programas se compilarán con el compilador GNAT<br />

y las opciones -gnaty -gnata. Recomendamos, por tanto, usar estas opciones para desarrollar<br />

las prácticas.<br />

No superen unas pruebas mínimas de ejecución.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!