You are on page 1of 293

Programaci n Concurrente o Curso 2009-2010

Documentaci n completa o de Pr cticas y Ejercicios a


Sergio Garca Mondaray Rodrigo Testillano Tordesillas David Antonio P rez Zaba e

Escuela Superior de Inform tica de Ciudad Real a Universidad de Castilla-La Mancha

Indice general
I
1

Pr cticas a
El puente de Puente Duero 1.1 1.2 Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resoluci n por monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . o 1.2.1 1.2.2 1.3 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

9
11 11 12 12 12 17 17 17 22 22 22 27 27 28 34 34 34 38 38 38 38 39 39 40 40

Resoluci n por monitores en Java . . . . . . . . . . . . . . . . . . . . . . . . . o 1.3.1 1.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

1.4

Resoluci n por sem foros en Ada . . . . . . . . . . . . . . . . . . . . . . . . . o a 1.4.1 1.4.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

1.5

Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . o 1.5.1 1.5.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

1.6

Resoluci n por regiones crticas condicionales en Ada . . . . . . . . . . . . . . o 1.6.1 1.6.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

1.7

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7.1 1.7.2 1.7.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

El circuito de karts 2.1 2.2 Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . o 2.2.1 Sin modicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2.2 2.2.3 2.3

Modicaci n (a) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o Modicaci n (b) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

45 51 59 59 64 69 76 76 77 88 88 88 88 89 89 90 90 90 99 99 99

Resoluci n por Monitores en Java . . . . . . . . . . . . . . . . . . . . . . . . . o 2.3.1 2.3.2 2.3.3 Sin modicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modicaci n (a) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o Modicaci n (b) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

2.4

Resoluci n por Monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . o 2.4.1 2.4.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

2.5

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 2.5.2 2.5.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Cintas transportadoras 3.1 3.2 Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resoluci n por monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . o 3.2.1 3.2.2 3.3 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

Resoluci n por monitores en Java . . . . . . . . . . . . . . . . . . . . . . . . . o 3.3.1 3.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

3.4

Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 o 3.4.1 3.4.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 o

3.5

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 3.5.1 3.5.2 3.5.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 125

Bolsa en Red 4.1 4.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Resoluci n por monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . 126 o 4.2.1 4.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 o

4.3

Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 o 4.3.1 4.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 o

4.4

Resoluci n por monitores en Java . . . . . . . . . . . . . . . . . . . . . . . . . 142 o 4.4.1 4.4.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 o

4.5

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 4.5.1 4.5.2 4.5.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 153

Directores deportivos 5.1 5.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Resoluci n por Citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 o 5.2.1 5.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 o

5.3

Resoluci n por monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . 161 o 5.3.1 5.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 o

5.4

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 5.4.1 5.4.2 5.4.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 171

Servicio de Atenci n de Urgencias o 6.1 6.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Resoluci n por Citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 o 6.2.1 6.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 o

6.3

Versi n simplicada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 o 6.3.1 6.3.2 Resoluci n por Citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . 185 o Resoluci n por Monitores en Ada . . . . . . . . . . . . . . . . . . . . . 189 o

6.4

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 6.4.1 6.4.2 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 o 5

6.4.3 7

Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 195

Becarios del servicio de Inform tica a 7.1 7.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 o 7.2.1 7.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 o

7.3

Resoluci n por tipos protegidos en Ada . . . . . . . . . . . . . . . . . . . . . . 205 o 7.3.1 7.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 o

7.4

Anexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 7.4.1 7.4.2 7.4.3 Tiempo de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Distribuci n de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 o Dicultad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

II
1

Ejercicios inventados
Julimocho 1.1 1.2

211
213

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 o 1.2.1 1.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 o 223

StarWars: Andr meda vs Ori n o o 2.1 2.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 o 2.2.1 2.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 o 233

F brica de chocolate a 3.1 3.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 o 3.2.1 C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 o 241

Party 4.1

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

4.2

Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 o 4.2.1 4.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 o 247

Florentino P rez e 5.1

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 249 Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

I.O. 6.1

III
1

Ejercicios asignados
Turismo de Almorox 1.1 1.2

251
253

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 o 1.2.1 1.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 o 259

Jardineros 2.1 2.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 o 2.2.1 2.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 o 265

Restaurante 3.1 3.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Resoluci n por citas Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 o 3.2.1 3.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 o

3.3

Resoluci n por monitores en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . 272 o 3.3.1 3.3.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 o C digo Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 o 277

Aeropuerto 4.1 4.2

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 o 4.2.1 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 o 7

4.2.2 5 Audi A3 5.1 5.2

C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 o 285

Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Resoluci n por citas en Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 o 5.2.1 5.2.2 Explicaci n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 o C digo fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 o

IV
1

Anexos
Valoraci n general de la asignatura o 1.1 1.2 1.3

291
293

Sobre la asignatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Sobre la carga de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

Parte I

Pr cticas a

Pr ctica 1 - El puente de Puente Duero a

Pr ctica 1 a

El puente de Puente Duero


1.1 Enunciado

El pueblo de Puente Duero debe su nombre a un viejo puente romano sobre el conocido ro. El puente es estrecho y no permite el cruce de dos coches que circulen en sentidos contrarios. Por su peculiar forma, alto en el centro y bajo en los extremos, no hay visibilidad, y desde un lado no podemos saber si hay un coche empezando a cruzar el puente por el otro. Se han instalado cuatro sensores y dos barreras. Dos sensores indican la llegada de coches en cada direcci n, emitiendo una se al por cada coche que pasa, y los otros dos indican salidas o n respectivas. Las barreras bloquean las entradas al puente, y cuando reciben una se al se levantan n para permitir el paso de un coche (y uno s lo); acto seguido se vuelven a cerrar. o Dise e un Programa Concurrente, libre de bloqueos e inaniciones, que simule el sistema den scrito, incluyendo un proceso que emplee las se ales recibidas de los sensores para emitir se ales n n apropiadas a las barreras, de manera que: 1. Nunca crucen simult neamente el puente vehculos en sentidos opuestos. a 2. Nadie espere eternamente para pasar 3. Todos pasen lo m s pronto posible salvo violaci n de las normas 1 o 2. a o 4. Las se ales de los sensores han de atenderse inmediatamente (o al menos lo m s pronto n a posible), para no perder el paso de ning n coche. u

11

Programaci n Concurrente o

1.2
1.2.1

Resoluci n por monitores en Ada o


Explicaci n o

En la realizaci n de la pr ctica del puente Duero, utilizando la t cnica de monitores en Ada, se o a e ha optado por crear un monitor y un array de tareas coches. El monitor hace las funciones del puente, es decir, es el encargado de dejar pasar a los coches de un lado o de otro, de contabilizar la ocupaci n del puente en cada momento, impidiendo el paso de m s coches y contabilizar el o a n mero de coches seguidos de cada lado que pasan por el puente, ya que s lo podr n pasar un u o a m ximo de coches a la vez. a La tarea coche representar la actuaci n del coche en el puente. El coche llegar al puente, se a o a podr a la cola, esperar hasta que tenga permiso para pasar, pasar y saldr del puente. a a a a Una vez descrita la pr ctica a grandes rasgos, se pasar a explicarla m s detalladamente. Se a a a empezar explicando el monitor, el cual se ha dicho que simular el comportamiento del puente. a a El monitor tendr cuatro porcedimientos y dos entradas. Dos de los procedimientos se usan para a contabilizar los coches que llegan a la cola de cada lado. Existe un procedimiento para la cola de la derecha llega cola der y otro para la cola de la izquierda llega cola izq Las dos entradas pasa coche der y pasa coche izq se utilizar n para que un coche pase por el puente. Un a coche pasar por el puente siempre y cuando se tenga el turno,que quiere decir que no habr coches a a del lado contrario pasando por el puente, la ocupaci n del puente no sea la m xima permitida y o a el n mero de coches seguidos no supere el m ximo permitido. Por ultimo lo que hacemos es u a incrementar, o no, la variable que contabiliza los coches seguidos de cada lado, seguidos der y textttseguidos izq Que se incremente o no esta variable depender si hay coches en el lado a contrario esperando, ya que si no hay, no sirve de nada incrementar esta variable, ya que podr n a pasar todos los coches sin necesidad a que esperen su turno para que los coches del otro lado puedan pasar. Los ultimos dos procedientos sale coche der y sale coche izq se usan para cuando un coche sale del puente, aqu lo que haremos ser decrementar la variable que contabiliza los coches a que estaban pasando por el puente, y la de la ocupaci n de este, ya que tendremos una ocupaci n o o m xima de coches que podr n pasar a la vez por el puente. Seguidamente comprobamos que en el a a puente ya no hay ning n coche, de ese lado pasando por el puente. Si es as, lo que hacemos ser u a dar el turno a los coches del lado contrario en el caso de que haya coches esperando, y si no, el turno que se asigna es indiferente para cada uno de los lados, de tal forma que el lado que primero tenga coches esperando ser el que coja el turno. Por ello se tiene un tipo de dato turno que a puede tener tres valores distintos DER para la derecha IZQ para la izquierda y NONE que un turno neutro. Por ultimo lo que hacemos ser inicializar la variable seguidos a cero siempre y cuando a esta haya alcanzado su lmite. La en la tarea coche lo unico que se har ser asignar un id al coche y un sentido. Una vez a a asignado el sentido el coche se pondr en la cola, esperar apasar por el puente y saldr de el. a a a

1.2.2

C digo Fuente o
C digo fuente 1.1: Problema de Puente Duero con monitores en Ada o

1 2 3

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions;

12

Pr ctica 1 - El puente de Puente Duero a


procedure puenteduero is i: Integer := 0; j: Integer := 0; x: Integer := 1; toca: Integer := 0; MAX_SEGUIDOS: constant Integer := 5; --maximo de coches seguidos . MAX_PUENTE: constant Integer:= 5; --maximos de coches en el puente type turno is (DER,IZQ,NONE);

4 5 6 7 8 9 10

11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

protected Monitor is procedure llega_coche_izq(id: in Integer); procedure llega_coche_der(id: in Integer); entry pasa_coche_izq(id: in Integer); entry pasa_coche_der(id: in Integer); procedure sale_coche_izq(id: in Integer); procedure sale_coche_der(id: in Integer); private cola_coches_izq : Integer :=0; cola_coches_der : Integer := 0; --variables que almacenara el numero de coches de la cola coches_puente_izq: Integer:= 0; coches_puente_der: Integer:= 0; --variables que almacenara los coches el numero de coches --del puente turn: turno:=NONE; seguidos_der: Integer:= 0; seguidos_izq: Integer:= 0; --variable que alamacenara el numero de coches seguidos ocupacion: Integer:=0; -- Definire la variables... end Monitor; protected body Monitor is procedure llega_coche_izq(id: in Integer) is begin put_line("El coche con id: " &IntegerImage(id)& " ha "& "llegado a la cola izquierda."); cola_coches_izq := cola_coches_izq +1; --se pone en la cola end llega_coche_izq; procedure llega_coche_der(id: in Integer) is begin put_line("El coche con id: " &IntegerImage(id)& " ha "& "llegado a la cola derecha."); cola_coches_der := cola_coches_der +1; -- se pone en la cola end llega_coche_der;

13

Programaci n Concurrente o
procedure sale_coche_izq(id: in Integer) is begin put_line("El coche con id: " &IntegerImage(id)& " sale del puente"); coches_puente_izq := coches_puente_izq - 1; --sale del puente-ocupacion := ocupacion -1; if coches_puente_izq = 0 then if cola_coches_der > 0 then --aqui cambiamos el turno turn := DER; else turn := NONE; end if; if seguidos_izq=MAX_SEGUIDOS then seguidos_izq := 0; end if; end if; end sale_coche_izq; procedure sale_coche_der(id: in Integer) is begin put_line("El coche con id: " &IntegerImage(id)& " sale del puente"); coches_puente_der := coches_puente_der -1; -- sale del puente ocupacion := ocupacion -1; if coches_puente_der = 0 then if cola_coches_izq > 0 then --aqui cambiamos el turno turn := IZQ; else turn := NONE; end if; if seguidos_der=MAX_SEGUIDOS then seguidos_der := 0; end if; end if; end sale_coche_der; entry pasa_coche_izq(id: in Integer) when (turn = IZQ or turn = NONE) and seguidos_izq < MAX_SEGUIDOS and ocupacion < MAX_PUENTE is begin turn:=IZQ; put_line("El coche de la izquierda con id: "& IntegerImage(id)&" esta pasando por"& " el puente"); coches_puente_izq := coches_puente_izq + 1; -- Pasa por el puente ocupacion := ocupacion +1; cola_coches_izq := cola_coches_izq -1; --lo quito de la cola

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

14

Pr ctica 1 - El puente de Puente Duero a


put_line("Ocupacion del puente: "&IntegerImage(ocupacion) ); if(cola_coches_der>0) then seguidos_izq := seguidos_izq +1; --Contabilizamos mientras haya coches esperando end if; put_line("Coches Seguidos:"&IntegerImage(seguidos_izq)); end pasa_coche_izq; entry pasa_coche_der(id: in Integer) when (turn = DER or turn = NONE) and seguidos_der < MAX_SEGUIDOS and ocupacion < MAX_PUENTE is begin turn:= DER; put_line("El coche de la derecha con id: "& IntegerImage(id)&" esta pasando por" &" el puente "); coches_puente_der := coches_puente_der +1; ocupacion := ocupacion +1; cola_coches_der := cola_coches_der -1; --lo quito de la cola put_line("Ocupacion del puente:"&IntegerImage(ocupacion)) ; if(cola_coches_izq>0) then seguidos_der := seguidos_der +1; --Contabilizamos mientras haya coches esperando end if; put_line("Coches Seguidos: "&IntegerImage(seguidos_der)); end pasa_coche_der;

114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

end Monitor; task type Coche is entry init_coche(x: natural;s:natural); end Coche;

coches: array (0..20) of Coche; --Array de tareas coches derecha.

task body Coche is id:natural; sen:natural; begin accept init_coche(x: natural;s:natural) do id:=x; sen:=s; end init_coche; if sen = 1 then Monitor.llega_coche_Der(id); Monitor.pasa_coche_Der(id); Monitor.sale_coche_Der(id); else

15

Programaci n Concurrente o
Monitor.llega_coche_izq(id); Monitor.pasa_coche_izq(id); Monitor.sale_coche_izq(id); end if; end Coche;

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

begin while x < 20 loop toca := Positive_Random(2); if toca = 1 and j < 10 then coches(i).init_coche(x,1); i := i+1; x := x+1; j := j+1; else coches(i).init_coche(x,2); i := i+1; x:= x+1; end if; end loop;

end puenteduero;

16

Pr ctica 1 - El puente de Puente Duero a

1.3
1.3.1

Resoluci n por monitores en Java o


Explicaci n o

La losofa que seguimos es muy similar a la del apartado anterior monitores en Ada, y pr cticamente a las peque as diferencias entre una y otra vienen dadas por las peculiaridades del lenguaje de pron gramaci n. o La forma de implementar los tipos protegidos en Java, es mediante la utilizaci n de m todos o e synchronized. Una clase con varios m todos de este tipo, s lo atender a uno al tiempo, e o a asegurando as la exclusi n mutua. o Al contrario de lo que hemos hecho con Ada, en Java vamos a necesitar 2 clases auxiliares a parte del Monitor principal. Esto es as porque los coches de un sentido deber n esperar a un a objeto, mediante wait(), y los del otro sentido a otro obs rvese que no tendra l gica poner e o a todos los coches, sea cual sea su sentido, esperando en una misma cola para un unico objeto. De esta forma, cuando se desee despertar al primer coche esperando en uno de los sentidos, se efectuar la llamada a notify() sobre el objeto correspondiente a dicho sentido. a Tal como se puede apreciar en el c digo fuente, al construir el objeto monitor principal le o pasamos dos auxiliares, uno para cada sentido. De esta forma podemos abstraernos desde la clase principal de esta peculiaridad de la implementaci n, y ser el monitor principal el que se encargar o a a de que todo funcione correctamente.

1.3.2

C digo fuente o
C digo fuente 1.2: Problema de Puente Duero con monitores en Java o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

import java.util.Random; class Monitor { private final int DER = 1; private final int IZQ = 0; private final int NONE = -1; private final int MAX_SEGUIDOS = 3; private final int CAPACIDAD_PUENTE = 5; private int cola_coches_izq; private int cola_coches_der; private int coches_puente_izq; private int coches_puente_der; int turno; int seguidos; int ocupacion; Monitor mon_izq; Monitor mon_der; public Monitor() { cola_coches_der = cola_coches_izq = 0; coches_puente_der = coches_puente_izq = 0; turno = NONE; seguidos = 0;

17

Programaci n Concurrente o
ocupacion = 0; } public Monitor(Monitor izq, Monitor der) { this(); this.mon_der = izq; this.mon_izq = der; } public synchronized void llega_coche_izq(int id) { print("El coche " + id + " llega a la cola (izq)"); cola_coches_izq++; } public synchronized void llega_coche_der(int id) { print("El coche " + id + " llega a la cola (der)"); cola_coches_der++; } public synchronized void sale_coche_izq(int id) { print("El coche " + id + " sale del puente (izq)"); boolean ultimo = false; coches_puente_izq--; ocupacion--; if (ocupacion == 0) { ultimo = true; } if (coches_puente_izq == 0) { if (coches_puente_der > 0) { turno = DER; } else { turno = NONE; } if (seguidos == MAX_SEGUIDOS) { seguidos = 0; } } if ((turno == IZQ || turno == NONE) && seguidos < MAX_SEGUIDOS && !ultimo && ocupacion < CAPACIDAD_PUENTE) { despertar_izq(); } else if (ultimo && turno == DER) { despertar_der(); } } public synchronized void sale_coche_der(int id) { print("El coche " + id + " sale del puente (der)"); boolean ultimo = false; coches_puente_der--; ocupacion--; if (ocupacion == 0) { ultimo = true; } if (coches_puente_der == 0) { if (coches_puente_izq > 0) {

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

18

Pr ctica 1 - El puente de Puente Duero a


turno = IZQ; } else { turno = NONE; } if (seguidos == MAX_SEGUIDOS) { seguidos = 0; } } if ((turno == DER || turno == NONE) && seguidos < MAX_SEGUIDOS && !ultimo && ocupacion < CAPACIDAD_PUENTE) { despertar_der(); } else if (ultimo && turno == IZQ) { despertar_izq(); } } private void despertar_izq() { try { this.mon_izq.notify(); } catch (Exception e) { } } private void despertar_der() { try { this.mon_der.notify(); } catch (Exception e) { } } public synchronized void pasa_coche_izq(int id) { try { if (turno == DER || seguidos >= MAX_SEGUIDOS || ocupacion >= CAPACIDAD_PUENTE) { mon_izq.wait(); } turno = IZQ; print("El coche " + id + " esta cruzando el puente (izq )"); coches_puente_izq++; ocupacion++; print("Ocupacion del puente: " + ocupacion + "/" + CAPACIDAD_PUENTE); cola_coches_izq--; //Lo quitamos de la cola if (cola_coches_der > 0) { seguidos++; } print("Coches seguidos mientras en DER esperan: " + seguidos + "/" + MAX_SEGUIDOS); } catch (InterruptedException ex) { print("ERROR al dormir al coche " + id); } } public synchronized void pasa_coche_der(int id) {

80 81 82 83 84 85 86 87 88

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

117 118 119

120 121 122 123 124

125 126 127 128 129 130

19

Programaci n Concurrente o
try { if (turno == IZQ || seguidos >= MAX_SEGUIDOS || ocupacion >= CAPACIDAD_PUENTE) { mon_der.wait(); } turno = DER; print("El coche " + id + " esta cruzando el puente (der )"); coches_puente_der++; ocupacion++; print("Ocupacion del puente: " + ocupacion + "/" + CAPACIDAD_PUENTE); cola_coches_der--; //Lo quitamos de la cola if (cola_coches_izq > 0) { seguidos++; } print("Coches seguidos mientras en IZQ esperan: " + seguidos + "/" + MAX_SEGUIDOS); } catch (InterruptedException ex) { print("ERROR al dormir al coche " + id); } } private void print(String s) { System.out.println(s); } } class Coche extends Thread { private private private private Monitor private final int IZQ = 0; final int DER = 1; int sentido; static int n = 0; monitor; int id;

131 132 133 134 135 136 137

138 139 140

141 142 143 144 145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

public Coche(Monitor monitor) { n++; id = n; this.monitor = monitor; } public void run() { try { //Esperamos un tiempo aleatorio sleep((long) ((new Random()).nextInt(10000))); this.sentido = (new Random()).nextInt(2); //genera un entero 0 o 1 if (sentido == IZQ) { alPuentePorLaIzquierda(); } else if (sentido == DER) { alPuentePorLaDerecha(); } else {

177 178 179 180 181

20

Pr ctica 1 - El puente de Puente Duero a


System.out.println("ERROR: En el coche " + id + " se ha generado un sentido no valido."); } } catch (InterruptedException ex) { } } private void alPuentePorLaIzquierda() { try { monitor.llega_coche_izq(id); monitor.pasa_coche_izq(id); sleep(1000); monitor.sale_coche_izq(id); } catch (Exception e) { } } private void alPuentePorLaDerecha() { try { monitor.llega_coche_der(id); monitor.pasa_coche_der(id); sleep(1000); monitor.sale_coche_der(id); } catch (Exception e) { } } } public class PuenteDueroMonitores { static int ncoches = 10; public static void main(String[] args) { Monitor aux_izq = new Monitor(); Monitor aux_der = new Monitor(); Monitor puente = new Monitor(aux_izq, aux_der); Coche aux; for (int i = 0; i < ncoches; i++) { aux = new Coche(puente); aux.start(); } } }

182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

21

Programaci n Concurrente o

1.4
1.4.1

Resoluci n por sem foros en Ada o a


Explicaci n o

Para llevar a cabo la resoluci n de esta pr ctica, mediante sem foros en Ada, lo primero que hemos o a a hecho es idear una forma de abordar el problema: Vamos a tener un turno, que cambiar de un sentido a otro cuando pasen el n mero m ximo a u a de coches seguidos, o bien cuando ya no haya m s coches queriendo pasar en este sentido y s a en el sentido contrario. El turno tomar un valor neutro, es decir, no estar asignado a ning n a a u sentido, cuando, por ejemplo, no haya coches queriendo pasar en ning n sentido. Los sentidos de u circulaci n los notaremos como 0 y 1. o Los sem foros que vamos a utilizar: a SemEntradas: vector de 2 sem foros, uno para los coches que vayan en un sentido y otro a para los del otro. MutexSentidos: vector de 2 sem foros de exclusi n mutua, uno para las variables coa o munes de un sentido y el otro para las del otro sentido. SemPuente: sem foro para que el puente duerma y sea despertado cuando convenga. a MutexPuente: sem foro de exclusi n mutua para las variables del puente, como el a o n mero de coches que circulan actualmente sobre el puente. u La idea es que cuando un coche llegue al puente en sentido i, compruebe si puede pasar ser a as cuando tenga el turno su sentido, no haya m s coches sobre el puente que los que el puente a soporta y, adem s, no hayan pasado el m ximo n mero de coches seguidos en ese sentido. Si a a u puede pasar lo har , en caso contrario esperar en el sem foro SemEntradas(i), hasta que el a a a puente le permita pasar, haciendo signal() sobre dicho sem foro. a Sea nada m s llegar, o cuando el puente le de paso, llegar un momento en el que el coche a a cruzar el puente. Despu s de actualizar el n mero de coches que han cruzado seguidos, los que a e u est n en ese momento sobre el puente, etc, esperaremos un tiempo para simular lo que se tarda en a cruzar el puente. Ahora viene algo importante. Cuando un coche termina de cruzar el puente, tras actualizar correctamente las variables que mencionamos antes, comprueba si el es el ultimo coche de los que est n cruzando en su sentido. Si es as, despertar a la tarea Puente, para que cambie el turno a a seg n sea necesario. u El puente asignar al turno un valor entre 0, 1 y -1, seg n corresponda con la situaci n: el a u o turno ser 0 si antes era 1 y hay coches esperando en sentido 0; y viceversa. Si no se cumplen a ninguna de las dos situaciones, el turno ser neutro, es decir, -1. En el caso de que el nuevo turno a no sea neutro, el puente calcula a cu ntos coches debe dejar paso en el sentido que tiene el nuevo a turno, y les da paso mediante signal() sucesivos a SemEntradas(nuevoTurno).

1.4.2

C digo fuente o
C digo fuente 1.3: Problema de Puente Duero con sem foros en Ada o a

22

Pr ctica 1 - El puente de Puente Duero a

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

with Ada.Text_Io, Ada.Integer_Text_Io, random, semaforos; use Ada.Text_Io, Ada.Integer_Text_Io, random, semaforos; procedure Puenteduero is task type TCoche; task type TPuente; Capacidad: Integer := 5; IndexOfCoche: Integer := 0; Puente: TPuente; NCoches: Integer := 20; Coches: array (Integer range 1..NCoches) of TCoche; NCochesEsperando: array (Integer range 0..1) of Integer; NCochesEnPuente: Integer; SemEntradas, MutexSentidos: array (Integer range 0..1) of TSemaforo; SemPuente, MutexPuente: TSemaforo; Seguidos: Integer; MaxSeguidos: Integer := 10; Turno: Integer;

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

task body TCoche is Sentido: integer; Index: Integer; TurnoCopia: Integer; EnPuente: Integer; EsperandoCopia: Integer; begin --Le asignamos un numero al coche IndexOfCoche := IndexOfCoche + 1; Index := IndexOfCoche; --Generamos aleatoriamente un sentido de circulacion Sentido := Integer(Positive_Random(2) - 1); --Los coches no llegan todos a la vez, sino que llegan uno a uno, puesto que van por un carril. delay(Index * 1.0);

45 46 47 48

Put_Line("> Coche" & IntegerImage(Index) & " llega en sentido" & IntegerImage(Sentido));

49 50 51 52 53

--COMPRUEBA SI PUEDE PASAR Wait(MutexPuente);--Exclusion mutua

23

Programaci n Concurrente o
--Si el turno es neutro nos lo pedimos if Turno = -1 then Turno := Sentido; end if; TurnoCopia := Turno; EnPuente := NCochesEnPuente; Signal(MutexPuente);--Exclusion mutua

54 55 56 57 58 59 60 61 62 63

64 65 66

if not (TurnoCopia = Sentido) or (EnPuente >= Capacidad) or ( Seguidos >= MaxSeguidos) then --O no tenemos el turno, o el puente esta lleno Put_Line("> Coche" & IntegerImage(Index) & " tiene que esperar"); --asi que tenemos que esperar Wait(MutexSentidos(Sentido)); NCochesEsperando(Sentido) := NCochesEsperando(Sentido) + 1; Signal(MutexSentidos(Sentido)); --Esperamos a que nos den el paso Wait(SemEntradas(Sentido)); end if; --En este punto, ya le han permitido cruzar --CRUZA EL PUENTE Wait(MutexSentidos(Sentido));--Exclusion mutua NCochesEsperando(Sentido) := NCochesEsperando(Sentido) - 1; Signal(MutexSentidos(Sentido));--Exclusion mutua --Cruzamos Wait(MutexPuente);--Exclusion mutua NCochesEnPuente := NCochesEnPuente + 1; Seguidos := Seguidos + 1; Signal(MutexPuente);--Exclusion mutua Put_Line("> > Coche" & IntegerImage(Index) & " cruzando el puente en sentido" & IntegerImage(Sentido) & "." & IntegerImage(NCochesEnPuente) & " coches en el puente"); delay(3.0); --SALIMOS DEL PUENTE Put_Line("> > > Coche" & IntegerImage(Index) & " sale del puente en sentido" & IntegerImage(Sentido)); Wait(MutexPuente);--Exclusion mutua NCochesEnPuente := NCochesEnPuente - 1; Signal(MutexPuente);--Exclusion mutua Wait(MutexSentidos(Sentido)); EsperandoCopia := NCochesEsperando(Sentido); Signal(MutexSentidos(Sentido));

67 68 69 70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

89 90 91 92 93 94

95 96 97 98 99 100 101 102 103

24

Pr ctica 1 - El puente de Puente Duero a


--Comprobamos si puede atravesar el puente uno mas (en nuestro mismo sentido) if (Seguidos < MaxSeguidos) and (EsperandoCopia >= 0) then --Podemos dejar pasar a uno mas Signal(SemEntradas(Sentido)); else --Ya ha pasado el maximo en este sentido, o ya no hay mas --Avisamos al puente para que cambie el turno y permita el paso de vehiculos en el otro sentido Signal(SemPuente); end if; end TCoche; task body TPuente is CuantosPasan: Integer; EsperandoCopia: array (Integer range 0..1) of Integer; begin --Espera hasta que alguien le avise, que ocurrira cuando tenga que cambiar el turno Wait(SemPuente); Wait(MutexSentidos(0)); --Exclusion mutua EsperandoCopia(0) := NCochesEsperando(0); Signal(MutexSentidos(0)); --Exclusion mutua Wait(MutexSentidos(1)); --Exclusion mutua EsperandoCopia(1) := NCochesEsperando(1); Signal(MutexSentidos(1)); --Exclusion mutua --Cambia el turno de circulacion Wait(MutexPuente); Seguidos := MaxSeguidos; --Para que no pase ningun coche hasta que el puente termine if Turno = 0 and EsperandoCopia(1)>0 then Turno := 1; else if Turno = 1 and EsperandoCopia(0)>0 then Turno := 0; else Turno := -1; --Turno neutro, porque no hay coches esperando en ningun sentido end if; end if; Put_Line("<<< Puente establece el turno a" & IntegerImage( Turno)); Seguidos := 0; Signal(MutexPuente); --Si no es turno nulo y hay coches esperando en el sentido

104

105 106 107 108 109 110

111 112 113 114 115 116 117 118 119 120 121 122 123

124 125 126 127 128 129 130 131 132 133 134 135 136

137 138 139 140 141 142 143

144 145 146 147

148 149 150 151 152

25

Programaci n Concurrente o
--que ahora tiene el turno, dejaremos que pasen como mucho la capacidad del puente if not (Turno = -1) then if EsperandoCopia(Turno) < Capacidad then CuantosPasan := EsperandoCopia(Turno); else CuantosPasan := Capacidad; end if; --Ahora dejamos que pasen tantos coches como hemos calculado if CuantosPasan > 0 then for I in 0..CuantosPasan loop Signal(SemEntradas(Turno)); end loop; end if; end if; end TPuente;

153

154 155 156 157 158 159 160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

begin IndexOfCoche := 0; Turno := -1; --Turno neutro --Inicializamos los semaforos Init(SemEntradas(0),0); Init(SemEntradas(1),0); Init(SemPuente, 0); Init(MutexPuente, 1); Init(MutexSentidos(0), 1); Init(MutexSentidos(1), 1);

NCochesEnPuente := 0; end Puenteduero;

26

Pr ctica 1 - El puente de Puente Duero a

1.5
1.5.1

Resoluci n por citas en Ada o


Explicaci n o

Para resolver esta practica he decidido tener dos tipos de tareas: sistema y coche. La tarea sistema es la que tendr los sensores y la barrera (controlar el paso de los coches), para ello tiene una a a serie de puntos de entrada: quieroP der: que ser llamado cuando llegue un coche por el lado derecho del puente. a En este punto de entrada, s lo se avisar al sistema de que el coche quiere pasar, pero no le o a dar paso, sino que s lo mantendr el n mero de coches que quieren pasar. a o a u quieroP izq: que ser llamado cuando llegue un coche por el lado izquierdo del puente. a En este punto de entrada, s lo se avisar al sistema de que el coche quiere pasar, pero no le o a dar paso, sino que s lo mantendr el n mero de coches que quieren pasar. a o a u paso der: pasa un coche por la derecha siempre y cuando, no venga ning n otro coche en u sentido contrario, no se supere el n mero m ximo de coches que caben en el puente, y que u a tampoco se supere el n mero de coches que pueden pasar seguidos en el mismo sentido.En u caso contrario se espera hasta que pueda. u paso izq: pasa un coche por la izquierda siempre y cuando, no venga ning n otro coche en sentido contrario, no se supere el n mero m ximo de coches que caben en el puente, y u a que tampoco se supere el n mero de coches que pueden pasar seguidos en el mismo sentido. u En caso contrario se espera hasta que pueda. salgo der: un coche, ya ha atravesado el puente y sale por la derecha. Si es el ultimo coche que pasa en este sentido comprueba si hay coches esperando para cruzar por el lado que sale (derecha), y si los hay les da el turno. salgo izq: un coche, ya ha atravesado el puente y sale por la izquierda. Si es el ultimo coche que pasa en este sentido comprueba si hay coches esperando para cruzar por el lado que sale (izquierda), y si los hay les da el turno. Y para controlar todos estos puntos de entrada, tiene las siguientes variables: Numero m ximo de coches que pueden cruzar el puente a la vez a Max coches en puente:integer Numero m ximo de coches que pueden cruzar seguidos en el mismo sentido a Max coches en sentido:integer Numero de coches que est n cruzando el puente en cada momento a coches total:integer; Numero de coches que cruzan el puente seguidos coches total sentido:integer Numero de coches esperando en la derecha del puente cola der:integer 27

Programaci n Concurrente o Numero de coches esperando en la izquierda del puente cola izq:integer La tarea coche tendr un punto de entrada (inicializar) que har que inicialicemos el a a coche. En este punto de entrada generar aleatoriamente el lado por el que entrar al puente, y a a despu s seg n su sentido llamar un punto de entrada del sistema o a otros. Primero informar al e u a a sistema de su deseo de entrar en el puente, luego pasar , tardar un rato en cruzarlo y nalmente a a saldr por el lado contrario al que entr . a o

1.5.2

C digo fuente o
C digo fuente 1.4: Problema de Puente Duero por citas en ADA o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; use Ada.Numerics.Float_Random; use ada.integer_text_io; use ada.text_io; procedure puente_citas is --Para numeros aleatorios G : Generator; type sentido is (der,izq,vacio); --Lado por el que pueden entrar los coches type lado is (der,izq); --No damos prioridad a ningun lado al inicio vienen:sentido:=vacio; --tarea sistema (controla los sensores y barreras) task type sistema is entry quieroP_der(id:integer); entry quieroP_izq(id:integer); entry paso_der(id:integer); entry paso_izq(id:integer); entry salgo_der(id:integer); entry salgo_izq(id:integer); end sistema; task body sistema is --Numero maximo de coches que pueden cruzar el puente a la vez Max_coches_en_puente:integer:=3; --Numero maximo de coches que pueden cruzar seguidos en el mismo sentido Max_coches_en_sentido:integer:=4; --Numero de coches que estan cruzando el puente en cada momento coches_total:integer:=0;

33 34

35 36

37

28

Pr ctica 1 - El puente de Puente Duero a


--Numero de coches que cruzan el puente seguidos coches_total_sentido:integer:=0; --Numero de coches esperando en la derecha del puente cola_der:integer:=0; --Numero de coches esperando en la izquierda del puente cola_izq:integer:=0; begin loop put_line("--------------------"); Select --Piden paso --Pide paso por la derecha accept quieroP_der(id:integer) do --Hay otro coche que quiere pasar por la derecha cola_der:=cola_der+1; put_line("Coche: " & Integerimage(id) & " quiero pasar por la derecha"); --se puede controlar con llega_izquierdacount ??? end quieroP_der; or --Pide paso por la izquierda accept quieroP_izq(id:integer) do --Hay otro coche que quiere pasar por la izquierda cola_izq:=cola_izq+1; put_line("Coche: " & Integerimage(id) & " quiero pasar por la izquierda"); end quieroP_izq;

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

56 57 58 59

60 61 62 63 64

65 66 67 68 69 70 71 72 73

or

--Pasan --Pasa un coche por la derecha (hacia la izquierda) cuando: --No viene nadie en sentido contrario, no hemos superado el --numero de coches que caben en el puente y tampoco el numero --de coches que pueden pasar seguidos en el mismo sentido when vienen/=izq and coches_total< Max_coches_en_puente and coches_total_sentido<Max_coches_en_sentido => accept paso_der(id:integer) do --Al pasar uno por la der, otorgaos el turno a la derecha vienen:=der; put_line("Coche: " & Integerimage(id) & " pasando izq <- der");

74

75

76

77

78 79 80

81 82 83 84

29

Programaci n Concurrente o
--Como pasa un coche, hay uno menos en la cola derecha cola_der:=cola_der-1; --Incrementamos el numero de coches pasando coches_total:=coches_total+1; --Incrementamos el numero de coches que pasan en ese sentido coches_total_sentido:=coches_total_sentido+1; end paso_der; or --Pasa un coche por la izquierda (hacia la derecha) cuando: --No viene nadie en sentido contrario, no hemos superado el --numero de coches que caben en el puente y tampoco el numero --de coches que pueden pasar seguidos en el mismo sentido when vienen/=der and coches_total< Max_coches_en_puente and coches_total_sentido<Max_coches_en_sentido => accept paso_izq(id:integer) do --Al pasar uno por la izq, otorgaos el turno a la izquierda vienen:=izq; put_line("Coche: " & Integerimage(id) & " pasando izq -> der"); --Como pasa un coche, hay uno menos en la cola izquierda cola_izq:=cola_izq-1; --Incrementamos el numero de coches pasando coches_total:=coches_total+1; --Incrementamos el numero de coches que pasan en ese sentido coches_total_sentido:=coches_total_sentido+1; end paso_izq;

85

86 87 88 89

90 91 92 93 94

95

96

97

98

99 100 101

102 103 104 105 106

107 108 109 110

111 112 113 114 115 116 117 118 119 120

or

--Salen accept salgo_der(id:integer) do put_line("Coche: " & Integerimage(id) & " sale por: der"); --decrementamos el numero de coches cruzando coches_total:=coches_total-1; if coches_total=0 then --comprueba el ultimo coche en salir coches_total_sentido:=0; --Si quedan por la izq le damos el turno if cola_der>0 then vienen:=der;

121 122 123 124

125 126 127 128

30

Pr ctica 1 - El puente de Puente Duero a


--Si no, dejamos el turno para el primero que llegue else vienen:=vacio; end if; end if; end salgo_der; or accept salgo_izq(id:integer) do put_line("Coche: " & Integerimage(id) & " sale por: izq"); --decrementamos el numero de coches cruzando coches_total:=coches_total-1; if coches_total=0 then --comprueba el ultimo coche en salir coches_total_sentido:=0; --Si quedan por la derecha le damos el turno if cola_izq>0 then vienen:=izq; --Si no, dejamos el turno para el primero que llegue else vienen:=vacio; end if; end if; end salgo_izq; or terminate; end select; put_line("Total coches: " & Integerimage(coches_total) ); end loop; put_line("----Fin del sistema----"); end sistema; sist:sistema; --tarea coche task type coche is entry inicializar(identificador: in Integer); end coche; task body coche is rand:float; --numero aleatorio l:lado;--lado por el que llega el coche id:integer;--identificador del coche tiempo_paso_coche:Integer:=4;--tiempo que tarda cada coche en cruzar

129

130 131 132 133 134 135 136 137 138 139

140 141 142 143

144 145

146 147 148

149 150 151 152 153 154 155 156 157 158 159 160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

31

Programaci n Concurrente o

178 179 180 181 182 183 184 185 186

begin --Inicializamos el coche. accept inicializar(identificador: integer) do Reset(G); --genero el numero aleatorio rand := Random(G); --Asigno de manera "aleatoria" el lado por el que entra --el coche en el puente if rand > 0.5 then l:=izq; else l:=der; end if; --Le damos un identificador id:=identificador; end inicializar; --Segun el lado por el que quiere entrar en el puente --llamara a uno u otros puntos de entrada. if l=der then--derecha --que quiero pasar sist.quieroP_der(id); --que paso sist.paso_der(id); elsif l=izq then--izquierda --que quiero pasar sist.quieroP_izq(id); --que paso sist.paso_izq(id); end if; --tardo un rato delay duration(tiempo_paso_coche); --salgo if l=der then --entro derecha --sale por izq sist.salgo_izq(id); elsif l=izq then --entro izquierda --sale por derecha sist.salgo_der(id); end if; end coche; --Numero maximo de coches para iniciar la practica Max_coches_inicio: constant :=15; --Vector de coches, con los que probamos la practica coches_inicio: array (1..Max_coches_inicio) of coche; --Tiempo de separacion entre los coches que llegan al puente

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

32

Pr ctica 1 - El puente de Puente Duero a


T_entre_coches:integer:=1; begin Put_Line("Practica 1 (citas)."); Put_Line("Empiezan a llegar coches....."); New_line; New_line; --Inicializamos unos cuantos coches para probarlo for i in 1..Max_coches_inicio loop coches_inicio(i).inicializar(i); --tiempo de espera entre llegadas de coches delay duration(T_entre_coches); end loop; end puente_citas;

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

33

Programaci n Concurrente o

1.6
1.6.1

Resoluci n por regiones crticas condicionales en Ada o


Explicaci n o

En la resoluci n de la pr ctica mediante regiones rticas condicionales, se ha optado por hacer dos o a tipos de tareas, coche y puente. La tarea puente es la que se encarga de controlar, el n mero de u coches que hay en cada lado, dejando pasar a un n mero determinado de coches, dependiendo de u la capacidad del puente, tambi n se encarga de dar el turno a los coches, y de comprobar que el e n mero seguidos de coches de cada lado no supera el m ximo que puede pasar por el puente. u a En la tarea coche lo primero que se hace es comprobar el sentido del coche, despu s nos e ponemos en la cola, incrementando la cariable cola der. A continuaci n lo que haremos ser o a pasar por el puente, en esta soluci n pasaremos por el puente cuando un coche tenga el turno y o haya coches de ese lado preparados para pasar. De las dem s condiciones, como que no pasen m s a a coches que el n mero m ximo permitido y que no pasen m s coches seguidos de los permitidos, se u a a ocupa la tarea puente. Adem s incrementaremos la variable seguidos der siempre y cuando a haya coches en la cola del lado contrario esperando. Por ultimo en la tarea coche tenemos una regi n llamada region ocupacion que se utiliza o cuando un coche sale del puente por lo que se decrementa la variable ocupacion si esta vale cero, la variable seguidos la inicializamos a cero. Ahora se explicar la tarea puente. La tarea puente se encarga tanto de dar el turno a los a coches como de controlar el ujo de coches tanto de un lado como de otro. En el momento que haya coches en la cola esperando y esa cola tenga el turno habr coches preparados para salir, pero a hay que tener en cuenta que el n mero de coches no debe superar el m ximo permitido, si esto u a sucede, asignaremos a la variable pasar el valor del m ximo n mero de coches que pueden pasar, a u y decrementaremos este valor al n mero de coches que est n esperando en la cola. Cuando esto u a suceda es puente esperar a que pasen todos los coches de ese lado, cuando pase el utimo coche, a el puente asignara el turno al lado contrario y el ciclo continuar hasta que no queden coches por a pasar.

1.6.2

C digo Fuente o
C digo fuente 1.5: Problema de Puente Duero con RCC o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure PuenteDuero_RCC is resource cola_izq(); resource cola_der(); resource pasa_izq(); resource pasa_der(); resource ocupacion(); resource espera(); private cola_coches_der:Integer:=0; cola_coches_izq:Integer:=0; coches_puente_izq:Integer:=0; coches_puente_der:Integer:=0;

34

Pr ctica 1 - El puente de Puente Duero a


ocupacion:Integer:=0; seguidos:Integer:=0;

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

task type coche is --tarea coche, se pone en la cola y espera a pasar. entry init(x:natural;s:natural); end coche; task type puente; type turno is (DER,IZQ,NONE); --variable para el turno task body coche is sentido:natural; id:natural; begin accept init(x:natural;s:natural) do id:=x; sentido:=s; end init; if(sentido = 1) then --coches de la derecha-region cola_der do cola_coches_der := cola_coches_der+1; put_line("El coche con id: "&IntegerImage(id)& "se ha puesto en la cola de la derecha"); end; region pasa_der when coches_puente_der > 0 and ocupacion=0 --pasan cuando hay coches para pasar-an seguidos_der < MAX_SEGUIDOS do put_line("El coche con id: "&IntgerImage(id)& "esta pasando por el puente"); if cola_coches_izq>0 then seguidos_der:=seguidos_der+1; --solo contamos si hay oches esperando-end if; delay(20);--tarda en pasar un tiempo-coches_puente_der:=coches_puente_der-1; end;

else --coches de la izquierda region cola_izq do cola_coches_izq := cola_coches_izq+1; put_line("El coche con id: "&IntegerImage(id)& "se ha puesto en la cola de la izquierda"); end; region pasa_izq when coches_puente_izq > 0 and ocupacion=0 and seguidos_izq < MAX_SEGUIDOS do --cuando hay coches para pasar pasamos-put_line("El coche con id: "&IntgerImage(id)& "esta pasando por el puente"); if cola_coches_der > 0 then seguidos_izq:=seguidos_izq+1;

35

Programaci n Concurrente o
--solo contamos si hay coches esperando-end if; delay(20);--tarda en pasar un tiempo-coches_puente_izq:= coches_puente_izq-1 --el coche sale end; end if; region ocupacion when ocupacion > 0 do ocupacion:= ocupacion-1; if ocupacion = 0 seguidos:=0; region espera do espera:=1; --para indicar al puente que han pasao todos-end; end if; end; end coche; task body puente is turn:turno; pasar:Integer:=0; begin if(Positive_Random(2)=1) then turn := DER; else turn:=IZQ end if; loop if(turn=DER) then --turno para coche de la derecha-region cola_der do --miramos si hay coches en la cola if cola_coches_der>0 then pasar:=cola_coches_der; --hay coches para pasar end if; end; if pasar >0 then region ocupacion then if coches_puente_der > MAX_PUENTE then --si hay mas coches que capacidad-coches_puente_der :=MAX_PUENTE; --pasan el maximo de capacidad-end if; ocupacion = coches_puente_der; --el puente esta ocupado-end; end if; if cola_coches_der > 0 then region cola_der do cola_coches_der:=cola_coches_der-pasar; --hay menos coches en la cola-end; end if; region espera when espera > 0 do --esperando a que salgan todos los coches--

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

36

Pr ctica 1 - El puente de Puente Duero a


espera = 0; end; else --turno de la izquierda-region cola_izq do --miramos si hay coches en la cola if cola_coches_izq>0 then pasar:=cola_coches_izq; --hay coches para pasar end if; end; if pasar >0 then region ocupacion then if coches_puente_izq > MAX_PUENTE then --si hay mas coches que capacidad-coches_puente_izq :=MAX_PUENTE; --pasan el maximo de capacidad-end if; ocupacion = coches_puente_izq; --el puente esta ocupado-end; end if; if cola_coches_izq > 0 then region cola_izq do cola_coches_izq:=cola_coches_izq-pasar; --hay menos coches en la cola-end; end if; region espera when espera > 0 do --esperando a que salgan todos los coches-espera = 0; end; end if; --cambiamos de turno-if(turn = DER) then turn:= IZQ; else turn = DER; end if; end loop; end puente;

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

begin for i in 1 MAX_COCHES loop coches(i).init; --lanzamos los coches-end loop; puente.init; end PuenteDuero_RCC;

37

Programaci n Concurrente o

1.7
1.7.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 25 o 26 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 4 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por monitores en Java: aproximadamente unas 5 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por sem foros en Ada: aproximadamente unas 4 horas, mas lo empleado en realizar la a documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 5 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por regiones crticas condicionales en Ada: aproximadamente unas 4 horas, mas lo em pleado en realizar la documentaci n (aproximadamente una hora). o

1.7.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

1.7.3

Dicultad

Por monitores en Ada: Dicultad de 3 sobre 10. Por monitores en Java: Dicultad de 4 sobre 10. Por sem foros en Ada: Dicultad de 5 sobre 10. a Por citas en Ada: Dicultad de 4 sobre 10. Por regiones crticas condicionales en Ada: Dicultad de 4 sobre 10.

38

Pr ctica 2 - El circuito de karts a

Pr ctica 2 a

El circuito de karts
2.1 Enunciado

En las afueras de Ciudad Real, se ha construido un circuito de karts. Los karts de los que se dispone son de dos clases: de peque a cilindrada para menores de edad, y de una cilindrada mayor para n adultos. El circuito est dotado con Ni karts de cada clase y, adem s de ello, una sala de espera de a a M plazas en la que las personas esperan para entrar al circuito. Las personas (adultos o ni os) que n quieran conducir un kart en el circuito, lo podr n hacer siempre y cuando uno de los karts de su a correspondiente clase est disponible. e Se debe cumplir que: Adultos y ni os no deben conducir en la pista al mismo tiempo. n Las personas competir n con el kart un tiempo aleatorio (seg n el precio que paguen en a u taquilla). Cuando nalice ese tiempo, entrar n en boxes para dejar el kart libre. a Nadie en el circuito debe esperar eternamente para competir. Si llega una persona y est n ocupados todos los karts, aguardar su turno en una sala de a a espera, hasta que uno de los karts quede libre. Si en la sala de espera, no queda sitio, se marchar a su casa sin poder competir. a Dise e un Programa Concurrente que simule el Sistema descrito. El programa ha de estar libre n de bloqueos e inaniciones. Modicaciones (a) Suponga que las personas est n dispuestas a esperar hasta un tiempo de espera m ximo, a a transcurrido el cual, se marchan si no han conseguido un kart. (b) Suponga ahora que los clientes llegan en grupo (todos los componentes de un grupo o son s lo ni os o s lo mayores), y se marchan cuando todos sus componentes han o n o conducido un coche. No necesariamente tienen que conducir todos al mismo tiempo.

39

Programaci n Concurrente o

2.2
2.2.1

Resoluci n por citas en Ada o


Sin modicaciones

Explicaci n o Para la resoluci n de esta pr ctica por Citas en Ada, hemos ideado un dise o basado en dos tipos o a n de tareas: Persona: Representa a los corredores. Se crean tantas tareas de este tipo como personas se desee que tenga la simulaci n. Dentro de ellas, un campo representar el tipo de persona: o a adulto o ni o. n Circuito: Representa al circuito. Tambi n se encarga de la sala de espera. Las tareas e Persona interactuar n con ella durante toda la simulaci n. a o El funcionamiento es sencillo: la tarea Circuito se encarga de atender los distintos tipos de peticiones que puede recibir por parte de las tareas Persona cuando una persona llega al circuito, cuando una persona est en la sala de espera,y cuando una persona termina de correr y a devuelve el coche as como de monitorizar el estado de la simulaci n en todo momento. o Por otro lado, las tareas Persona, tras ser creadas e inicializadas, lo primero que intentar n a ser acceder al circuito (n tese que normalmente s lo pasar n directamente las primeras personas a o o a que lleguen). Si no es posible, pasar n a la sala de espera que consiste en sucesivas peticiones a de entrada al circuito, hasta que la tarea Circuito le de permiso para salir de la sala y coger un kart. Cuando una Persona obtenga el permiso para correr que ocurrir cuando en la pista a est n corredores de su tipo (adulto o ni o) y no hayan pasado el m ximo n mero de personas e n a u seguidas (puesto que en ese caso el turno cambiara) o, por otro lado, cuando el circuito este vaco y el turno no est asignado pasar al circuito, dar unas vueltas y terminar , devolviendo el kart e a a a y march ndose. a C digo fuente o

C digo fuente 2.1: Circuito de karts por Citas en Ada (sin modicaciones) o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

-- Circuito de Karts -- Citas en Ada with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure Karts is -- Tipos de turnos/personas que va a haber type Clase_Persona is (ADULTO, NINO, NONE); -- Tarea Persona task type Persona is entry Init(Ident: in Integer); end Persona;

40

Pr ctica 2 - El circuito de karts a


-- Tarea Circuito task Circuito is entry Llega_Persona(Id: in Integer; Tipo_Persona: in Clase_Persona; Ok: out Boolean); entry Sala_Espera(Id: in Integer; Tipo: in Clase_Persona; Ok: out Boolean); entry Pasar_Adulto(Id: in Integer); entry Pasar_Nino(Id: in Integer); entry Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona); end Circuito; -- Numero de personas a crear en la simulacion NUM_PERSONAS: Integer := 20; -- Vector de las tareas Personas creadas Gentes: array (Integer range 1..NUM_PERSONAS) of Persona; ---------------------------------------------------------------32 33 34 35 36 37

17 18 19

20

21 22 23

24 25 26 27 28 29 30 31

task body Persona is Tipo: Clase_Persona; -- Tipo de persona: adulto/nino Id: Integer; -- Identificador de la persona Ok_Circuito, Ok_Espera: Boolean; -- Variables de permiso de acceso Puedo: Boolean; -- Indica si vamos a poder correr en el circuito begin --Inicializamos la persona, asignandole una identidad accept Init(Ident: in Integer) do Id := Ident; end; --Esperamos un poco para generar los datos aleatorios y entrar delay(Positive_Random(4)*1.0); --Definimos si es adulto o nino if Positive_Random(2) - 1 = 0 then Tipo := ADULTO; else Tipo := NINO; end if; --Cogemos un kart si podemos. En caso contrario intentamos entrar en la sala de espera Circuito.Llega_Persona(Id, Tipo, Ok_Circuito); if Ok_Circuito then --Podemos pasar al circuito directamente Puedo := True; else --No podemos pasar al circuito, por lo que miramos si podemos ir a la sala de espera Puedo := False; Circuito.Sala_Espera(Id, Tipo, Ok_Espera);

38

39 40 41 42 43 44 45

46 47 48 49 50 51 52 53 54

55 56 57 58 59

60 61 62

41

Programaci n Concurrente o
if Ok_Espera then --Podemos entrar a la sala de espera -- La sala de espera consiste en la comprobacion periodica -- del acceso al circuito, hasta que le den permiso. while Puedo = False loop if Tipo = ADULTO then select Circuito.Pasar_Adulto(Id); Puedo := True; or delay(5.0); end select; else select Circuito.Pasar_Nino(Id); Puedo := True; or delay(5.0); end select; end if; end loop; else --La sala esta llena, asi que nos vamos de vuelta a casa Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") no puede entrar a la sala de espera porque esta LLENA. Se marcha"); end if; end if; if Puedo then -- Se nos ha asignado un kart y podemos correr delay(Positive_Random(4)*1.0); --Devolvemos el coche al terminar Circuito.Devuelve_Coche(Id, Tipo); end if; end Persona; ---------------------------------------------------------------100 101 102 103

63 64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

85 86 87

88 89 90 91 92 93 94 95 96 97 98 99

task body Circuito is CAPACIDAD_CIRCUITO: Integer := 10; -- Numero maximo de vehiculos corriendo MAX_SEGUIDOS: Integer := 5; -- Maximo de vehiculos seguidos del mismo tipo Seguidos: Integer := 0; -- Los karts del mismo tipo que van seguidos Coches_En_Pista: Integer := 0; -- Numero de karts actualmente corriendo Turno: Clase_Persona := NONE; -- Turno actual del circuito: adulto/nino -- Personas esperando de cada tipo:

104

105

106

107

108

42

Pr ctica 2 - El circuito de karts a


Esperando: array(Clase_Persona range ADULTO..NINO) of Integer ; CAPACIDAD_SALA_ESPERA: Integer := 20; -- Capacidad maxima de la sala de espera Capacidad_Espera: Integer := CAPACIDAD_SALA_ESPERA; -- Huecos libres procedure Muestra_Estado_Simulacion is begin Put_Line(" << CIRCULANDO:" & IntegerImage(Coches_En_Pista ) & " " & Clase_PersonaImage(Turno) & "S | EN SALA DE ESPERA:" & IntegerImage( Esperando(NINO)) & " ninos y" & IntegerImage(Esperando(ADULTO)) & " adultos >>"); end Muestra_Estado_Simulacion; begin --Inicialmente la sala de espera esta vacia Esperando(NINO) := 0; Esperando(ADULTO) := 0; loop select -- Nada mas llegar una persona, intenta acceder directamente al -- circuito. Con este punto de entrada miramos si es posible, -- en cuyo caso le damos permiso para coger un kart. accept Llega_Persona(Id: in Integer; Tipo_Persona: in Clase_Persona; Ok: out Boolean) do if Seguidos < MAX_SEGUIDOS and (Turno = Tipo_Persona or Turno = NONE) and Coches_En_Pista < CAPACIDAD_CIRCUITO then --Le vamos a dejar pasar Ok := True; Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; --Y nos aseguramos de que tenga el turno su tipo Turno := Tipo_Persona; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo_Persona) & ") llega y entra al circuito directamente. Circulando..."); else --No le dejamos pasar. Le ponemos a la espera Ok := False; end if; end; or -- Cuando a una persona no le dejan entrar al circuito directamente,

109

110

111

112 113 114 115

116 117

118

119 120 121 122 123 124 125 126 127 128 129

130

131 132

133

134 135 136 137 138 139 140 141 142 143 144

145 146 147 148 149 150 151

43

Programaci n Concurrente o
-- utiliza este punto de entrada para intentar acceder a la sala -- de espera, que solo sera posible si no esta llena. accept Sala_Espera(Id: in Integer; Tipo: in Clase_Persona; Ok: out Boolean) do Ok := False; if Capacidad_Espera > 0 then Ok := True; Esperando(Tipo) := Esperando(Tipo) + 1; Capacidad_Espera := Capacidad_Espera - 1; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") entra en la sala de espera"); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; end if; end; or -- Cuando una persona termina de correr, devuelve el kart -- y se marcha. Para ello utiliza este punto de entrada . accept Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona) do Coches_En_Pista := Coches_En_Pista - 1; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo_Persona) & ") termina, devuelve el coche y se va." ); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; if Coches_En_Pista = 0 then --Es el ultimo coche. Cambiamos el turno Seguidos := 0; Put(" >> TURNO: " & Clase_PersonaImage(Turno) & " -> "); if Turno = ADULTO and Esperando(NINO)>0 then Turno := NINO; else if Turno = NINO and Esperando(ADULTO)>0 then Turno := ADULTO; else Turno := NONE; end if; end if; Put_Line(Clase_PersonaImage(Turno)); end if; end; or -- Dejaremos acceder al circuito a la gente que esta esperando -- si es el turno de su tipo, no se ha cumplido el maximo de seguidos, -- y l circuito no esta lleno.

152

153 154

155 156 157 158 159 160 161 162 163 164 165 166 167 168

169

170

171 172 173 174

175 176 177 178 179 180 181

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

197

198

44

Pr ctica 2 - El circuito de karts a


when (Turno = NINO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Nino(Id: in Integer) do Turno := NINO; --Por si era NONE Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(NINO) := Esperando(NINO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("Persona" & IntegerImage(Id) & " (NINO) sale de la sala de espera y entra al circuito . Circulando..."); end; or when (Turno = ADULTO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Adulto(Id: in Integer) do Turno := ADULTO; --Por si era NONE Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(ADULTO) := Esperando(ADULTO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("Persona" & IntegerImage(Id) & " ( ADULTO) sale de la sala de espera y entra al circuito. Circulando..."); end; end select; end loop; end Circuito; ---------------------------------------------------------------227 228 229 230 231 232

199

200 201 202 203 204 205 206 207 208

209 210 211

212 213 214 215 216 217 218 219 220

221 222 223 224 225 226

begin for I in 1..NUM_PERSONAS loop Gentes(I).Init(I); end loop; end Karts;

2.2.2

Modicaci n (a) o

Explicaci n o Para implementar esta modicaci n no tenemos que hacer grandes cambios, en gran medida grao cias a la forma de implementaci n de la sala de espera que hemos realizado en la resoluci n sin o o modicaciones. Tal como veamos, implement bamos la espera mediante sucesivas peticiones, a hasta que la tarea Circuito daba permiso a la Persona para coger un kart. Pues bien, para posibilitar que las personas se marchen transcurrido un tiempo, es decir, que cansen de esperar, smplemente limitamos esas peticiones a un n mero concreto. u 45

Programaci n Concurrente o Si el n mero de peticiones posibles termina, la persona abandona la sala de espera y se marcha u posblemente cabreado por no haber podido correr en la pista. Los cambios para esta modicaci n, tal como hemos dicho, son muy pocos, y en su mayora o pueden apreciarse en la lnea 41 y entre las lneas 62 y 96.

C digo fuente o

C digo fuente 2.2: Circuito de karts por Citas en Ada (modicaci n (a)) o o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

-- Circuito de Karts -- Citas en Ada (mod A) with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure Karts is -- Tipos de turnos/personas que va a haber type Clase_Persona is (ADULTO, NINO, NONE); -- Tarea Persona task type Persona is entry Init(Ident: in Integer); end Persona; -- Tarea Circuito task Circuito is entry Llega_Persona(Id: in Integer; Tipo_Persona: in Clase_Persona; Ok: out Boolean); entry Sala_Espera(Id: in Integer; Tipo: in Clase_Persona; Ok: out Boolean); entry Pasar_Adulto(Id: in Integer); entry Pasar_Nino(Id: in Integer); entry Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona); entry Me_Canse(Id: in Integer; Tipo: in Clase_Persona); end Circuito; -- Numero de personas a crear en la simulacion NUM_PERSONAS: Integer := 20; -- Vector de las tareas Personas creadas Gentes: array (Integer range 1..NUM_PERSONAS) of Persona; ---------------------------------------------------------------------

20

21 22 23

24 25 26 27 28 29 30 31 32

33 34 35 36 37 38

task body Persona is Tipo: Clase_Persona; -- Tipo de persona: adulto/nino Id: Integer; -- Identificador de la persona Ok_Circuito, Ok_Espera: Boolean; -- Variables de permiso de acceso

46

Pr ctica 2 - El circuito de karts a


Puedo: Boolean; -- Indica si vamos a poder correr en el circuito Intentos_Restantes: Integer := 2; begin --Inicializamos la persona, asignandole una identidad accept Init(Ident: in Integer) do Id := Ident; end; --Esperamos un poco para generar los datos aleatorios y entrar delay(Positive_Random(4)*1.0); --Definimos si es adulto o nino if Positive_Random(2) - 1 = 0 then Tipo := ADULTO; else Tipo := NINO; end if; --Cogemos un kart si podemos. En caso contrario intentamos entrar en la sala de espera Circuito.Llega_Persona(Id, Tipo, Ok_Circuito); if Ok_Circuito then --Podemos pasar al circuito directamente Puedo := True; else --No podemos pasar al circuito, por lo que miramos si podemos ir a la sala de espera Puedo := False; Circuito.Sala_Espera(Id, Tipo, Ok_Espera); if Ok_Espera then --Podemos entrar a la sala de espera -- La sala de espera consiste en la comprobacion periodica -- del acceso al circuito, hasta que le den permiso. while Puedo = False and Intentos_Restantes > 0 loop if Tipo = ADULTO then select Circuito.Pasar_Adulto(Id); Puedo := True; or delay(5.0); Intentos_Restantes := Intentos_Restantes - 1; end select; else select Circuito.Pasar_Nino(Id); Puedo := True; or delay(5.0); Intentos_Restantes := Intentos_Restantes - 1; end select; end if; end loop; if Intentos_Restantes = 0 then -- La paciencia se acaba Circuito.Me_Canse(Id, Tipo);

39

40 41 42 43 44 45 46 47 48

49 50 51 52 53 54 55 56 57

58 59 60 61 62

63 64 65 66 67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

47

Programaci n Concurrente o
Puedo := False; end if; else --La sala esta llena, asi que nos vamos de vuelta a casa Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") no puede entrar a la sala de espera porque esta LLENA. Se marcha"); end if; end if; if Puedo then -- Se nos ha asignado un kart y podemos correr delay(Positive_Random(4)*1.0); --Devolvemos el coche al terminar Circuito.Devuelve_Coche(Id, Tipo); end if; end Persona; --------------------------------------------------------------------109 110 111 112

90 91 92

93 94 95

96 97 98 99 100 101 102 103 104 105 106 107 108

task body Circuito is CAPACIDAD_CIRCUITO: Integer := 10; -- Numero maximo de vehiculos corriendo MAX_SEGUIDOS: Integer := 5; -- Maximo de vehiculos seguidos del mismo tipo Seguidos: Integer := 0; -- Los karts del mismo tipo que van seguidos Coches_En_Pista: Integer := 0; -- Numero de karts actualmente corriendo Turno: Clase_Persona := NONE; -- Turno actual del circuito: adulto/nino -- Personas esperando de cada tipo: Esperando: array(Clase_Persona range ADULTO..NINO) of Integer ; CAPACIDAD_SALA_ESPERA: Integer := 20; -- Capacidad maxima de la sala de espera Capacidad_Espera: Integer := CAPACIDAD_SALA_ESPERA; -- Huecos libres procedure Muestra_Estado_Simulacion is begin Put_Line(" << CIRCULANDO:" & IntegerImage(Coches_En_Pista ) & " " & Clase_PersonaImage(Turno) & "S | EN SALA DE ESPERA:" & IntegerImage( Esperando(NINO)) & " ninos y" & IntegerImage(Esperando(ADULTO)) & " adultos >>"); end Muestra_Estado_Simulacion; begin

113

114

115

116

117 118

119

120

121 122 123 124

125 126

127

128 129 130

48

Pr ctica 2 - El circuito de karts a

131 132 133 134 135 136 137 138

--Inicialmente la sala de espera esta vacia Esperando(NINO) := 0; Esperando(ADULTO) := 0; loop select -- Nada mas llegar una persona, intenta acceder directamente al -- circuito. Con este punto de entrada miramos si es posible, -- en cuyo caso le damos permiso para coger un kart. accept Llega_Persona(Id: in Integer; Tipo_Persona: in Clase_Persona; Ok: out Boolean) do if Seguidos < MAX_SEGUIDOS and (Turno = Tipo_Persona or Turno = NONE) and Coches_En_Pista < CAPACIDAD_CIRCUITO then --Le vamos a dejar pasar Ok := True; Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; --Y nos aseguramos de que tenga el turno su tipo Turno := Tipo_Persona; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo_Persona) & ") llega y entra al circuito directamente. Circulando..."); else --No le dejamos pasar. Le ponemos a la espera Ok := False; end if; end; or -- Cuando a una persona no le dejan entrar al circuito directamente, -- utiliza este punto de entrada para intentar acceder a la sala -- de espera, que solo sera posible si no esta llena. accept Sala_Espera(Id: in Integer; Tipo: in Clase_Persona; Ok: out Boolean) do Ok := False; if Capacidad_Espera > 0 then Ok := True; Esperando(Tipo) := Esperando(Tipo) + 1; Capacidad_Espera := Capacidad_Espera - 1; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") entra en la sala de espera"); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; end if; end; or -- Cuando alguien se cansa de esperar utiliza esta entrada, que

139

140 141

142

143 144 145 146 147 148 149 150 151 152 153

154 155 156 157 158 159 160

161

162 163

164 165 166 167 168 169 170 171 172 173 174 175 176 177

49

Programaci n Concurrente o
-- actualiza las variables y muestra la informacion por pantalla accept Me_Canse(Id: in Integer; Tipo: in Clase_Persona) do Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") SE CANSA de esperar y se marcha."); Esperando(Tipo) := Esperando(Tipo) - 1; Capacidad_Espera := Capacidad_Espera + 1; -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; end; or -- Cuando una persona termina de correr, devuelve el kart -- y se marcha. Para ello utiliza este punto de entrada . accept Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona) do Coches_En_Pista := Coches_En_Pista - 1; Put_Line("Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo_Persona) & ") termina, devuelve el coche y se va." ); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; if Coches_En_Pista = 0 then --Es el ultimo coche. Cambiamos el turno Seguidos := 0; Put(" >> TURNO: " & Clase_PersonaImage(Turno) & " -> "); if Turno = ADULTO and Esperando(NINO)>0 then Turno := NINO; else if Turno = NINO and Esperando(ADULTO)>0 then Turno := ADULTO; else Turno := NONE; end if; end if; Put_Line(Clase_PersonaImage(Turno)); end if; end; or -- Dejaremos acceder al circuito a la gente que esta esperando -- si es el turno de su tipo, no se ha cumplido el maximo de seguidos, -- y l circuito no esta lleno. when (Turno = NINO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Nino(Id: in Integer) do Turno := NINO; --Por si era NONE

178

179

180 181 182 183 184 185 186 187 188 189

190

191

192 193 194 195

196 197 198 199 200 201 202

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217

218

219 220

221 222 223

50

Pr ctica 2 - El circuito de karts a


Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(NINO) := Esperando(NINO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("Persona" & IntegerImage(Id) & " (NINO) sale de la sala de espera y entra al circuito . Circulando..."); end; or when (Turno = ADULTO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Adulto(Id: in Integer) do Turno := ADULTO; --Por si era NONE Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(ADULTO) := Esperando(ADULTO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("Persona" & IntegerImage(Id) & " ( ADULTO) sale de la sala de espera y entra al circuito. Circulando..."); end; end select; end loop; end Circuito; --------------------------------------------------------------------248 249 250 251 252 253

224 225 226 227 228 229

230 231 232

233 234 235 236 237 238 239 240 241

242 243 244 245 246 247

begin for I in 1..NUM_PERSONAS loop Gentes(I).Init(I); end loop; end Karts;

2.2.3

Modicaci n (b) o

Explicaci n o Para implementar esta modicaci n hemos tenido que realizar varios cambios. Para empezar la o losofa del funcionamiento del circuito ha cambiado, y ahora hacemos que las personas pasen siempre a trav s de la sala de espera, en la que s lo esperar n si es necesario1 . e o a Tambi n hemos creado una tarea Grupo, que tiene un tipo (adultos o ni os) y un n mero e n u de miembros. Esta tarea gurpo es la encargada de crear a sus miembros, tareas Persona, y no el procedimiento principal, como ocurra antes. El Grupo, lo primero que hace es solicitarle
Este peque o cambio, que aparentemente no es muy importante, solventa unas dicultades que se plantean al mann tener la posibilidad de que las personas, perteneciendo a un grupo, entrasen directamente al circuito. La problem tica a era, principalmente, la reserva de espacio en la sala de espera. Con la implementaci n que hemos hecho este problema o desaparece, manteniendo todos los requisitos del problema.
1

51

Programaci n Concurrente o permiso al Circuito para acceder a la sala de espera se le dar permiso cuando en la sala haya a espacio para todo el grupo. Si el grupo obtiene permiso, el Circuito reserva espacio para todo el grupo, y este accede a la sala (cada tarea Persona individualmente); en caso contrario, el grupo se marcha frustrado de vuelta a casa. Una vez est el grupo en la sala, esperar a que todas a a y cada una de las personas corran. As mismo, las personas que vayan terminando de correr se quedar n esperando a que todos acaben. Cuando todas las personas de un grupo terminen, dicho a grupo la tarea Grupo y todas las tareas Persona del mismo se marchar del circuito. a Las tareas Persona, ahora tienen un atributo que es el numero de grupo. Por lo dem s, a pr cticamente el funcionamiento es el mismo; solo que ahora en vez de marcharse al terminar, a esperar n a que el resto de miembros del grupo terminen, momento en el cual todos se marchar n a a a la vez. Los cambios importantes en el c digo, pueden apreciarse entre las lneas 39 y 94, entre la o 136 y la 147, y entre las lneas 208 y 217. El resto de cambios son meros pre mbulos de los a mencionados. C digo fuente o

C digo fuente 2.3: Circuito de karts por Citas en Ada (modicaci n (b)) o o
1 2 3 4 5 6 7 8 9 10 11 12 13 14

-- Circuito de Karts -- Citas en Ada with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure Karts is -- Tipos de turnos/personas que va a haber type Clase_Persona is (ADULTO, NINO, NONE); -- Tarea Persona task type Persona is entry Init(Ident: in Integer; Grup: in Integer; Clase: in Clase_Persona); entry Fin; end Persona; -- Tarea Grupo task type Grupo is entry Init(Ident: in Integer); entry Persona_Termina; end Grupo; -- Tarea Circuito task Circuito is entry Sala_Espera_Grupo(Id: in Integer; N: in Integer; Tipo: in Clase_Persona; Ok: out Boolean); entry Pasar_Adulto(Id: in Integer; Grupo: in Integer); entry Pasar_Nino(Id: in Integer; Grupo: in Integer); entry Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona; Grupo: in Integer); end Circuito;

15 16 17 18 19 20 21 22 23 24 25 26

27 28 29

30

52

Pr ctica 2 - El circuito de karts a

31 32 33 34 35 36 37

-- Numero de personas a crear en la simulacion NUM_GRUPOS: Integer := 4; -- Vector de las tareas Personas creadas Grupos: array (Integer range 1..NUM_GRUPOS) of Grupo; ---------------------------------------------------------------------

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

task body Grupo is Tipo: Clase_Persona; -- Tipo del grupo: adultos/ninos Id: Integer; -- Identificador del grupo N: Integer; -- Numero de componentes del grupo Ok: Boolean; -- Control de acceso a la sala de espera type TPersona is access Persona; begin accept Init(Ident: in Integer) do Id := Ident; N := Positive_Random(10) + 1; end; --Esperamos un poco delay(Positive_Random(4)*1.0); --Definimos si el grupo es de adultos o ninos if Positive_Random(2) - 1 = 0 then Tipo := ADULTO; else Tipo := NINO; end if; Put_Line("GRUPO" & IntegerImage(Id) & ":" & IntegerImage(N) & " " & Clase_PersonaImage(Tipo) & "S"); -- Comprobamos si todo el grupo va a caber en la sala de espera Circuito.Sala_Espera_Grupo(Id, N, Tipo, Ok); if Ok then -- Vamos a caber todos en la sala de espera, ya tenemos el sitio reservado -- Creamos los componentes del grupo declare Personas: array (Integer range 1..N) of TPersona; begin for I in 1..N loop Personas(I) := new Persona; Personas(I).Init(I, Id, Tipo); end loop; -- Esperamos a que todo el grupo termine for I in 1..N loop accept Persona_Termina; end loop;

64

65 66 67

68 69 70 71 72 73 74 75 76 77 78 79 80 81

53

Programaci n Concurrente o
--En este punto todos los componentes del grupo han terminado Put_Line("[> Grupo" & IntegerImage(Id) & ": Todos sus componentes han terminado. Se marchan juntos"); -- Avisamos a los componentes, que ya acabaron, para irnos todos juntos for I in 1..N loop Personas(I).Fin; end loop; end;

82

83

84 85

86 87 88 89 90 91 92 93 94 95 96

end if; end Grupo; ---------------------------------------------------------------------

97 98 99 100 101 102

task body Persona is Tipo: Clase_Persona; -- Tipo de persona: adulto/nino Id: Integer; -- Identificador de la persona Puedo: Boolean; -- Indica si vamos a poder correr en el circuito Grupo: Integer; -- Grupo al que pertenece begin --Inicializamos la persona, asignandole identidad, grupo y tipo accept Init(Ident: in Integer; Grup: in Integer; Clase: in Clase_Persona) do Grupo := Grup; Id := Ident; Tipo := Clase; end; --Esperamos un poco para generar los datos aleatorios y entrar delay(Positive_Random(4)*1.0); -- En la -- de Puedo while if este caso, con grupos, pasamos al circuito a traves de sala espera, para evitar reservas inconsistentes. := False; Puedo = False loop Tipo = ADULTO then select Circuito.Pasar_Adulto(Id, Grupo); Puedo := True; or delay(5.0); end select; else select

103 104 105 106

107

108 109 110 111 112

113 114 115

116 117 118 119 120 121 122 123 124 125 126 127

54

Pr ctica 2 - El circuito de karts a


Circuito.Pasar_Nino(Id, Grupo); Puedo := True; or delay(5.0); end select; end if; end loop; if Puedo then -- Se nos ha asignado un kart y podemos correr delay(Positive_Random(4)*1.0); --Devolvemos el coche al terminar Circuito.Devuelve_Coche(Id, Tipo, Grupo); -- Avisamos al grupo de que hemos terminado Grupos(Grupo).Persona_Termina; -- Esperamos a que el TODO EL GRUPO termine accept Fin; Put_Line("G" & IntegerImage(Grupo) & " - Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo) & ") se marcha con el resto del grupo."); end if; end Persona; --------------------------------------------------------------------152 153 154 155

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

145 146 147 148 149 150 151

task body Circuito is CAPACIDAD_CIRCUITO: Integer := 10; -- Numero maximo de vehiculos corriendo MAX_SEGUIDOS: Integer := 5; -- Maximo de vehiculos seguidos del mismo tipo Seguidos: Integer := 0; -- Los karts del mismo tipo que van seguidos Coches_En_Pista: Integer := 0; -- Numero de karts actualmente corriendo Turno: Clase_Persona := NONE; -- Turno actual del circuito: adulto/nino -- Personas esperando de cada tipo: Esperando: array(Clase_Persona range ADULTO..NINO) of Integer ; CAPACIDAD_SALA_ESPERA: Integer := 20; -- Capacidad maxima de la sala de espera Capacidad_Espera: Integer := CAPACIDAD_SALA_ESPERA; -- Huecos libres procedure Muestra_Estado_Simulacion is begin Put_Line(" << CIRCULANDO:" & IntegerImage(Coches_En_Pista ) & " " & Clase_PersonaImage(Turno) & "S | EN SALA DE ESPERA:" & IntegerImage( Esperando(NINO)) &

156

157

158

159

160 161

162

163

164 165 166 167

168 169

55

Programaci n Concurrente o
" ninos y" & IntegerImage(Esperando(ADULTO)) & " adultos >>"); end Muestra_Estado_Simulacion; begin --Inicialmente la sala de espera esta vacia Esperando(NINO) := 0; Esperando(ADULTO) := 0; loop select -- Cuando una persona termina de correr, devuelve el kart -- y se marcha. Para ello utiliza este punto de entrada . accept Devuelve_Coche(Id: in Integer; Tipo_Persona: in Clase_Persona; Grupo: in Integer) do Coches_En_Pista := Coches_En_Pista - 1; Put_Line("G" & IntegerImage(Grupo) & " - Persona" & IntegerImage(Id) & " (" & Clase_PersonaImage(Tipo_Persona) & ") termina, devuelve el coche y espera en la calle al resto del grupo"); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; if Coches_En_Pista = 0 then --Es el ultimo coche. Cambiamos el turno Seguidos := 0; Put(" >> TURNO: " & Clase_PersonaImage(Turno) & " -> "); if Turno = ADULTO and Esperando(NINO)>0 then Turno := NINO; else if Turno = NINO and Esperando(ADULTO)>0 then Turno := ADULTO; else Turno := NONE; end if; end if; Put_Line(Clase_PersonaImage(Turno)); end if; end; or accept Sala_Espera_Grupo(Id: in Integer; N: in Integer; Tipo: in Clase_Persona; Ok: out Boolean) do Ok := False; if Capacidad_Espera >= N then Ok := True; Capacidad_Espera := Capacidad_Espera - N; Esperando(Tipo) := Esperando(Tipo) + N; Put_Line("GRUPO" & IntegerImage(Id) & " reserva espacio de espera para" & IntegerImage(N) & " personas"); else

170

171 172 173 174 175 176 177 178 179 180 181

182

183

184 185

186 187

188 189 190 191 192 193 194

195 196 197 198 199 200 201 202 203 204 205 206 207 208

209 210 211 212 213 214

215

56

Pr ctica 2 - El circuito de karts a


Put_Line("GRUPO" & IntegerImage(Id) & " no tiene espacio de espera (son" & IntegerImage(N) & " personas). Se marchan"); end if; end; or -- Dejaremos acceder al circuito a la gente que esta esperando -- si es el turno de su tipo, no se ha cumplido el maximo de seguidos, -- y l circuito no esta lleno. when (Turno = NINO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Nino(Id: in Integer; Grupo: in Integer) do Turno := NINO; --Por si era NONE Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(NINO) := Esperando(NINO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("G" & IntegerImage(Grupo) & " - Persona " & IntegerImage(Id) & " (NINO) sale de la sala de espera y entra al circuito. Circulando ..."); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; end; or when (Turno = ADULTO or Turno = NONE) and Seguidos < MAX_SEGUIDOS and Coches_En_Pista + 1 < CAPACIDAD_CIRCUITO => accept Pasar_Adulto(Id: in Integer; Grupo: in Integer) do Turno := ADULTO; --Por si era NONE Seguidos := Seguidos + 1; Coches_En_Pista := Coches_En_Pista + 1; Esperando(ADULTO) := Esperando(ADULTO) - 1; Capacidad_Espera := Capacidad_Espera + 1; Put_Line("G" & IntegerImage(Grupo) & " - Persona " & IntegerImage(Id) & " (ADULTO) sale de la sala de espera y entra al circuito. Circulando ..."); -- Monitorizamos el estado de la simulacion Muestra_Estado_Simulacion; end; end select; end loop; end Circuito; --------------------------------------------------------------------255

216

217 218 219 220

221

222 223

224 225

226 227 228 229 230 231 232

233 234 235 236 237

238 239

240 241 242 243 244 245 246

247 248 249 250 251 252 253 254

57

Programaci n Concurrente o
begin for I in 1..NUM_GRUPOS loop Grupos(I).Init(I); end loop; end Karts;

256 257 258 259 260

58

Pr ctica 2 - El circuito de karts a

2.3
2.3.1

Resoluci n por Monitores en Java o


Sin modicaciones

Explicaci n o Para la realizaci n de esta pr ctica en monitores java, se ha optado por crear un monitor que es el o a que se encargar de dar paso a los karts tanto de adultos como de ni os, de controlar la capacidad a n de la sala de espera y de controlar la salida de estos. La clase persona es la encargada de crear a las persona, tanto adultos como ni os, se distinguen n por el tipo, que ser una variable con valor aleatorio entre cero y uno, cero para los adultos, y uno a para los ni os. Una vez creadas las personas de cada tipo, adultos y ni os, se comprueba que n n hay espacio en la sala, si es as la persona pasa a la sala con el m todo llega adulto() o e llega ninio() una vez en la sala las personas se ponen a la cola, incrementan la variable cola ninio,cola adulto y la variable capacidad sala. Ya en la sala las personas pasaran a competir, una persona podr competir si, es su turno, es a decir el turno es de los ni os, para que compitan los ni os, o el turno es de los adultos, para que n n compitan los adultos, si no se ha llegado a la capacidad m xima de la pista, y por ultimo una a persona podr competir si no se ha llegado a un n mero m ximo de carreras seguidas de adultos o a u a de ni os. Hay que decir tambi n que existen tres tipos de turno el de los adultos, el de los ni os y n e n turno indenido, que quiere decir que el turno ser para el primero que lo coja. a El n mero de carreras seguidas de adultos o de ni os s lo se contabilizar si existen personas u n o a del tipo contrario esperando para competir, si no hay personas del tipo contrario esperando sera in til contabilizar el n mero de carreras seguidas, ya que si supera el m ximo pero no hay personas u u a del tipo contrario que est n esperando para competir, el programa se quedara en interbloqueo. e Cuando los karts terminan de correr salen del circuito, decrementan la variable capacidad pista y si han llegado al n mero m ximo de carreras seguidas, ponen esta variable a cero y dan el turno a u a las personas contrarias a su tipo,en caso contrario el turno ser indenido, es decir para el primero a que lo coja.

C digo Fuente o

C digo fuente 2.4: Circuito de karts con monitores en Java o


1 2 3 4 5 6 7 8 9 10 11 12 13 14

import java.util.Random; /** * * @author Rodrigo */ class Monitor extends Thread { private final int ADULTOS = 1; private final int NINIOS = 0; private final int NONE = -1; private final int MAX_SEGUIDAS = 5; private final int CAPACIDAD_CIRCUITO = 4;

59

Programaci n Concurrente o
private final int M = 10;

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

private private private private private private private

int int int int int int int

cola_ninios; cola_adultos; capacidad_sala; capacidad_pista; turno; carreras_seguidas_ninio; carreras_seguidas_adulto;

public Monitor() { cola_ninios = 0; cola_adultos = 0; capacidad_pista = 0; turno = NONE; carreras_seguidas_ninio = 0; carreras_seguidas_adulto = 0; capacidad_sala = 0; }

/*el n i o llega a la sala de espera*/ public synchronized void llega_ninio(int id,Persona p) { System.out.println("El n i o con id "+ id+ "ha entrado en la sala"); cola_ninios++; capacidad_sala++; } /*el adulto llega a la sala de espera*/ public synchronized void llega_adulto(int id, Persona p) { cola_adultos++; capacidad_sala++; System.out.println("El adulto con id "+ id+ "ha entrado en la sala"); } /*devuelve la capacidad de la sala*/ public int get_capacidad_sala() { return M; } /*devuelve el n m e r o de personas que hay en la sala*/ public int get_capacidad() { return capacidad_sala; }

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

60

Pr ctica 2 - El circuito de karts a


public synchronized void competir_adulto(int id){ try{ while(turno == NINIOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_adulto >= MAX_SEGUIDAS ) { System.out.println("Adulto con id "+ id+ " esperando"); wait(); } turno = ADULTOS;//damos el turno a los adultos capacidad_sala--; cola_adultos--; System.out.println("El adulto con id: "+id+ " Esta corriendo"); capacidad_pista++; sleep((int)(Math.random()*3000)); if(cola_ninios>0) carreras_seguidas_adulto++; System.out.println("Carreras de adultos seguidas: "+ carreras_seguidas_adulto); }catch(Exception e){} } public synchronized void sale_adulto(int id){ try{ System.out.println("El adulto con id " + id+" e s t saliendo"); capacidad_pista--; System.out.println("Capaidad de pista : " +capacidad_pista); if(capacidad_pista == 0){ if(carreras_seguidas_adulto >= MAX_SEGUIDAS){ carreras_seguidas_adulto = 0; if(cola_ninios>0) turno = NINIOS; /*si hay n i o s esperando les damos * turno a los n i o s y si no * dejamos el turno para el primero * que lo coja. */ else turno = NONE; }else turno = NONE; this.notifyAll(); }

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

}catch(Exception e){} } public synchronized void competir_ninio(int id){ try{ while(turno == ADULTOS || capacidad_pista >= CAPACIDAD_CIRCUITO ||

61

Programaci n Concurrente o
carreras_seguidas_ninio >= MAX_SEGUIDAS) { System.out.println("Esperando n i o con id "+ id); this.wait(); } turno = NINIOS;//le damos el turno a los n i o s capacidad_sala--; capacidad_pista++; sleep((int)(Math.random()*3000)); if(cola_adultos > 0) carreras_seguidas_ninio++; System.out.println("Carreras de n i o s seguidas: "+ carreras_seguidas_ninio); }catch(Exception e){} }

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

public synchronized void sale_ninio(int id){ try{ System.out.println("El n i o con id "+ id+" e s t saliendo"); capacidad_pista--; if(capacidad_pista == 0){ System.out.println("Capacidad de pista es: "+ capacidad_pista); if(carreras_seguidas_ninio >= MAX_SEGUIDAS){ carreras_seguidas_ninio = 0; if(cola_adultos>0) turno = ADULTOS; /*si hay adultos esperando les damos * turno a los adultos y si no * dejamos el turno para el primero * que lo coja. */ else turno = NONE; }else turno = NONE; this.notifyAll(); } }catch(Exception e){} }

class Persona extends Thread{ private int id; private Monitor m; private int tipo; public Persona(int id, Monitor m , int tipo){ this.id = id;

62

Pr ctica 2 - El circuito de karts a


this.m = m; this.tipo = tipo; } public void run(){ try{ if(tipo == 1){ int c = m.get_capacidad(); /*si no hay capacidad se marcha*/ if(c < m.get_capacidad_sala()){ m.llega_ninio(this.id,this); sleep((int)(Math.random()*5000)); m.competir_ninio(this.id); sleep((int)(Math.random()*5000)); m.sale_ninio(this.id); }else System.out.println("La sala e s t ocupada, " + "el ninio con id "+id+ " se marcha"); }else{ int c = m.get_capacidad(); /*Si no hay capacidad se marcha*/ if(c< m.get_capacidad_sala()){ m.llega_adulto(this.id,this); sleep((int)(Math.random()*5000)); m.competir_adulto(this.id); sleep((int)(Math.random()*5000)); m.sale_adulto(this.id); }else System.out.println("La sala e s t ocupada, " + "el adulto con id "+id+ " se marcha"); } }catch(Exception e){} } } public class Main { public static void main(String [] args) { try{ Monitor circuito = new Monitor(); Persona personas; int tipo; for(int i=0;i<100; i++){ tipo = (new Random()).nextInt(2); personas = new Persona(i,circuito,tipo); personas.start(); } }catch(Exception e){} } }

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

197 198 199 200 201 202 203 204 205 206 207 208 209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

63

Programaci n Concurrente o

2.3.2

Modicaci n (a) o

Explicaci n o El problema es el mismo que sin la modicaci n, lo unico que cambia es la condici n de que si o o espera m s de un tiempo especco y la persona no ha entrado en pista esta se marcha, para ello a utilizo la sentencia wait(time). Esto lo que hace es esperar el tiempo indicado en time. Para realizar esto tengo una variable pasa que utlizo para saber si es la primera vez que estoy esperando o no, es decir, esta variable inicialmente tendr el valor de cero, si as la persona entra a a la sala y espera para correr, si esa persona no es despertada antes de que pase el tiempo se despierta sola, y pone la variable pasa a uno por tanto ya no esperar m s y la persona se marchar . En a a a cambio si la persona es llamada saldr del bucle y empezar a competir. Todo esto se hace en la a a funci n competir adulto y competir ninio. o

C digo Fuente o

C digo fuente 2.5: Circuito de karts con monitores en Java (modicaci n (a) o o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

import java.util.Random; /** * * @author Rodrigo */ class Monitor extends Thread { private final int ADULTOS = 1; private final int NINIOS = 0; private final int NONE = -1; private final int MAX_SEGUIDAS = 5; private final int CAPACIDAD_CIRCUITO = 4; private final int M = 1000; private private private private private private private private private int int int int int int int int int cola_ninios; cola_adultos; capacidad_sala; capacidad_pista; turno; carreras_seguidas_ninio; carreras_seguidas_adulto; kars_nino; kars_adulto;

public Monitor() { cola_ninios = 0; cola_adultos = 0; capacidad_pista = 0; turno = NONE; carreras_seguidas_ninio = 0; carreras_seguidas_adulto = 0; capacidad_sala = 0; }

64

Pr ctica 2 - El circuito de karts a

35 36 37 38 39 40 41

/*el n i o llega a la sala de espera*/ public synchronized void llega_ninio(int id,Persona p) { System.out.println("El n i o con id "+ id+ "ha entrado en la sala"); cola_ninios++; capacidad_sala++; } /*el adulto llega a la sala de espera*/ public synchronized void llega_adulto(int id, Persona p) {

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

cola_adultos++; capacidad_sala++; System.out.println("El adulto con id "+ id+ "ha entrado en la sala"); } /*devuelve la capacidad de la sala*/ public int get_capacidad_sala() { return M; } /*devuelve el n m e r o de personas que hay en la sala*/ public int get_capacidad() { return capacidad_sala; }

public synchronized boolean competir_adulto(int id){ boolean sale = false; int pasa = 0; try{ while(turno == NINIOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_adulto >= MAX_SEGUIDAS) { if(pasa == 0){ System.out.println("Adulto con id "+ id+ " esperando"); this.wait(1000); /*Espera un segundo si no es llamado * se va. */ pasa = 1; }else {

65

Programaci n Concurrente o
sale = true; return sale; } } turno = ADULTOS; //damos el turno a los adultos capacidad_sala--; cola_adultos--; System.out.println("El adulto con id: "+id+ " Esta corriendo"); capacidad_pista++; sleep((int)(Math.random()*3000)); if(cola_ninios>0) carreras_seguidas_adulto++; System.out.println("Carreras de adultos seguidas: "+ carreras_seguidas_adulto); }catch(Exception e){} return sale; } public synchronized void sale_adulto(int id){ try{ System.out.println("El adulto con id " + id+" e s t saliendo"); capacidad_pista--; System.out.println("Capaidad de pista : " +capacidad_pista); if(capacidad_pista == 0){ if(carreras_seguidas_adulto >= MAX_SEGUIDAS){ carreras_seguidas_adulto = 0; if(cola_ninios>0) turno = NINIOS; /*si hay n i o s esperando les damos * turno a los n i o s y si no * dejamos el turno para el primero * que lo coja. */ else turno = NONE; }else turno = NONE; this.notifyAll(); }

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

}catch(Exception e){} } public synchronized boolean competir_ninio(int id){ boolean sale = false; int pasa = 0; try{ while(turno == ADULTOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_ninio >= MAX_SEGUIDAS) { if(pasa == 0){ System.out.println(" N i o con id "+

66

Pr ctica 2 - El circuito de karts a


id+ " esperando"); this.wait(1000); /*Espera un segundo si no es llamado * se va. */ pasa = 1; }else { sale = true; return sale; } } turno = NINIOS; //le damos el turno a los n i o s capacidad_sala--; System.out.println("El ninio con id: "+id+" Esta corriendo"); capacidad_pista++; sleep((int)(Math.random()*3000)); if(cola_adultos > 0) carreras_seguidas_ninio++; System.out.println("Carreras de n i o s seguidas: " +carreras_seguidas_ninio); }catch(Exception e){} return sale; }

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

178 179 180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

public synchronized void sale_ninio(int id){ try{ System.out.println("El n i o con id "+ id+" e s t saliendo"); capacidad_pista--; if(capacidad_pista == 0){ System.out.println("Capacidad de pista: "+ capacidad_pista); if(carreras_seguidas_ninio >= MAX_SEGUIDAS){ carreras_seguidas_ninio = 0; if(cola_adultos>0) turno = ADULTOS; /*si hay adultos esperando les damos * turno a los adultos y si no * dejamos el turno para el primero * que lo coja. */ else turno = NONE; }else turno = NONE; this.notifyAll(); } }catch(Exception e){} }

67

Programaci n Concurrente o

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

class Persona extends Thread{ private int id; private Monitor m; private int tipo; public Persona(int id, Monitor m , int tipo){ this.id = id; this.m = m; this.tipo = tipo; } public void run(){ boolean sale = false; try{ if(tipo == 1){ int c = m.get_capacidad(); /*si hay capacidad paso*/ if(c < m.get_capacidad_sala()){ m.llega_ninio(this.id,this); sleep((int)(Math.random()*5000)); sale = m.competir_ninio(this.id); /*si se cansa de esperar se va*/ if (sale== false){ sleep((int)(Math.random()*5000)); m.sale_ninio(this.id); }else System.out.println("El n i o con id"+id+" se " + "ha cansado de esperar"); }else System.out.println("La sala e s t ocupada, " + "el ninio con id "+id+ " se marcha"); }else{ int c = m.get_capacidad(); /*Si hay capacidad paso*/ if(c < m.get_capacidad_sala()){ m.llega_adulto(this.id,this); sleep((int)(Math.random()*1000)); sale = m.competir_adulto(this.id); /*si se cansa de esperar se va*/ if(sale == false){ sleep((int)(Math.random()*1000)); m.sale_adulto(this.id); }else System.out.println("El adulto con id" +id + "se" + "ha cansado de esperar"); }else System.out.println("La sala e s t ocupada, " + "el adulto con id "+id+ " se marcha"); } }catch(Exception e){} }

228 229

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244

245 246

247 248 249 250

68

Pr ctica 2 - El circuito de karts a


} public class Main { public static void main(String [] args) { try{ Monitor circuito = new Monitor(); Persona personas; int tipo; for(int i=0;i<100; i++){ tipo = (new Random()).nextInt(2); personas = new Persona(i,circuito,tipo); personas.start(); } }catch(Exception e){} } }

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

2.3.3

Modicaci n (b) o

Explicaci n o En esta modicaci n ya cambia algo el problema. En un principio se ha creado una tarea m s, o a la tarea grupo. Esta tarea grupo se encargar de crear las personas de cada grupo y asignarlas a un identicador de persona y de grupo. Antes de crear el grupo se mira si hay sitio en la sala de espera, si es as se reserva tantos sitios como n mero de componentes del grupo. Una vez u reservado el sitio el grupo puede entrar. Las personas del grupo entran y no tienen porque correr todos a la vez. Para la reserva del sitio se ha creado una nueva funci n en el monitor que no tenan o nico que hace es incrementarla los problemas anteriores, esta funci n es reservar(), que lo u o variable capacidad sala en el n mero de componentes del grupo. u Las personas podr n correr siempre y cuando la capacidad no supere la m xima, tengan el a a turno (adulto o ni o) y su grupo sea el que pueda correr por la pista, es decir tengan el mismo id n de grupo que el que corre en ese momento. En esta modicaci n no se ha tenido en cuenta un n mero m ximo de carreras seguidas por o u a parte de alumnos o ni os, sino que cuando terminan los adultos, por ejemplo, si hay grupos de n ni os esperando en la sala, se les da el turno, en caso de que no haya ning n grupo de ni os, el n u n turno ser indenido es decir para el primero que lo coja. Lo mismo ocurre en el caso contrario, a si hay un grupo de adultos esperando se les da el turno, en caso contrario el turno ser indenido. a C digo Fuente o

C digo fuente 2.6: Circuito de karts con monitores en Java (modicaci n (b) o o
1 2 3

import java.util.Random; /** *

69

Programaci n Concurrente o
* @author Rodrigo */ class Monitor extends { private final int private final int private final int private final int private final int private final int private private private private private private private private private private private private private int int int int int int int int int int int int int

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

Thread ADULTOS = 1; NINIOS = 0; NONE = -1; MAX_SEGUIDAS = 10; CAPACIDAD_CIRCUITO = 10000; M = 15;

cola_ninios; cola_adultos; capacidad_sala; capacidad_pista; turno; carreras_seguidas_ninio; carreras_seguidas_adulto; kars_nino; kars_adulto; id_grupo; personas_grupo; aux = 0; aux_idgrupo = 0;

public Monitor() { cola_ninios = 0; cola_adultos = 0; capacidad_pista = 0; turno = NONE; carreras_seguidas_ninio = 0; carreras_seguidas_adulto = 0; capacidad_sala = 0; id_grupo = -1; }

43 44 45

public synchronized void llega_ninio(int id,int id_grupo,int ngrupo) { System.out.println("El n i o con id "+ id+ " e id de grupo " + id_grupo+ " ha entrado en la sala"); cola_ninios++; } public synchronized void llega_adulto(int id, int id_grupo, int ngrupo) { cola_adultos++; System.out.println("El adulto con id "+ id+ "e id de grupo "+ id_grupo+" ha entrado en la sala");

46 47 48 49 50

51 52 53 54 55

70

Pr ctica 2 - El circuito de karts a

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

} public int get_capacidad_sala() { return M; } public int get_capacidad() { return capacidad_sala; } /* esta f u n c i n nos s e r v i r para saber si un * componente de un grupo puede pasar a competir o no*/ public int pasa_grupo(int id_grupo) { if(this.id_grupo == id_grupo || this.id_grupo == -1) return 0; else return 1; } public void reservar(int n) { capacidad_sala+=n; }

public synchronized void competir_adulto(int id, int id_grupo, int ngrupo){ try{ while(turno == NINIOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_adulto >= MAX_SEGUIDAS || pasa_grupo(id_grupo)==1) { System.out.println("Adulto con id "+ id+ " e id de grupo: "+id_grupo+" esperando "); wait(); } this.id_grupo = id_grupo; turno = ADULTOS;// le damos el turno a los adultos /*incrementamos la variable personas de grupo * solo cuando pase el primer componente, ya que * todos los componentes llevan la informacion del * numero que componen el grupo */ if(aux == 0) { personas_grupo = ngrupo; aux =1; } capacidad_sala--; cola_adultos--;

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

71

Programaci n Concurrente o
System.out.println("El adulto con id: "+id+ " e id de grupo "+ id_grupo+" esta corriendo"); capacidad_pista++; System.out.println("Carreras de adultos seguidas: "+ carreras_seguidas_adulto); }catch(Exception e){} } public synchronized void sale_adulto(int id, int id_grupo, int ngrupo){ try{ System.out.println("El adulto con id " + id+" e id de grupo "+id_grupo+" e s t saliendo"); capacidad_pista--; personas_grupo--; System.out.println("Capaidad de pista : " +capacidad_pista); if(capacidad_pista == 0){ if(personas_grupo == 0) { if(cola_ninios>0) turno = NINIOS; /*si hay n i o s esperando le damos el turno * a los n i o s , si no el turno sera * para el primero que lo coja */ else turno = NONE; aux = 0; this.id_grupo = -1; this.notifyAll(); } } }catch(Exception e){} } public synchronized void competir_ninio(int id, int id_grupo, int ngrupo){ try{ while(turno == ADULTOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_ninio >= MAX_SEGUIDAS || pasa_grupo(id_grupo)==1) { System.out.println("Esperando n i o con id "+ id +" e" + " id de grupo: "+id_grupo); this.wait(); } this.id_grupo = id_grupo; turno = NINIOS; // le damos el turno a los n i o s /*incrementamos la variable personas de grupo * solo cuando pase el primer componente, ya que * todos los componentes llevan la informacion del * numero que componen el grupo */

111 112 113 114 115 116 117 118 119 120 121 122 123 124

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

155 156 157 158 159 160 161 162 163 164

72

Pr ctica 2 - El circuito de karts a


if(aux == 0){ personas_grupo = ngrupo; aux = 1; } capacidad_sala--; cola_ninios--; System.out.println("El ninio con id: "+id+" e id de grupo" + +id_grupo+" Esta corriendo"); capacidad_pista++; System.out.println("Carreras de n i o s seguidas: " +carreras_seguidas_ninio); }catch(Exception e){} }

165 166 167 168 169 170 171 172

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

public synchronized void sale_ninio(int id, int id_grupo, int ngrupo){ try{ System.out.println("El n i o con id "+ id+" e id de" + "grupo "+id_grupo+" e s t saliendo"); capacidad_pista--; personas_grupo--; if(capacidad_pista == 0){ System.out.println("Capacidad de pista: "+ capacidad_pista); if(personas_grupo == 0){ if (cola_adultos>0) turno = ADULTOS; /*si hay adultos esperando * le damos el turno a los adultos * si no, el turno s e r para el primero * que lo coja */ else turno = NINIOS; aux = 0; this.id_grupo = -1; this.notifyAll(); } } }catch(Exception e){} } } class Persona extends Thread{ private int id; private Monitor m; private int tipo; private int id_grupo; private int ngrupo; public Persona(int id, Monitor m , int tipo, int id_grupo, int ngrupo){ this.id = id;

216 217

73

Programaci n Concurrente o
this.m = m; this.tipo = tipo; this.id_grupo = id_grupo; this.ngrupo = ngrupo; } public void run(){ try{ if(tipo == 1){ m.llega_ninio(id,this.id_grupo,this.ngrupo); sleep((int)(Math.random()*1000)); m.competir_ninio(this.id, this.id_grupo,this. ngrupo); sleep((int)(Math.random()*1000)); m.sale_ninio(this.id, this.id_grupo,this.ngrupo );

218 219 220 221 222 223 224 225 226 227 228 229

230 231

232 233 234 235 236 237

}else{ m.llega_adulto(id,this.id_grupo,this.ngrupo); sleep((int)(Math.random()*1000)); m.competir_adulto(this.id, this.id_grupo,this. ngrupo); sleep((int)(Math.random()*1000)); m.sale_adulto(this.id, this.id_grupo,this. ngrupo); } }catch(Exception e){} } } /*la clase grupo contiene la informaci n del grupo, * id del grupo, n m e r o de personas... * Crea a los componente del grupo y los lanza. */ class Grupo extends Thread { private int ngrupo; private int id_grupo; private Monitor m; private int tipo; private Persona p; public Grupo(int ngrupo, int id, Monitor m,int tipo){ this.ngrupo = ngrupo; this.id_grupo = id; this.m = m; this.tipo = tipo; }

238 239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269

public void run() { if(tipo == 1){ //adultos for(int i=0;i<ngrupo;i++){ this.p = new Persona(i, m, tipo, id_grupo, ngrupo);

74

Pr ctica 2 - El circuito de karts a


p.run(); } }else{ // n i o s for(int i=0;i<ngrupo;i++){ this.p = new Persona(i, m, tipo, id_grupo, ngrupo); p.run(); } } }

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

} public class Main { public static void main(String [] args) { int ids = 0; int ngrupo= 5; int personas_grupo = 5; int libres = 0; try{ Monitor circuito = new Monitor(); int M = circuito.get_capacidad_sala(); int tipo; for(int i=0;i<ngrupo; i++){ tipo = (new Random()).nextInt(2); libres = M-circuito.get_capacidad(); /*si queda sitio para todo el grupo * le creamos y reservamos plazas * si no, salimos. */ if(libres >= personas_grupo){ Grupo g = new Grupo(personas_grupo,i,circuito, tipo); circuito.reservar(ngrupo); g.start(); }else System.out.println("El grupo con id: "+i+" " + "no cabe en la sala, por eso se marcha"); } }catch(Exception e){} } }

310 311 312

313 314 315 316 317 318

75

Programaci n Concurrente o

2.4
2.4.1

Resoluci n por Monitores en Ada o


Explicaci n o

Esta pr ctica ha sido resuelta de dos formas distintas, una con la primera modicaci n del enuna o ciado (apartado a) y otra con la segunda. La principal diferencia entre ellas es que en la primera tenamos una tarea Persona y un monitor que simboliza al circuito Circuito, y en la segunda adem s de estas tenemos tambi n la tarea Grupo que es la que tiene y se encarga de crear las a e tareas personas (no como en el primer apartado que se crean en el procedimiento principal). Para la segunda modicaci n del enunciado, hemos tenido que hacer que un grupo de personas o se vayan todas a la vez, esto ha sido implementado con unos puntos de entrada en la tarea Grupo y en la tarea Persona, al terminar de hacer todo lo que tiene que hacer la tarea persona avisa a su grupo (para ello tiene el identicador de su grupo aparte del suyo) y espera a que este le de permiso para irse denitivamente, y cada grupo espera el aviso de todas las personas que tiene antes de marcharse. Cuando ha recibido todos los avisos, enva a cada una de estas el aviso para marchase todos a la vez. Todas las tareas excepto el Circuito tienen un punto de entrada para inicializarlos, en los que se generar n aleatoriamente el tipo de personas (adulto o ni o), y seg n esto llamar a un a n u a punto de entrada pas ndole unos par metros u otros. a a Los puntos de entrada m s importantes se encuentran en el monitor (Cicuito) y son los a siguientes: procedure LlegaPersona(Id:Integer;Tipo:Turno;Pasar:out Boolean) Avisa a la pista de la llegada de la persona Id, del tipo Tipo, y esta le devolver la variable a Pasar que indicar si puede pasar directamente a la pista o tendr que ir a la sala de espera. a a procedure SalaEspera(Id:Integer;Tipo:Turno;Esperar:out Boolean) Permiten saber a la persona si podr acceder a la sala de espera o esta, est tambi n llena a a a e trav s de la variable Esperar (tiene una capacidad limitada). e procedure SalgoPista(Id:Integer;Tipo:Turno) Indica al sistema que la persona Id del tipo Tipo, sale de la pista. Cuando salga el ultimo participante esta cambiar el turno para que le toque al otro tipo de personas. a entry PasaNino(Id:Integer) Es un punto de entrada para llamar a los ni os que se quedaron esperando en la sala de n espera. entry PasaAdulto(Id:Integer) Es un punto de entrada para llamar a los adultos que se quedaron esperando en la sala de espera. Para tener una idea m s clara de c mo se desarrolla esta pr ctica puede verse el c digo en el a o a o cu l se explican todos los pasos que se dan. a 76

Pr ctica 2 - El circuito de karts a

2.4.2

C digo fuente o

C digo fuente 2.7: Circuito de Karts con monitores en Ada (modicaci n (a)) o o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

--Problema de los karts por tipos protegidos + modificacion a with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; with Ada.Exceptions; use use use use Ada.Numerics.Float_Random; ada.integer_text_io; ada.text_io; Ada.Exceptions;

procedure karts_tiposprotegidos is --para los numeros aleatorios G:Generator; --tipo enumerado para el tipo de persona, y saber por quien esta ocupada la pista type Turno is ( Adulto,Nino,Nadie ); --tarea persona task type persona is entry Inicializacion(Id:integer); end persona; --monitor Circuito protected Circuito is --procedimientos y pto. entradas procedure LlegaPersona(Id:Integer;Tipo:Turno;Pasar:out Boolean); procedure SalaEspera(Id:Integer;Tipo:Turno;Esperar:out Boolean); procedure SalgoPista(Id:Integer;Tipo:Turno); --Para cuando esten en espera las personas entry PasaNino(Id:Integer); entry PasaAdulto(Id:Integer); private --Variables --pista ocupada inicialmente por nadie T:Turno:=Nadie; --numero de karts de cada tipo N:integer:=5; --capacidad sala de espera M:integer:=10; --numero max. de coches seguidos del mismo tipo MaxSeguidos:Integer:=6; --num. coches segudos actualmente

20 21 22 23 24 25 26 27 28 29 30

31

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

77

Programaci n Concurrente o
Seguidos:Integer:=0; --num. coches en pista actualmente (usandose) Coches:Integer:=0; --num. personas en la sala de espera actualmente Espera:Integer:=0; end Circuito; --cuerpo de persona task body persona is --identificador I:Integer; Rand:float; --tipo de persona: adulto o nino Tipo:Turno; --tiempo estan conduciendo un kart Tcorriendo:Integer:=Integer(Random(G)*5.0); --Logicos, para controlar si dan paso a una persona --Paso: para controlar la entrada directa al circuito --Espero: para controlar si entra a la sala de espera Paso ,Espero :Boolean:=False; --tiempo que transcurre hasta que se cansa de esperar Tespera:Integer:=3; Cansado:Boolean:=False; begin accept inicializacion(id:integer) do Reset(G); Rand:=Random(G); I:=Id; if Rand>0.4 then Tipo:=Adulto; else Tipo:=Nino; end if; Reset(G); end inicializacion; --quiere entrar Circuito.Llegapersona(I,Tipo,paso); --Si puedo pasar paso if paso=True then --corremos en un kart delay Duration(Tcorriendo); else --Si no, voy a la sala de espera (si hay sitio) Circuito.SalaEspera(I,Tipo,espero); if espero=True then --espero solo un cierto tiempo antes de marcharme while not Paso and not Cansado loop if Tipo=NINO then select Circuito.PasaNino(I); Paso:=True;--salimos bucle delay Duration(Tcorriendo);

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

78

Pr ctica 2 - El circuito de karts a


or delay Duration(Tespera); Cansado:=True; end select; else select Circuito.PasaAdulto(I); Paso:=True; delay Duration(Tcorriendo); or delay Duration(Tespera); Cansado:=True; end select; end if; end loop; end if; --Si no puedo esperar, me voy, no hay sitio ni en la sala de espera end if; --si hemos conseguido pasar a la pista devolvemos el kart if Paso=True then Circuito.SalgoPista(I,Tipo); end if; if Cansado then Put_Line("<< Me he cansado de esperar, adios.("&Integer Image(I)&")"); end if; end persona; --cuerpo de circuito protected body Circuito is procedure LlegaPersona(Id:Integer;Tipo:Turno;Pasar:out Boolean) is begin if Seguidos<MaxSeguidos and Coches<N and (T=Tipo or T= Nadie) then Put_Line(">> Pasa: "&TurnoImage(Tipo) & "("&integer Image(Id) &"), directo."); Pasar:=True; --La persona puede pasar a la pista --Aumentamos el num. coches en pista y el num.coches que han pasado Seguidos:=Seguidos+1; Coches:=Coches+1; --Es el turno de su tipo T:=Tipo; else --la persona no pasa, debera ir a la sala de espera (si hay sitio) Pasar:=False; end if;

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

122 123 124 125 126 127 128 129 130

131 132 133 134 135 136 137 138

139 140

141

142 143 144

145 146 147 148 149 150

151 152 153

79

Programaci n Concurrente o

154 155 156 157 158 159 160 161 162 163

end LlegaPersona; --una persona sale de la pista procedure SalgoPista(Id:Integer;Tipo:Turno) is begin Coches:=Coches-1; --Si es el ultimo coche en pista, --cede el turno al otro tipo si hay esperando alguno. --Si no hay nadie esperando, el turno es para el primero que lo coja. if Coches=0 then --han terminado los coches en ese sentido Seguidos:=0; T:=Nadie; --Eran adultos if Tipo=Adulto then --hay ninos esperando if PasaNinoCount>0 then Put_Line("********Cambio de turno"); T:=Nino; end if; else if Tipo=Nino then --Eran ninos y hay adultos esperando if PasaAdultoCount>0 then Put_Line("********Cambio de turno"); T:=Adulto; --No end if; end if; end if; end if; Put_Line("<< Gracias, me voy "&TurnoImage(Tipo)& IntegerImage(Id) &")"); end SalgoPista; "(" &

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

189 190 191

192 193 194 195

procedure SalaEspera(Id:Integer;Tipo:Turno;Esperar:out Boolean) is begin --Si hay sitio, espera if Espera<M then Put_Line("-- Espera: "&TurnoImage(tipo) & "("&integer Image(Id) &")"); --hay sitio en la sala de espera Espera:=Espera+1; Esperar:=True; else --La sala de espera esta llena, la persona se va Put_Line("<< No Hay Sitio, Me Piro (" &IntegerImage(Id ) &")"); Esperar:=False; end if;

196 197 198 199 200 201 202

203 204

80

Pr ctica 2 - El circuito de karts a


end SalaEspera; --Llama a un nino que estaba esperando entry PasaNino(Id:Integer) when Seguidos<MaxSeguidos and (T=Nino or T=Nadie) and Coches< N is begin Put_Line(">> Pasa: Nino" & "("&integerImage(Id) &"), estaba esperando"); Coches:=Coches+1; Seguidos:=Seguidos+1; T:=Nino; Espera:=Espera-1; end PasaNino; --Llama a un nino que estaba esperando entry PasaAdulto(Id:Integer) when Seguidos<MaxSeguidos and (T=Adulto or T=Nadie) and Coches<N is begin Put_Line(">> Pasa: Adulto" & "("&integerImage(Id) &"), estaba esperando"); Coches:=Coches+1; Seguidos:=Seguidos+1; T:=Adulto; Espera:=Espera-1; end PasaAdulto; end Circuito;

205 206 207 208 209

210 211

212 213 214 215 216 217 218 219 220

221 222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

--numero de persona iniciales P:Integer:=20; --matriz de personas Mp: array (1..P) of Persona; --tiempo de llegada entre personas Tpersonas:integer:=1; begin Put_Line("Practica2. Tipos protegidos"); New_Line; New_Line; for ii in 1..P loop Mp(Ii).Inicializacion(Ii); --espera entre llegada de personas delay Duration(Tpersonas); end loop; --capturo alguna excepcion exception when error:others => put_line(exception_message(error)); end karts_tiposprotegidos;

81

Programaci n Concurrente o C digo fuente 2.8: Circuito de Karts con monitores en Ada (modicaci n (b)) o o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

--Problema de los karts por tipos protegidos + modificacion b with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; with Ada.Exceptions; use use use use Ada.Numerics.Float_Random; ada.integer_text_io; ada.text_io; Ada.Exceptions;

procedure Karts_Tiposprotegidos_b is --para los numeros aleatorios G:Generator; --numero de grupos iniciales P:Integer:=20; --tiempo de llegada entre grupos Tpersonas:integer:=1; --tipo enumerado para el tipo de persona, y saber por quien esta ocupada la pista type Turno is ( Adulto,Nino,Nadie ); --tarea persona task type persona is entry Inicializacion(Id:Integer;Idp:integer); entry VamonosTodos; end persona; task type Grupo is entry Inicializacion(Id:Integer); entry VamonosGrupo; end Grupo;

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

--matriz de grupos Mg: array (1..P) of Grupo ; --monitor Circuito protected Circuito is --procedimientos y pto. entradas procedure LlegaPersona(Id:Integer;I2:Integer;Tipo:Turno;Pasar :out Boolean); procedure SalaEspera(Id:Integer;I2:Integer;Tipo:Turno;Esperar :out Boolean); procedure SalgoPista(Id:Integer;I2:Integer;Tipo:Turno); --Para cuando esten en espera las personas entry PasaNino(Id:Integer;I2:Integer); entry PasaAdulto(Id:Integer;I2:Integer);

46

47 48 49 50 51

82

Pr ctica 2 - El circuito de karts a


private --Variables --pista ocupada inicialmente por nadie T:Turno:=Nadie; --numero de karts de cada tipo N:integer:=5; --capacidad sala de espera M:integer:=10; --numero max. de coches seguidos del mismo tipo MaxSeguidos:Integer:=6; --num. coches segudos actualmente Seguidos:Integer:=0; --num. coches en pista actualmente (usandose) Coches:Integer:=0; --num. personas en la sala de espera actualmente Espera:Integer:=0; end Circuito; --cuerpo grupo task body Grupo is I:Integer; Npersonas:Integer:=3; --matriz de personas Mp: array (1..Npersonas) of Persona; begin accept Inicializacion(Id:Integer)do I:=Id; end Inicializacion; --inicializamos todas las personas for Ii in 1..Npersonas loop Mp(Ii).Inicializacion(I,Ii); end loop; for Ii in 1..Npersonas loop accept VamonosGrupo; end loop; --Se van todas las personas a la vez for Ii in 1..Npersonas loop Mp(Ii).VamonosTodos; end loop; Put_Line("<<<< El Grupo" & IntegerImage(I)&" Se Marcha");

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

end Grupo; --cuerpo de persona task body persona is --identificadores I,I2:Integer; Rand:float; --tipo de persona: adulto o nino Tipo:Turno; --tiempo estan conduciendo un kart

83

Programaci n Concurrente o
Tcorriendo:Integer:=Integer(Random(G)*5.0); --Logicos, para controlar si dan paso a una persona --Paso: para controlar la entrada directa al circuito --Espero: para controlar si entra a la sala de espera Paso ,Espero :Boolean:=False; --tiempo que transcurre hasta que se cansa de esperar Tespera:Integer:=3; Cansado:Boolean:=False; begin accept inicializacion(id:Integer;Idp:integer) do Reset(G); Rand:=Random(G); I:=Id; I2:=Idp; if Rand>0.4 then Tipo:=Adulto; else Tipo:=Nino; end if; Reset(G); end inicializacion; --quiere entrar Circuito.Llegapersona(I,i2,Tipo,paso); --Si puedo pasar paso if paso=True then --corremos en un kart delay Duration(Tcorriendo); else --Si no, voy a la sala de espera (si hay sitio) Circuito.SalaEspera(I,i2,Tipo,espero); if espero=True then --espero solo un cierto tiempo antes de marcharme while not Paso and not Cansado loop if Tipo=NINO then select Circuito.PasaNino(I,i2); Paso:=True;--salimos bucle delay Duration(Tcorriendo); or delay Duration(Tespera); Cansado:=True; end select; else select Circuito.PasaAdulto(I,i2); Paso:=True; delay Duration(Tcorriendo); or delay Duration(Tespera); Cansado:=True; end select; end if;

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

84

Pr ctica 2 - El circuito de karts a


end loop; end if; --Si no puedo esperar, me voy, no hay sitio ni en la sala de espera end if; --si hemos conseguido pasar a la pista devolvemos el kart if Paso=True then Circuito.SalgoPista(I,I2,Tipo); end if; if Cansado then Put_Line("<< Me he cansado de esperar, adios.("&Integer Image(I)&","&IntegerImage(I2)&")"); end if; Mg(I).VamonosGrupo; accept VamonosTodos; end persona; --cuerpo de circuito protected body Circuito is procedure LlegaPersona(Id:Integer;I2:Integer;Tipo:Turno;Pasar :out Boolean) is begin if Seguidos<MaxSeguidos and Coches<N and (T=Tipo or T= Nadie) then Put_Line(">> Pasa: "&TurnoImage(Tipo) & "("&integer Image(Id)&","&IntegerImage(I2) &"), directo."); Pasar:=True; --La persona puede pasar a la pista --Aumentamos el num. coches en pista y el num.coches que han pasado Seguidos:=Seguidos+1; Coches:=Coches+1; --Es el turno de su tipo T:=Tipo; else --la persona no pasa, debera ir a la sala de espera (si hay sitio) Pasar:=False; end if;

164 165 166

167 168 169 170 171 172 173 174 175

176 177 178 179 180 181 182 183 184 185 186 187

188 189

190

191 192 193

194 195 196 197 198 199

200 201 202 203 204 205 206 207 208 209 210 211 212

end LlegaPersona; --una persona sale de la pista procedure SalgoPista(Id:Integer;I2:Integer;Tipo:Turno) is begin Coches:=Coches-1; --Si es el ultimo coche en pista, --cede el turno al otro tipo si hay esperando alguno. --Si no hay nadie esperando, el turno es para el primero

85

Programaci n Concurrente o
que lo coja. if Coches=0 then --han terminado los coches en ese sentido Seguidos:=0; T:=Nadie; --Eran adultos if Tipo=Adulto then --hay ninos esperando if PasaNinoCount>0 then Put_Line("********Cambio de turno"); T:=Nino; end if; else if Tipo=Nino then --Eran ninos y hay adultos esperando if PasaAdultoCount>0 then Put_Line("********Cambio de turno"); T:=Adulto; --No end if; end if; end if; end if; Put_Line("<< Gracias, me voy "&TurnoImage(Tipo)& IntegerImage(Id)&"," &IntegerImage(I2)&")"); end SalgoPista; "(" &

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

238 239 240

241 242 243 244

procedure SalaEspera(Id:Integer;I2:Integer;Tipo:Turno;Esperar :out Boolean) is begin --Si hay sitio, espera if Espera<M then Put_Line("-- Espera: "&TurnoImage(tipo) & "("&integer Image(Id)&","&IntegerImage(I2) &")"); --hay sitio en la sala de espera Espera:=Espera+1; Esperar:=True; else --La sala de espera esta llena, la persona se va Put_Line("<< No Hay Sitio, Me Piro (" &IntegerImage(Id )&","&IntegerImage(I2)&")"); Esperar:=False; end if; end SalaEspera; --Llama a un nino que estaba esperando entry PasaNino(Id:Integer;I2:integer) when Seguidos<MaxSeguidos and (T=Nino or T=Nadie) and Coches< N is begin Put_Line(">> Pasa: Nino" & "("&integerImage(Id)&","& IntegerImage(I2) &"), estaba esperando"); Coches:=Coches+1;

245 246 247 248 249 250 251

252 253 254 255 256 257 258

259 260

261

86

Pr ctica 2 - El circuito de karts a


Seguidos:=Seguidos+1; T:=Nino; Espera:=Espera-1; end PasaNino; --Llama a un nino que estaba esperando entry PasaAdulto(Id:Integer;I2:integer) when Seguidos<MaxSeguidos and (T=Adulto or T=Nadie) and Coches<N is begin Put_Line(">> Pasa: Adulto" & "("&integerImage(Id)&","& IntegerImage(I2) &"), estaba esperando"); Coches:=Coches+1; Seguidos:=Seguidos+1; T:=Adulto; Espera:=Espera-1; end PasaAdulto; end Circuito;

262 263 264 265 266 267 268 269

270 271

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295

begin Put_Line("Practica2. Tipos protegidos"); New_Line; New_Line; for ii in 1..P loop Mg(Ii).Inicializacion(Ii); --espera entre llegada de grupos delay Duration(Tpersonas); end loop; --capturo alguna excepcion exception when error:others => put_line(exception_message(error)); end Karts_Tiposprotegidos_b;

87

Programaci n Concurrente o

2.5
2.5.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 25 o 26 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 10 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por monitores en Java: aproximadamente unas 9 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 13 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o

2.5.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

2.5.3

Dicultad

Por monitores en Ada: Dicultad de 6 sobre 10. Por monitores en Java: Dicultad de 5 sobre 10. Por citas en Ada: Dicultad de 5 sobre 10.

88

Pr ctica 3 - Cintas transportadoras a

Pr ctica 3 a

Cintas transportadoras
3.1 Enunciado

La nueva terminal de Barajas estar conectada con la actual mediante un par de cintas transportaa doras (una en cada sentido) para hacer menos fatigoso el desplazamiento de los viajeros. Las cintas poseen un mecanismo de control para que est n en marcha solo cuando se necesitan. Esto e se consigue mediante unos sensores a la entrada de cada cinta que detectan la llegada de usuarios. El criterio seguido es: Si una cinta esta parada, debe ponerse en marcha al detectarse la presencia de un usuario. Si una cinta est en marcha, se para si pasa un minuto sin que llegue nadie. a Para implementar este sistema se dispone de: un procedimiento de acceso al sensor procedimientos de manejo del motor que ponen en marcha y detienen la cinta N, respectivamente, y un unico proceso Reloj que cada segundo envia un mensaje a trav s del canal. e Adem s, resulta que si surge alg n problema en el motor de una de las cintas se requiere que a u al menos la otra cinta siga funcionando. Extra: Qu modicaciones habra que realizar en su sistema si ahora queremos que en vez de e tener prejados los sentidos de la marcha, estos sean variables? Se supone que disponemos de sensores en ambos extremos de cada cinta y el requisito adicional sera que las cintas no deben nunca desplazarse en el mismo sentido.

89

Programaci n Concurrente o

3.2
3.2.1

Resoluci n por monitores en Ada o


Explicaci n o

La soluci n que presentamos, directamente del ejercicio con extra incluido, y basada en monitores o en Ada, tiene tres partes principales: Monitor: Se encarga de simular el funcionamiento de los sensores y las cintas transportadoras con las que interaccionan los sensores. Tareas Persona: Accionan los sensores y circulan sobre las cintas. Adem s, tal y como a veremos, son las personas las encargadas de avisar cuando una cinta no funciona momento en el que el t cnico comienza a repararla; esto es as para hacer un poco m s realista la e a simulaci n. o Reloj: Da un aviso por segundo al Monitor. Es necesario para evitar el bloqueo del Monitor en esperas1 , as como para posibilitar la parada de las cintas cuando pasan un minuto2 sin usarse. Las personas se aproximan a las cintas, o bien en sentido izquierda o bien en sentido derecha. Cuando una persona llega a las cintas mira por cual puede entrar, activando los sensores de entrada. Si se encuentra con una cinta estropeada, avisa y el t cnico, que empieza a repararla hemos e modelado esto as para aumentar un poco el realismo de la simulaci n. Cuando una persona o termina de cruzar la cinta, esta se actualiza, pudiendo estropearse (con cierta probabilidad). Si una cinta se estropea, nada ocurrir hasta que una persona intente entrar por ella, se de cuenta de que a no funciona y de un aviso al t cnico. e Las cintas pasan por tres estados: en movimiento hacia la izquierda, en movimiento hacia la derecha, y parada (para ahorrar energa). Cuando una cinta est parada y una persona activa un a sensor, la cinta comienza a moverse en el sentido que lleva la persona, y esta ultima la atraviesa. Sobre la detecci n de salida o Existe la posibilidad de implementar la detecci n de la salida de personas de las cintas mediante o el reloj, prediciendo el tiempo que tarda cada persona en cruzar la cinta3 . Pero, dado que las cintas pueden moverse en ambos sentidos y, por lo tanto, tienen que tener sensores en ambos extremos ya que la gente puede entrar por ambos lados, hemos considerado m s realista detectar a directamente cu ndo sale una persona de la cinta sin considerar el tiempo que tarde en cruzarla. a Adem s, no es posible predecir el tiempo que una persona emplea en cruzar la cinta, puesto que a algunas personas permanecen inm viles mientras la cinta les lleva, y otras pueden caminar sobre o la cinta (tardando mucho menos).

3.2.2

C digo fuente o

1 Si emple semos llamadas a delay() en un procedimiento del monitor, bloquearamos al monitor entero, impidia endo que atienda a otras llamadas. Por eso empleamos una tarea Reloj. 2 En nuestra implementaci n, en lugar de 60 segundos, imaginamos que los minutos son de 10 segundos, para poder o observar el funcionamiento sin perder excesivo tiempo. 3 Esto s lo resulta util si solo existe sensor en un extremo de cada cinta, y eso s lo ocurre en el problema sin extra, o o donde cada cinta se mueve en un s lo sentido. o

90

Pr ctica 3 - Cintas transportadoras a C digo fuente 3.1: Cintas transportadoras con monitores en Ada o
1 2 3 4 5 6 7 8 9

-- Cintas transportadoras -- Monitores en Ada with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure cintasmonitores is type Sentido is (IZQUIERDA, DERECHA, PARADO); --Estados posibles de una cinta task Reloj; task type Persona is entry Init(Identificador: in Integer); end Persona; N: Integer := 20; Personas: array (Integer range 1..N) of Persona; MUCHO: Integer := 100; MINUTO: Integer := 10; -----------------------------------------------------------protected Monitor is procedure ); procedure ); procedure ); procedure ); procedure procedure procedure procedure procedure procedure procedure procedure procedure procedure procedure procedure procedure private Sentido_Cinta_1, Sentido_Cinta_2: Sentido := PARADO; Activa_Sensor_1_Der(Id: in Integer; Ok: out Boolean Activa_Sensor_1_Izq(Id: in Integer; Ok: out Boolean Activa_Sensor_2_Der(Id: in Integer; Ok: out Boolean Activa_Sensor_2_Izq(Id: in Integer; Ok: out Boolean

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

27

28

29

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

Entra_Cinta_1(Id: in Integer); Entra_Cinta_2(Id: in Integer); Sale_Cinta_1(Id: in Integer); Sale_Cinta_2(Id: in Integer); Para_Cinta_1; Para_Cinta_2; Enciende_Cinta_1(S: in Sentido); Enciende_Cinta_2(S: in Sentido); Estropea_Cinta_1; Estropea_Cinta_2; Repara_Cinta_1; Repara_Cinta_2; Tiempo;

91

Programaci n Concurrente o
Personas_En_Cinta_1, Personas_En_Cinta_2: Integer := 0; Contador_Segundos_1, Contador_Segundos_2: Integer := MUCHO; Estropeada_1, Estropeada_2: Boolean := False; Arreglando_1, Arreglando_2: Boolean := False; Tiempo_Reparacion_Restante_1, Tiempo_Reparacion_Restante_2: Integer := 0; end Monitor; protected body Monitor is --Activacion del sensor derecho de la cinta 1 para poder entrar procedure Activa_Sensor_1_Der(Id: in Integer; Ok: out Boolean ) is begin Ok := False; --Podra pasar cuando el sentido de la cinta sea opuesto al extremo del sensor. P.ej: Podras acceder a la cinta por la izquierda cuando la cinta se desplace hacia la derecha if not Estropeada_1 and not (Sentido_Cinta_1 = DERECHA) then Ok := True; if Sentido_Cinta_1 = PARADO then Enciende_Cinta_1(IZQUIERDA); end if; Put_Line("<> Persona" & IntegerImage(Id) & " entra en la cinta 1 por el extremo DERECHO"); Entra_Cinta_1(Id); else if Estropeada_1 and not Arreglando_1 then --Avisamos para que arreglen la cinta Put_Line("[><] Persona" & IntegerImage(Id) & " avisa de que la cinta 1 esta rota. Tecnico reparandola..."); Arreglando_1 := True; Tiempo_Reparacion_Restante_1 := 6; --Tiempo que se tarda en reparar end if; end if; end Activa_Sensor_1_Der; --Activacion del sensor izquierdo de la cinta 1 para poder entrar procedure Activa_Sensor_1_Izq(Id: in Integer; Ok: out Boolean ) is begin Ok := False; if not Estropeada_1 and not (Sentido_Cinta_1 = IZQUIERDA) then Ok := True; if Sentido_Cinta_1 = PARADO then Enciende_Cinta_1(DERECHA); end if;

50 51 52 53 54

55 56 57 58 59 60

61

62 63 64

65

66 67 68 69 70

71 72 73 74 75

76 77

78 79 80 81 82

83

84 85 86

87 88 89 90

92

Pr ctica 3 - Cintas transportadoras a


Put_Line("<> Persona" & IntegerImage(Id) & " entra en la cinta 1 por el extremo IZQUIERDO"); Entra_Cinta_1(Id); else if Estropeada_1 and not Arreglando_1 then --Avisamos para que arreglen la cinta Put_Line("[><] Persona" & IntegerImage(Id) & " avisa de que la cinta 1 esta rota. Tecnico reparandola..."); Arreglando_1 := True; Tiempo_Reparacion_Restante_1 := 6; --Tiempo que se tarda en reparar end if; end if; end Activa_Sensor_1_Izq; --Activacion del sensor derecho de la cinta 2 para poder entrar procedure Activa_Sensor_2_Der(Id: in Integer; Ok: out Boolean ) is begin Ok := False; if not Estropeada_2 and not (Sentido_Cinta_2 = DERECHA) then Ok := True; if Sentido_Cinta_2 = PARADO then Enciende_Cinta_2(IZQUIERDA); end if; Put_Line("<> Persona" & IntegerImage(Id) & " entra en la cinta 2 por el extremo DERECHO"); Entra_Cinta_2(Id); else if Estropeada_2 and not Arreglando_2 then --Avisamos para que arreglen la cinta Put_Line("[><] Persona" & IntegerImage(Id) & " avisa de que la cinta 2 esta rota. Tecnico reparandola..."); Arreglando_2 := True; Tiempo_Reparacion_Restante_2 := 6; --Tiempo que se tarda en reparar end if; end if; end Activa_Sensor_2_Der; --Activacion del sensor izquierdo de la cinta 2 para poder entrar procedure Activa_Sensor_2_Izq(Id: in Integer; Ok: out Boolean ) is begin Ok := False; if not Estropeada_2 and not (Sentido_Cinta_2 = IZQUIERDA) then Ok := True; if Sentido_Cinta_2 = PARADO then Enciende_Cinta_2(DERECHA); end if;

91

92 93 94 95 96

97 98

99 100 101 102 103

104

105 106 107

108 109 110 111 112

113 114 115 116 117

118 119

120 121 122 123 124

125

126 127 128

129 130 131 132

93

Programaci n Concurrente o
Put_Line("<> Persona" & IntegerImage(Id) & " entra en la cinta 2 por el extremo IZQUIERDO"); Entra_Cinta_2(Id); else if Estropeada_2 and not Arreglando_2 then --Avisamos para que arreglen la cinta Put_Line("[><] Persona" & IntegerImage(Id) & " avisa de que la cinta 2 esta rota. Tecnico reparandola..."); Arreglando_2 := True; Tiempo_Reparacion_Restante_2 := 6; --Tiempo que se tarda en reparar end if; end if; end Activa_Sensor_2_Izq; --Una persona entra por la cinta 1, porque el sensor le ha dejado procedure Entra_Cinta_1(Id: in Integer) is begin Personas_En_Cinta_1 := Personas_En_Cinta_1 + 1; Contador_Segundos_1 := MUCHO; --Para ignorar al reloj end Entra_Cinta_1; --Una persona entra por la cinta 2, porque el sensor le ha dejado procedure Entra_Cinta_2(Id: in Integer) is begin Personas_En_Cinta_2 := Personas_En_Cinta_2 + 1; Contador_Segundos_2 := MUCHO; --Para ignorar al reloj end Entra_Cinta_2; --Una persona termina de cruzar la cinta 1 procedure Sale_Cinta_1(Id: in Integer) is begin Personas_En_Cinta_1 := Personas_En_Cinta_1 - 1; Put_Line("<> Persona" & IntegerImage(Id) & " termina de cruzar la cinta 1 y sale por la " & SentidoImage( Sentido_Cinta_1)); if Personas_En_Cinta_1 = 0 then --Es el ultimo en salir Contador_Segundos_1 := 0; --Iniciamos la cuenta --Puede que la cinta se estropee if Positive_Random(3) = 1 then Estropea_Cinta_1; end if; end if; end Sale_Cinta_1; --Una persona termina de cruzar la cinta 2 procedure Sale_Cinta_2(Id: in Integer) is begin Personas_En_Cinta_2 := Personas_En_Cinta_2 - 1; Put_Line("<> Persona" & IntegerImage(Id) & " termina de cruzar la cinta 2 y sale por la " & SentidoImage( Sentido_Cinta_2));

133

134 135 136 137 138

139 140

141 142 143 144 145

146 147 148 149 150 151 152

153 154 155 156 157 158 159 160 161 162 163

164 165 166

167 168 169 170 171 172 173 174 175 176 177

94

Pr ctica 3 - Cintas transportadoras a


if Personas_En_Cinta_2 = 0 then --Es la ultima persona en salir Contador_Segundos_2 := 0; --Iniciamos la cuenta --Puede que la cinta se estropee if Positive_Random(3) = 1 then Estropea_Cinta_2; end if; end if; end Sale_Cinta_2; procedure Para_Cinta_1 is begin Sentido_Cinta_1 := PARADO; end Para_Cinta_1; procedure Para_Cinta_2 is begin Sentido_Cinta_2 := PARADO; end Para_Cinta_2; procedure Enciende_Cinta_1(S: in Sentido) is begin Sentido_Cinta_1 := S; Put_Line("[><] Cinta 1 se enciende, moviendose hacia la "& SentidoImage(S)); end Enciende_Cinta_1; procedure Enciende_Cinta_2(S: in Sentido) is begin Sentido_Cinta_2 := S; Put_Line("[><] Cinta 2 se enciende, moviendose hacia la "& SentidoImage(S)); end Enciende_Cinta_2; procedure Estropea_Cinta_1 is begin Estropeada_1 := True; Put_Line("[><] Cinta (1) ESTROPEADA, pronto alguien se dara cuenta y avisara al tecnico"); Contador_Segundos_1 := MUCHO; end Estropea_Cinta_1; procedure Estropea_Cinta_2 is begin Estropeada_2 := True; Put_Line("[><] Cinta (2) ESTROPEADA, pronto alguien se dara cuenta y avisara al tecnico"); Contador_Segundos_2 := MUCHO; end Estropea_Cinta_2; procedure Repara_Cinta_1 is begin Estropeada_1 := False; Arreglando_1 := False; Para_Cinta_1;

178

179 180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

201 202 203 204 205 206

207 208 209 210 211 212

213 214 215 216 217 218 219

220 221 222 223 224 225 226 227

95

Programaci n Concurrente o
Tiempo_Reparacion_Restante_1 := -1; Put_Line("[><] Cinta (1) reparada"); end Repara_Cinta_1; procedure Repara_Cinta_2 is begin Estropeada_2 := False; Arreglando_2 := False; Para_Cinta_2; Tiempo_Reparacion_Restante_2 := -1; Put_Line("[><] Cinta (2) reparada"); end Repara_Cinta_2; procedure Tiempo is begin Contador_Segundos_1 := Contador_Segundos_1 + 1; Contador_Segundos_2 := Contador_Segundos_2 + 1; Tiempo_Reparacion_Restante_1 := Tiempo_Reparacion_Restante_1 - 1; Tiempo_Reparacion_Restante_2 := Tiempo_Reparacion_Restante_2 - 1; Put_Line("RELOJ:" & IntegerImage(Contador_Segundos_1)&"," &IntegerImage(Contador_Segundos_2) &" | TIEMPO REPARACION RESTANTE:" & IntegerImage( Tiempo_Reparacion_Restante_1)&","&IntegerImage( Tiempo_Reparacion_Restante_2)); --Si algun contador ha llegado a 60 paramos la cinta if Contador_Segundos_1 = MINUTO then Para_Cinta_1; Put_Line("[><] Cinta 1 SE PARA para ahorrar energia"); end if; if Contador_Segundos_2 = MINUTO then Para_Cinta_2; Put_Line("[><] Cinta 2 SE PARA para ahorrar energia"); end if; --Si el tiempo restante de reparacion es 0 la cinta ya esta reparada if Tiempo_Reparacion_Restante_1 = 0 then Repara_Cinta_1; end if; if Tiempo_Reparacion_Restante_2 = 0 then Repara_Cinta_2; end if; end Tiempo; end Monitor; -----------------------------------------------------------task body Reloj is begin loop Monitor.Tiempo; delay(1.0); end loop; end Reloj;

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

246

247

248 249 250 251 252 253 254 255 256 257

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

96

Pr ctica 3 - Cintas transportadoras a

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

-----------------------------------------------------------task body Persona is Id: Integer; S: Sentido; Puedo: Boolean; Extremo: Sentido; --Extremo por el que conseguimos entrar Cinta: Integer; --Cinta por la que conseguimos entrar begin --Le asignamos una identidad accept Init(Identificador: in Integer) do Id := Identificador; end; --Le asignamos un sentido de la marcha delay(Positive_Random(10)*1.0 + 1.0); if Positive_Random(2) = 1 then S := IZQUIERDA; else S := DERECHA; end if; Put_Line("<> Persona" & IntegerImage(Id) & " se aproxima en sentido " & SentidoImage(S)); --Pasamos en dicho sentido Puedo := False; while not Puedo loop delay(Positive_Random(10)*1.0 + 1.0); if S = IZQUIERDA then --Pasaremos por uno de los sensores del extremo derecho Monitor.Activa_Sensor_1_Der(Id, Puedo); Cinta := 1; if not Puedo then Monitor.Activa_Sensor_2_Der(Id, Puedo); Cinta := 2; end if; Extremo := DERECHA; else --Pasaremos por uno de los sensores del extremo izquierdo Monitor.Activa_Sensor_1_Izq(Id, Puedo); Cinta := 1; if not Puedo then Monitor.Activa_Sensor_2_Izq(Id, Puedo); Cinta := 2; end if; Extremo := IZQUIERDA; end if; end loop; --Ya hemos entrado en una cinta, ahora la recorremos delay(5.0); --Al llegar al otro extremo, salimos de la cinta if Cinta = 1 then

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330

97

Programaci n Concurrente o
Monitor.Sale_Cinta_1(Id); else Monitor.Sale_Cinta_2(Id); end if; end Persona;

331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

------------------------------------------------------------

begin for I in 1..N loop Personas(I).Init(I); delay(Positive_Random(10)*1.0); end loop; end CintasMonitores;

98

Pr ctica 3 - Cintas transportadoras a

3.3
3.3.1

Resoluci n por monitores en Java o


Explicaci n o

En esta pr ctica hemos creado (para las dos versiones del problema) las clases Usuario, Sistema, a Reloj, y Reparador todo dentro de un mismo archivo. Cada una de estas, es una tarea independiente que lanzaremos en el m todo principal. e Tal y como est planteado el problema debido al proceso Reloj y Reparador que est n a a siempre enviando informaci n al Sistema, debemos saber que no terminar nunca la ejecuci n o a o del proceso principal (aunque podremos ver c mo si que terminan de llegar personas y c mo las o o cintas entran en modo ahorro), por lo tanto deberemos parar su ejecuci n para nalizarlo. o En la primera versi n de la pr ctica (ya que en la segunda tambi n es as y nos parece m s o a e a realista) hemos decidido, que las cintas controlen el n mero de personas que abandonan la cinta, u esto es debido a que no todas las personas tardar n lo mismo en cruzar la cinta mec nica (unas a a pueden seguir andando, otras quietas, etc). Vamos a comenzar explicando las tareas que no varan con la modicaci n: Reloj, este enva o cada segundo una se al al Sistema para que este, controle el modo ahorro de las cintas (parada n de las cintas cuando nadie las ha utilizado durante un tiempo). La tarea Reparador cada cierto tiempo (un tiempo constante) revisa el Sistema, (y para no quedarse sin trabajo) estropea alguna de las cintas de forma aleatoria, de este modo tiene que repararla, tardando un tiempo variable y aleatorio, una vez arreglado descansa un rato para volver a revisar el Sistema m s tarde. a Si se da el caso de que cuando se rompe una cinta, hay personas en ella, estas seguir n avana zando (a pie) hasta salir de ella, esto se puede observar al ejecutar la pr ctica ya que se indica a cu ndo una persona ha salido andando. De esta forma, si hay gente en la cinta cuando se rompi y a o contin a hasta que se arregla, se le asignar el sentido que tena antes de romperse, para que estas u a personas no vean cambiado su destino, si no hubiese usuario no se le asignara ning n sentido para u as quedar de forma neutra. En la primera versi n las personas tienen un sentido aleatorio hacia el que van y por lo tanto o tienen un cinta ja que coger (la que va en su sentido), por lo tanto si por lo que sea no se pueden montar (est estropeada o llena) esperar n su turno hasta que les toque. Sin embargo en la mode a icaci n las personas prueban una cinta, si en esta no pueden pasar (esta llena, rota o va hacia el o otro sentido) prueban la otra, y si ninguna de las dos va, vuelven a empezar desde el principio a probar las cintas. As por ejemplo una persona si se encuentra una cinta rota (no puede pasar), y la otra est desocupada puede comenzar en esta sin tener que esperar a que se arregle ninguna. a Por ultimo hay alguna otra diferencia en el c digo de la clase Sistema, debido a que en la o modicaci n hemos insertado el concepto de sentido de cada cinta. o

3.3.2

C digo fuente o
C digo fuente 3.2: Cintas transportadoras con monitores en Java o

1 2 3 4 5

import java.util.Random; //clase con el metodo principa class Cintas_java {

99

Programaci n Concurrente o

6 7 8 9 10 11 12

//numero de usuarios de las cintas inicialmente. static final int nclientes = 40; public static void main(String a[]) { System.out.println("Practica 3. Cintas transportadoras ( Monitores Java)\n"); Sistema m = new Sistema(); Reloj r = new Reloj(m); r.start(); Reparador rep = new Reparador(m); rep.start(); //referencia a usuario Usuario u = null; try { for (int ii = 0; ii < nclientes; ii++) { //creamos cada usuario u = new Usuario(m); //ejecutamos usuario u.start(); Thread.sleep(1000); } } catch (Exception e) { System.out.println(e.toString()); } } }//fin cintas_java class Usuario extends Thread { //contantes que indican el sentido private final int DER = 1; private final int IZQ = 0; //tiempo max en cruzar la cinta private final int Tcruzar = 8; //tiempo antes de iniciarse private final int Tinicio = 5; //sentido de la persona private int sentido; //identificador del usuario private final int id; //contador de instancias de usuario private static int n; //referencia a monitor private Sistema m; public Usuario(Sistema m) { this.m = m; id = n; n++; } @Override public void run() {

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

100

Pr ctica 3 - Cintas transportadoras a


try { //tarda un rato en llegar sleep(new Random().nextInt(Tinicio) * 1000); //asignamos un sentido al usuario sentido = (new Random()).nextInt(2); //Segun hacia donde vaya utiliza una cinta transportadora this.usoCinta(sentido); } catch (InterruptedException e) { System.out.println(e.toString()); } } private void usoCinta(int sent) { try { //Obligatoriamente el usuario pasara por su lado //Si la cinta esta ocupada (rota o llena), tendra que esperar hasta que pueda. if (sent == DER) { //llego a la cinta m.llegaCinta_1(id); //paso por la cinta m.pasaCinta_1(id); //tarda un tiempo en cruzar sleep(new Random().nextInt(this.Tcruzar) * 1000); //sale de la cinta m.saleCinta_1(id); } else if (sent == IZQ) { //llego a la cinta m.llegaCinta_2(id); //paso por la cinta m.pasaCinta_2(id); //tarda un tiempo en cruzar sleep(new Random().nextInt(this.Tcruzar) * 1000); //sale de la cinta m.saleCinta_2(id); } } catch (InterruptedException e) { System.out.println(e.toString()); } } }//Fin usuario class Sistema { private final int DER = 1, IZQ = 0, ON = 1, OFF = 0; private final int Maxpersonas_cinta = 5; private int personas_cinta_1 = 0, personas_cinta_2 = 0, personas_esp_1 = 0, personas_esp_2 = 0; private int Tpararse = 3, contador1 = 0, contador2 = 0; private int estado1 = ON, estado2 = ON; private boolean estropeado1 = false, estropeado2 = false; public boolean reposo1 = false, reposo2 = false;

61 62 63 64 65 66

67 68 69 70 71 72 73 74 75 76

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

101

Programaci n Concurrente o
public Sistema() { this.activaCinta_1(); this.activaCinta_2(); } public boolean estaOn1() { return estado1 == ON && !estropeado1; } public boolean estaOn2() { return estado2 == ON && !estropeado2; } private int getMaxpersonas() { return this.Maxpersonas_cinta; } private int getPersonas1() { return this.personas_cinta_1; } private int getPersonas2() { return this.personas_cinta_2; } public synchronized void llegaCinta_1(int id) { System.out.println("Usuario (" + id + ") llega a Cinta 1"); this.activaCinta_1(); this.personas_esp_1++; } public synchronized void pasaCinta_1(int id) { String motivo = ""; try { if (!this.estaOn1()) { motivo += " apagada, cola: " + this.personas_esp_1; } if (!(this.getPersonas1() < this.getMaxpersonas())) { motivo += " llena, ahora: " + this.personas_cinta_1 ; } while (!this.estaOn1() || !(this.getPersonas1() < this. getMaxpersonas())) { System.out.println("Usuario (" + id + ") espera en Cinta 1" + motivo); this.wait(); } //Una persona mas en la cinta this.personas_cinta_1++; System.out.println("Usuario (" + id + ") pasa en Cinta 1, ahora: " + this.personas_cinta_1); //Una persona menos esperando

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

157 158

159 160

161 162 163 164 165

166

102

Pr ctica 3 - Cintas transportadoras a


this.personas_esp_1--; } catch (InterruptedException e) { System.out.println(e.toString()); } } public synchronized void saleCinta_1(int id) { String como = ""; if (estropeado1) { como = " andando (se ha estropeado estando dentro)"; } //Una persona menos en la cinta this.personas_cinta_1--; System.out.println("Usuario (" + id + ") sale en Cinta 1" + como); //Si hay personas esperando en esta cinta, desperamos a una if (this.personas_esp_1 > 0) { this.notify(); } } public synchronized void llegaCinta_2(int id) { System.out.println("Usuario (" + id + ") llega a Cinta 2"); this.activaCinta_2(); this.personas_esp_2++; } public synchronized void pasaCinta_2(int id) { String motivo = ""; try { if (!this.estaOn2()) { motivo += " apagada, cola: " + this.personas_esp_2; } if (!(this.getPersonas2() < this.getMaxpersonas())) { motivo += " llena, ahora: " + this.personas_cinta_2 ; } while (!this.estaOn2() || !(this.getPersonas2() < this. getMaxpersonas())) { System.out.println("Usuario (" + id + ") espera en Cinta 2" + motivo); this.wait(); } //Una persona mas en la cinta this.personas_cinta_2++; //Una persona menos esperando this.personas_esp_2--; System.out.println("Usuario (" + id + ") pasa en Cinta 2, ahora: " + this.personas_cinta_2); } catch (InterruptedException e) { System.out.println(e.toString()); } }

167 168 169 170 171 172 173 174 175 176 177 178 179 180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

202 203

204

205 206 207 208 209 210 211 212

213 214 215 216 217

103

Programaci n Concurrente o
public synchronized void saleCinta_2(int id) { String como = ""; //Una persona menos en la cinta this.personas_cinta_2--; if (estropeado2) { como = " andando (se ha estropeado estando dentro)"; } System.out.println("Usuario (" + id + ") sale en Cinta 2" + como); //Si hay personas esperando en esta cinta, desperamos a una if (this.personas_esp_2 > 0) { this.notify(); } } public synchronized void paraCinta_1() { System.out.println("Cinta 1 Parada"); this.estado1 = OFF; } public synchronized void paraCinta_2() { System.out.println("Cinta 2 Parada"); this.estado2 = OFF; } public synchronized void estropear(int i) { if (i == DER) { estropeado1 = true; } else { estropeado2 = true; } } public synchronized void reparar(int i) { if (i == DER && estropeado1) { System.out.println("************************* Reparada Cinta 1"); estropeado1 = false; } else if (i == IZQ && estropeado2) { System.out.println("************************* Reparada Cinta 2"); estropeado2 = false; } } public synchronized void activaCinta_1() { if (!this.estropeado1) { System.out.println("Cinta 1 Activa"); reposo1 = false; this.estado1 = ON; } } public synchronized void activaCinta_2() { if (!this.estropeado2) {

218 219 220 221 222 223 224 225

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

254 255 256

257 258 259 260 261 262 263 264 265 266 267 268 269 270

104

Pr ctica 3 - Cintas transportadoras a


System.out.println("Cinta 2 Activa"); reposo2 = false; this.estado2 = ON; } } public synchronized void avisoParada() { if (this.getPersonas1() == 0 && !reposo1) { contador1++; if (contador1 >= this.Tpararse) { if (this.estaOn1()) { reposo1 = true; System.out.println(" Sistema ahorro," + " parada de Cinta 1: pasando hay " + personas_cinta_1 + " y en la cola " + personas_esp_1); this.paraCinta_1(); } contador1 = 0; } } else { contador1 = 0; } if (this.getPersonas2() == 0 && !reposo2) { contador2++; if (contador2 >= this.Tpararse) { if (this.estaOn2()) { reposo2 = true; System.out.println(" Sistema ahorro," + " parada de Cinta 2: pasando hay " + personas_cinta_2 + " y en la cola " + personas_esp_1); this.paraCinta_2(); } contador2 = 0; } } else { contador2 = 0; } } }//fin monitor class Reloj extends Thread { private int intervalo = 1; Sistema m = null; public Reloj(Sistema r) { m = r; } @Override public void run() { try {

271 272 273 274 275 276 277 278 279 280 281 282 283

284

285 286 287 288 289 290 291 292 293 294 295 296 297

298

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

105

Programaci n Concurrente o
while (true) { sleep(intervalo * 1000); m.avisoParada(); } } catch (Exception e) { } } } class Reparador extends Thread { private Sistema m = null; private int elegida; public Reparador(Sistema m) { this.m = m; } @Override public void run() { try { while (true) { //Va a revisar las cosas en un periodo fijo sleep(10 * 1000); elegida = new Random().nextInt(2);

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

352 353

354

355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372

//estropea if (elegida == 1 && !m.reposo1 && m.estaOn1()) { System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxx Estropeada Cinta 1"); m.estropear(elegida); } else if (elegida == 0 && !m.reposo2 && m.estaOn2 ()) { System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxx Estropeada Cinta 2"); m.estropear(elegida); } //Tarda un tiempo variable en hacerlo sleep(new Random().nextInt(10) * 1000); //arregla if (elegida == 1) { m.reparar(elegida); } else { m.reparar(elegida); } } } catch (Exception e) { System.out.println(e.toString()); } } }

106

Pr ctica 3 - Cintas transportadoras a C digo fuente 3.3: Cintas transportadoras con monitores en Ada (modicaci n) o o
1 2 3 4 5 6 7 8 9 10 11 12

import java.util.Random; //clase con el metodo principal public class Cintas_java_b { //numero de usuarios de las cintas inicialmente. static final int nclientes = 15; public static void main(String a[]) { System.out.println("Practica 3. Cintas transportadoras ( Monitores Java). Modificacion\n"); Sistema m = new Sistema(); Reloj r = new Reloj(m); r.start(); Reparador rep = new Reparador(m); rep.start(); //referencia a usuario Usuario u = null; try { for (int ii = 0; ii < nclientes; ii++) { //creamos cada usuario u = new Usuario(m); //ejecutamos usuario u.start(); Thread.sleep(new Random().nextInt(5) * 1000); } } catch (Exception e) { System.out.println(e.toString()); } } }//fin cintas_java class Usuario extends Thread { //contantes que indican el sentido private final int DER = 1; private final int IZQ = 0; //tiempo max en cruzar la cinta private final int Tcruzar = 8; //tiempo antes de iniciarse private final int Tinicio = 5; //sentido de la persona private int sentido; //identificador del usuario private final int id; //contador de instancias de usuario private static int n; //referencia a monitor private Sistema m; public Usuario(Sistema m) {

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

107

Programaci n Concurrente o
this.m = m; id = n; n++; } @Override public void run() { //asignamos un sentido al usuario sentido = (new Random()).nextInt(2); //Segun hacia donde vaya utiliza una cinta transportadora this.usoCinta(sentido); } private void usoCinta(int sent) { boolean puedo = false; try { while (!puedo) { //tarda un rato en llegar sleep(new Random().nextInt(Tinicio) * 1000); //llego a la cinta puedo = m.llegaCinta_1(id, sent); if (puedo) { //paso por la cinta m.pasaCinta_1(id); //tarda un tiempo en cruzar sleep(new Random().nextInt(this.Tcruzar) * 1000); //sale de la cinta m.saleCinta_1(id); } else { puedo = m.llegaCinta_2(id, sent); if (puedo) {//paso por la cinta m.pasaCinta_2(id); //tarda un tiempo en cruzar sleep(new Random().nextInt(this.Tcruzar) * 1000); //sale de la cinta m.saleCinta_2(id); } } //Si no ha podido pasar por ninguna cinta, vuelve a intentarlo. //Se puede dar cuando alguna este esrtopeada y la otra, vaya hacia el otro sentido //del que quiere el usuario, asi no tendria porque esperar a que se arregle si por //ejemplo cambia de sentido la otra cinta mientras. if (!puedo) { System.out.println("Usuario (" + id + ") no " + "se por donde pasar...a ver...yo queria : " + ((sent == DER) ? "DER" : "IZQ")); } } } catch (InterruptedException e) { System.out.println(e.toString());

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

80 81 82 83 84 85 86 87

88 89 90 91 92

93

94

95 96 97 98

99 100 101 102 103

108

Pr ctica 3 - Cintas transportadoras a


} } }//Fin usuario class Sistema { private final int DER = 1, IZQ = 0, NINGUNO = -1, ON = 1, OFF = 0; private final int Maxpersonas_cinta = 5; private int personas_cinta_1 = 0, personas_cinta_2 = 0, personas_esp_1 = 0, personas_esp_2 = 0; private int Tpararse = 1, contador1 = 0, contador2 = 0; private int estado1 = ON, estado2 = ON; private boolean estropeado1 = false, estropeado2 = false; public boolean reposo1 = false, reposo2 = false; public int sentido1, sentido2; public Sistema() { sentido1 = NINGUNO; sentido2 = NINGUNO; estado1 = OFF; estado2 = OFF; } public boolean estaOn1() { return estado1 == ON && !estropeado1; } public boolean estaOn2() { return estado2 == ON && !estropeado2; } private int getMaxpersonas() { return this.Maxpersonas_cinta; } private int getPersonas1() { return this.personas_cinta_1; } private int getPersonas2() { return this.personas_cinta_2; } //Nos aseguramos que las cintas tengan sentidos contrarios, o alguna este sin moverse public boolean sentidosDistintos() { return (sentido1 == DER && sentido2 == IZQ) || (sentido1 == IZQ && sentido2 == DER) || (sentido1 == NINGUNO) || (sentido2 == NINGUNO); } public synchronized boolean llegaCinta_1(int id, int lado) {

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

151 152 153 154 155 156 157 158

109

Programaci n Concurrente o
boolean puedo = sentidosDistintos() && lado != sentido2 && (sentido1 == lado || sentido1 == NINGUNO) && !this. estropeado1; if (puedo) { System.out.println("Usuario (" + id + ") llega a Cinta 1, hacia: " + ((lado == DER) ? "DER" : "IZQ")); sentido1 = lado; this.activaCinta_1(); this.personas_esp_1++; } return puedo; } public synchronized void pasaCinta_1(int id) { String motivo = ""; try { //Comprobamos que se puede pasar cada vez que se despierte hasta que pueda while (!this.estaOn1() || !(this.getPersonas1() < this. getMaxpersonas())) { //Por si no puede pasar, buscamos el motivo if (!this.estaOn1()) { motivo += " apagada, cola: " + this. personas_esp_1; } if (!(this.getPersonas1() < this.getMaxpersonas())) { motivo += " llena, pasando: " + this. personas_cinta_1; } System.out.println("Usuario (" + id + ") espera en Cinta 1" + motivo); //Espera this.wait(); } //Una persona mas en la cinta this.personas_cinta_1++; System.out.println("Usuario (" + id + ") pasa en Cinta 1, pasando: " + this.personas_cinta_1); //Una persona menos esperando this.personas_esp_1--; } catch (InterruptedException e) { System.out.println(e.toString()); } } public synchronized void saleCinta_1(int id) { String como = ""; if (estropeado1) { como = " andando (se ha estropeado estando dentro)"; } //Una persona menos en la cinta this.personas_cinta_1--; System.out.println("Usuario (" + id + ") sale en Cinta 1" + como);

159

160 161

162 163 164 165 166 167 168 169 170 171 172 173

174

175 176 177

178 179

180

181 182

183 184 185 186 187 188

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203

110

Pr ctica 3 - Cintas transportadoras a


//Si hay personas esperando en esta cinta, desperamos a una if (this.personas_esp_1 > 0) { this.notify(); } else { //Si es la ultima persona en pasar y no hay nadie esperando if (this.personas_cinta_1 == 0 && this.personas_esp_1 == 0) { sentido2 = NINGUNO; System.out.println("Cinta 1, hacia: NINGUNO"); } } } public synchronized boolean llegaCinta_2(int id, int lado) { boolean puedo = sentidosDistintos() && lado != sentido1 && (sentido2 == lado || sentido2 == NINGUNO) && !this. estropeado2; if (puedo) { System.out.println("Usuario (" + id + ") llega a Cinta 2, hacia: " + ((lado == DER) ? "DER" : "IZQ")); sentido2 = lado; this.activaCinta_2(); this.personas_esp_2++; } return puedo; } public synchronized void pasaCinta_2(int id) { String motivo = ""; try { //Comprobamos que se puede pasar cada vez que se despierte hasta que pueda while (!this.estaOn2() || !(this.getPersonas2() < this. getMaxpersonas())) { //Por si no puede pasar, buscamos el motivo if (!this.estaOn2()) { motivo += " apagada, cola: " + this. personas_esp_2; } if (!(this.getPersonas2() < this.getMaxpersonas())) { motivo += " llena, pasando: " + this. personas_cinta_2; } System.out.println("Usuario (" + id + ") espera en Cinta 2" + motivo); //Espera this.wait(); } //Una persona mas en la cinta this.personas_cinta_2++; //Una persona menos esperando this.personas_esp_2--;

204 205 206 207 208

209

210 211 212 213 214 215 216 217

218 219 220

221 222 223 224 225 226 227 228 229 230 231 232

233

234 235 236

237 238

239

240 241

242 243 244 245 246 247 248

111

Programaci n Concurrente o
System.out.println("Usuario (" + id + ") pasa en Cinta 2, pasando: " + this.personas_cinta_2); } catch (InterruptedException e) { System.out.println(e.toString()); } } public synchronized void saleCinta_2(int id) { String como = ""; //Una persona menos en la cinta this.personas_cinta_2--; if (estropeado2) { como = " andando (se ha estropeado estando dentro)"; } System.out.println("Usuario (" + id + ") sale en Cinta 2" + como); //Si hay personas esperando en esta cinta, desperamos a una if (this.personas_esp_2 > 0) { this.notify(); } else { //Si es la ultima persona en pasar y no hay nadie esperando if (this.personas_cinta_2 == 0 && this.personas_esp_2 == 0) { sentido2 = NINGUNO; System.out.println("Cinta 2, hacia: NINGUNO"); } } } //Para la cinta1 public synchronized void paraCinta_1() { this.estado1 = OFF; sentido1 = NINGUNO; System.out.println("Cinta 1 Parada, hacia: " + hacia1()); } //Para la cinta2 public synchronized void paraCinta_2() { this.estado2 = OFF; sentido2 = NINGUNO; System.out.println("Cinta 2 Parada, hacia: " + hacia2()); } //Estropea la cinta public synchronized if (i == DER) { estropeado1 } else { estropeado2 } } i void estropear(int i) { = true; = true;

249

250 251 252 253 254 255 256 257 258 259 260 261 262

263 264 265 266 267

268

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300

//Repara la cinta i si esta estropeada public synchronized void reparar(int i) {

112

Pr ctica 3 - Cintas transportadoras a


if (i == DER && estropeado1) { System.out.println("************************* Reparada Cinta 1"); estropeado1 = false; } else if (i == IZQ && estropeado2) { System.out.println("************************* Reparada Cinta 2"); estropeado2 = false; } } public String hacia1() { return (sentido1 == DER) ? "DER" : (sentido1 == IZQ) ? "IZQ " : "NINGUNO"; } public String hacia2() { return (sentido2 == DER) ? "DER" : (sentido2 == IZQ) ? "IZQ " : "NINGUNO"; } //El sensor de entrada de la cinta se ha activado public synchronized void activaCinta_1() { if (!this.estropeado1) { System.out.println("Cinta 1 Activa, hacia: " + hacia1() ); reposo1 = false; this.estado1 = ON; } } //El sensor de entrada de la cinta se ha activado public synchronized void activaCinta_2() { if (!this.estropeado2) { System.out.println("Cinta 2 Activa, hacia: " + hacia2() ); reposo2 = false; this.estado2 = ON; } } //Avisos que da el reloj, con ellos controlamos el tiempo que para sin que //entren usuarios a la cinta, para asi poder utilizar el modo ahorro (pararla) public synchronized void avisoParada() { if (this.getPersonas1() == 0 && !reposo1) { contador1++; if (contador1 >= this.Tpararse) { if (this.estaOn1()) { reposo1 = true; System.out.println(" Sistema ahorro, parada de Cinta: 1"); this.paraCinta_1(); //sentido1 = NINGUNO; }

301 302

303 304 305

306 307 308 309 310 311

312 313 314 315

316 317 318 319 320 321

322 323 324 325 326 327 328 329 330

331 332 333 334 335 336

337

338 339 340 341 342 343 344

345 346 347

113

Programaci n Concurrente o
contador1 = 0; } } else { contador1 = 0; } if (this.getPersonas2() == 0 && !reposo2) { contador2++; if (contador2 >= this.Tpararse) { if (this.estaOn2()) { reposo2 = true; System.out.println(" Sistema ahorro, parada de Cinta: 2"); this.paraCinta_2(); } contador2 = 0; } } else { contador2 = 0; } } }//fin monitor class Reloj extends Thread { private int intervalo = 1; Sistema m = null; public Reloj(Sistema r) { m = r; } @Override public void run() { try { //Cada segundo que pasa avisamos al sitema while (true) { sleep(intervalo * 1000); m.avisoParada(); } } catch (Exception e) { } } } class Reparador extends Thread { private Sistema m = null; private int elegida; public Reparador(Sistema m) { this.m = m; } @Override public void run() { try {

348 349 350 351 352 353 354 355 356 357 358

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

114

Pr ctica 3 - Cintas transportadoras a


while (true) { //Va a revisar las cosas cada periodo (fijo) sleep(10 * 1000); elegida = new Random().nextInt(2); //estropea la cinta elegida //para que no parezca que no hace nada y le despidan if (elegida == 1 && !m.reposo1 && m.estaOn1()) { System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxx Estropeada Cinta 1"); m.estropear(elegida); } else if (elegida == 0 && !m.reposo2 && m.estaOn2 ()) { System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxx Estropeada Cinta 2"); m.estropear(elegida); } //Tarda un tiempo variable en hacerlo sleep(new Random().nextInt(10) * 1000); //arregla la cinta estropeada if (elegida == 1) { m.reparar(elegida); } else { m.reparar(elegida); } } } catch (Exception e) { System.out.println(e.toString()); } } }

403 404 405 406 407 408 409 410

411 412

413 414

415

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433

115

Programaci n Concurrente o

3.4
3.4.1

Resoluci n por citas en Ada o


Explicaci n o

Para la realizaci n de la pr ctica de las cintas transportadoras por citas, lo primero que se hace es o a denir las tareas que se van a necesitar. Se tiene dos tareas cintas, dos sensores por cada cinta, ya que las personas querr n entrar por un extremo o por el otro, un array de tareas personas, una tarea a que se encarga de estropear la cinta, una tarea mec nico que se encarga de arreglarla, y una tarea a roloj, que se encargar de enviar ticks de reloj a las cintas y cuando no haya personas pasando por a la cinta durante un minuto estas se parar n. a Una vez denidas todas las tareas se pasa a describir su funcionamiento. Las personas querr n a entrar por un extremo de las cintas, bien, lo primero que se hace es pasar por el sensor, la funci n o del sensor es preguntar a la cinta su estado, si este es el mismo que el sentido por el que quiere pasar la persona, esta pasa sin problemas. Puede pasar que el estado de la cinta sea que este parada, en ese caso la persona tambi n pasar directamente y establecer el estado de la cinta, es decir su e a a sentido, al sentido de la misma persona que ha pasado. Existen dos casos en que lapersona no podr pasar y ser cuando la cinta este en sentido contrario al de la persona o cuando la cinta este a a estropeada. Si la cinta se mueve en sentido contrario la persona probar utilizar la otra cinta, hasta a que pueda pasar por alguna. Cuando una persona pasa por la cinta tarda un tiempo aleatorio en salir. En el caso en que la cinta est estropeada, el t cnico la arregla cuando puede, es decir cuando e e no hay personas en la cinta, una vez arreglada la cinta adquiere el estado de parada. La tarea que estropea las cintas lo hace aleatoriamente,pero s lo una cada vez, ya que no se pueden estropear o las dos al mismo tiempo. Cuando una cinta se estropea el t cnico es llamado para realizar la e reparaci n. o La tarea clock, lo que hace es mandar un tick de reloj cada un segundo, estos son ignorados si en la cinta hay gente, si no hay personas se iran contabilizando, si llega a sesenta ticks (un minuto) sin que ninguna persona haya pasado por la cinta, la cinta se parar , adquiriendo el estado a de parado.

3.4.2

C digo Fuente o
C digo fuente 3.4: Cintas transportadoras con citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure cintas_ada is type Estado_Motor is(Izquierda,Derecha,Parado,Estropeado); type Senti is (IZQ,DER); MAXPERSONAS: constant integer:= 50; --definimos las tareas --tareas cintas task type Cinta is entry init_cinta(id_cinta: in integer); entry Pasa_derecha(id: in integer); entry Pasa_izquierda(id: in integer);

116

Pr ctica 3 - Cintas transportadoras a


entry Parar; entry Dar_estado(estado: out Estado_motor); entry Estropear; end Cinta; cintas: array (1..2) of Cinta; --tareas sensores, dos por cada cinta task Sensor1_Der is entry Pasa_Persona(pasa: out boolean; id: in integer); end Sensor1_Der;

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

task Sensor2_Der is entry Pasa_Persona(pasa: out boolean; id: in integer); end Sensor2_Der; task Sensor1_Izq is entry Pasa_Persona(pasa: out boolean; id: in integer); end Sensor1_Izq;

task Sensor2_Izq is entry Pasa_Persona(pasa: out boolean; id: in integer); end Sensor2_Izq; --tarea tecnico task tecnico is entry reparar(n_cinta: in integer; estado_cinta: out Estado_Motor); end tecnico; --tarea estropear task estropear; --tarea persona task type Persona is entry init_persona(x: integer); end Persona; personas: array (1..MAXPERSONAS) of Persona; --tarea reloj task clock;

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

--Cuerpo de las tareas task body clock is begin loop delay(1.0); --Cada minuto se para si no pasa gente cintas(1).Parar; cintas(2).Parar; end loop;

117

Programaci n Concurrente o
end clock; task body estropear is i:Integer; j:Integer; begin loop delay duration(Positive_Random(10)); i:=Positive_Random(100); if(i>45) then --entonces se estropea j:=Positive_Random(2); if(j=1) then cintas(1).Estropear; else cintas(2).Estropear; end if; end if; end loop; end estropear; task body tecnico is begin loop select accept reparar(n_cinta : in integer; estado_cinta: out Estado_Motor) do put_line("El tecnico esta reparando la cinta " &IntegerImage(n_cinta)); delay duration(Positive_Random(3)); estado_cinta:= Parado; end reparar; end select; end loop; end tecnico; task body Sensor1_Der is pasar : boolean:=false; estado : Estado_Motor; begin loop select accept Pasa_Persona(pasa: out boolean; id: in integer) do cintas(1).Dar_estado(estado); --si la cinta e s t parada o su sentido es derecha --pasamos por ella if (estado = Derecha or estado = Parado) then pasa:=true; cintas(1).Pasa_derecha(id); else pasa:=false; end if; end Pasa_Persona;

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

115 116 117 118 119 120 121 122 123 124

118

Pr ctica 3 - Cintas transportadoras a


end select; end loop; end Sensor1_Der;

125 126 127 128 129 130 131 132 133 134 135 136

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

task body Sensor1_Izq is pasar: boolean:= false; estado:Estado_Motor; begin loop select accept Pasa_Persona(pasa: out boolean; id: in integer) do cintas(1).Dar_estado(estado); --si la cinta e s t parada o su sentido es derecha --pasamos por ella if (estado = Izquierda or estado = Parado) then pasa:=true; cintas(1).Pasa_izquierda(id); else pasa:=false; end if; end Pasa_Persona; end select; end loop; end Sensor1_Izq; task body Sensor2_Der is pasar: boolean:=false; estado: Estado_Motor; begin loop select accept Pasa_Persona(pasa: out boolean; id: in Integer) do cintas(2).Dar_estado(estado); --si la cinta e s t parada o su sentido es derecha --pasamos por ella if (estado = Derecha or estado = Parado) then pasa:=true; cintas(2).Pasa_derecha(id); else pasa:=false; end if; end Pasa_Persona; end select; end loop; end Sensor2_Der;

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

task body Sensor2_Izq is pasar: boolean:=false; estado:Estado_Motor; begin loop select

119

Programaci n Concurrente o
accept Pasa_Persona(pasa: out boolean; id: in integer) do cintas(2).Dar_estado(estado); --si la cinta e s t parada o su sentido es derecha --pasamos por ella if (estado = Izquierda or estado = Parado) then pasa:=true; cintas(2).Pasa_izquierda(id); else pasa:=false; end if; end Pasa_Persona; end select; end loop; end Sensor2_Izq; ------------------------cintas ---------------------------------------task body Cinta is estado_cinta:Estado_Motor:=Parado; n_personas:Integer:=0; contador:integer:=0; ncinta:integer; begin loop select accept init_cinta(id_cinta: in integer) do ncinta:=id_cinta; end init_cinta; or accept Pasa_derecha(id:in integer) do estado_cinta:= Derecha; n_personas:= n_personas+1; put_line("La persona con id"&IntegerImage(id)& " e s t pasando por la derecha en la cinta " &IntegerImage(ncinta)); delay duration(Positive_Random(2)); put_line("La persona con id"&IntegerImage(id)& " e s t saliendo de la cinta " &IntegerImage(ncinta)); n_personas:=n_personas-1; end Pasa_derecha; or accept Pasa_izquierda(id: in integer) do estado_cinta:= Izquierda; n_personas:= n_personas+1; put_line("La persona con id"&IntegerImage(id)& " e s t pasando por la izquierda en la cinta" &IntegerImage(ncinta)); put_line("La persona con id"&IntegerImage(id)& " e s t saliendo de la cinta " &IntegerImage(ncinta)); n_personas:=n_personas-1; end Pasa_izquierda;

179

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

120

Pr ctica 3 - Cintas transportadoras a


or accept Parar do if (n_personas = 0 and estado_cinta /= Parado and estado_cinta /= Estropeado) then if(contador=60) then estado_cinta := Parado; put_line("La cinta" &IntegerImage(ncinta)&" se ha PARADO"); else contador:=contador+1; end if; else contador:=0; end if; end Parar; or accept Dar_estado(estado : out Estado_Motor) do estado:= estado_cinta; end Dar_estado; or accept Estropear do if (estado_cinta /= Estropeado and estado_cinta /= Parado) then put_line("La cinta "&IntegerImage(ncinta) &" esta ESTROPEADA"); estado_cinta := Estropeado; tecnico.reparar(ncinta,estado_cinta); put_line("La cinta "&IntegerImage(ncinta)& " esta REPARADA"& Estado_MotorImage(estado_cinta)); end if; end Estropear; end select; end loop; end Cinta; --------------------------------------------------------------------269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

233 234 235 236 237 238 239

240 241 242 243 244 245 246 247 248 249 250 251 252 253

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

task body Persona is id : integer; pasa: boolean:=false; sentido: integer; n_sensor: integer:=0; --para saber porque sensor voy begin select accept init_persona(x : integer) do id := x; sentido:= Positive_Random(2); end init_persona; end select; if sentido = 1 then --entra por la derecha de la cinta1 put_line("La persona con id : "&IntegerImage(id)& "quiere entrar por la derecha"); while not pasa loop

121

Programaci n Concurrente o
Sensor1_Der.Pasa_Persona(pasa,id); n_sensor:=1; if not pasa then Sensor2_Der.Pasa_Persona(pasa,id); n_sensor:=2; end if; end loop; else put_line("La persona con id : "&IntegerImage(id)& "quiere entrar por la izquierda"); while not pasa loop Sensor1_Izq.Pasa_Persona(pasa,id); n_sensor:=1; if not pasa then Sensor2_Izq.Pasa_Persona(pasa,id); n_sensor:=2; end if; end loop; end if; end Persona; begin cintas(1).init_cinta(1); cintas(2).init_cinta(2); for i in 1..MAXPERSONAS loop delay duration(Positive_Random(3)); personas(i).init_persona(i); end loop;

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316

end cintas_ada;

122

Pr ctica 3 - Cintas transportadoras a

3.5
3.5.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 25 o 26 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 10 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por monitores en Java: aproximadamente unas 12 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 10 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o

3.5.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

3.5.3

Dicultad

Por monitores en Ada: Dicultad de 5 sobre 10. Por monitores en Java: Dicultad de 5 sobre 10. Por citas en Ada: Dicultad de 5 sobre 10.

123

Programaci n Concurrente o

124

Pr ctica 4 - Bolsa en Red a

Pr ctica 4 a

Bolsa en Red
4.1 Enunciado

Se trata de dise ar un sistema de gesti n de compra y venta de ttulos burs tiles. Se supone la exisn o a tencia de usuarios compradores y usuarios vendedores que se conectan a un servidor que gestiona sus ofertas y demandas. Se supone, adem s, una clasicaci n de los ttulos por su nivel de riesgo a o (bajo, medio o alto), que se puede calcular mediante la funci n predenida Nivel Riesgo(Titulo). o Cuando un vendedor desea utilizar este sistema para poner a la venta un ttulo, publica un anun cio en un tabl n virtual ubicado en el servidor y a continuaci n queda esperando a que alg n o o u comprador le notique su inter s en adquirir el ttulo. Tras realizarse la adquisici n, se retirar el e o a anuncio del tabl n. El vendedor, eventualmente, puede retirar una orden. o Por otro lado, cuando un comprador desee adquirir un ttulo, deber comunicarle al servidor a el nivel m ximo de riesgo que se desea asumir. Al realizar esta petici n, el comprador le indicar a o a tambi n al servidor qu anuncios ha descartado ya, con el n de que el servidor no le proporcione e e un anuncio que ya ha sido consultado. Seguidamente, el comprador examinar el anuncio con a la intenci n de averiguar si le interesa o no (funci n predenida Interesa(Cliente,Titulo)). Si no o o le interesa, lo descartar y vuelve a pedir un anuncio con id ntico riesgo al servidor. Si, por el a e contrario, el anuncio le interesa, el comprador noticar su inter s al servidor y este, a su vez, se a e lo har saber al vendedor. Si la noticaci n llega tarde porque otro comprador se le ha adelantado, a o el comprador pedir al servidor otro anuncio (de nuevo, con el mismo nivel de riesgo). a Para simplicar, supondremos que: El tabl n tiene capacidad para un m ximo de K anuncios. o a Hay un m ximo de V vendedores y C compradores, siendo estos valores relativamente a peque os. n La cuesti n del pago por el tulo es ajena a este sistema. o

125

Programaci n Concurrente o

4.2
4.2.1

Resoluci n por monitores en Ada o


Explicaci n o

Para la resoluci n de esta pr ctica, se utiliza un monitor que ser el que haga de servidor. Tambi n o a a e se dispondr de tareas Personas, estas podr n ser o compradores o vendedores. Tendremos un a a n mero m ximo de compradores y de vendedores, el cual lo deniremos mediante las constantes u a MAXCOMPRADORES Y MAXVENDEDORES. En el servidor (monitor), tendremos los siguientes procedimientos y entradas: poner anuncios, un vendedor pondr un anuncio cuando tenga su ttulo, y haya sitio a en el tabl n para poner anuncios, ya que el tabl n estar limitado a un n mero m ximo o o a u a de anuncios que deniremos con la constantes MAXANUNCIOS. Si un vendedor no puede poner su anuncio porque no hay hueco, se espera y cuando alg n vendedor quite el suyo, u entonces lo anunciar . a Al procedimiento quitar anuncios se le pasa un ttulo, y este es quitado del tabl n. o Y por ultimo comprar ttulo, este procedimiento es llamado por el comprador, y lo que hace es buscar un ttulo de entre los que est n en el tabl n que tenga el mismo nivel de a o riesgo que pide el comprador, si es as entonces tendremos que ver si interesa o no interesa, para ello se tiene creada una funci n, que devuelve true o false, llamada interesa aqu o se elige mediante una probabilidad del cincuenta por ciento si el ttulo ofertado por el sis tema le interesa al cliente o no le interesa. En el caso de que el ttulo interese se compra inmediatamente, se comunica al vendedor que su ttulo ha sido vendido y entonces se quita el anuncio del tabl n. Si por el contrario el ttulo ofertado por el sistema no le interesa al o cliente, este seguir buscando en el tabl n, si en ese momento al comprador no le interesa a o ninguno o no encuentra uno que se ajuste a su riesgo, el comprador se marcha sin comprar ttulos. Decir tambi n que el vendedor cuando pone un anucio en el tabl n espera un tiempo determie o nado, si en ese tiempo no se ha vendido el ttulo, se quitar el anuncio del tabl n. a o Para los ttulos se ha utilizado un registro que contiene el id del ttulo, un id del vendedor, y el riesgo del ttulo.

4.2.2

C digo Fuente o
C digo fuente 4.1: Bolsa en red con Monitores en Ada o

1 2 3 4 5 6 7 8 9 10

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure bolsa_red is --maximo numero de vendedores MAXVENDEDORES : constant integer:= 5; --maximo numero de compradores MAXCOMPRADORES : constant integer:=5; --maximo de anuncios en el tablon MAXANUNCIOS: constant integer := 2;

126

Pr ctica 4 - Bolsa en Red a


--tipo persona comprador C o vendedor V type t_persona is (V,C); type t_riesgo is (ALTO,MEDIO,BAJO,NADA); type Titulo is record --un identificador (por defecto -1) Id:Integer:=-1; --identificador del propietario Id_d:Integer:=-1; --un riesgo R:t_riesgo; end record; --tablon de titulos type Tablon is array (1..MAXANUNCIOS) of Titulo; --un titulo por vendedor Titulos: array (1..MAXVENDEDORES) of Titulo; --definicion tarea persona task type Persona is entry init_persona(id: in Integer; tipo:t_persona); entry titulo_comprado; end Persona; --array de vendedores vendedores : array(1..MAXVENDEDORES) of Persona; --array de compradores compradores : array(1..MAXCOMPRADORES) of Persona; --funcion interesa, comprueba que un titulo interesa --a un cliente Function interesa return boolean is i:integer:= Positive_Random(100); begin if i<50 then --80 por ciento de posibilidades --que interese return true; --interesa else return false;--no interesa end if; end interesa; procedure avisar_vendedor(id:Integer) is begin vendedores(id).titulo_comprado; end avisar_vendedor; protected monitor is entry poner_anuncio(t: in Titulo); procedure comprar_titulo(id : in integer; r: in t_riesgo; comprado: out boolean); procedure quitar_anuncio(t: in Titulo); private tablon_anuncios:Tablon; nanuncios: integer:=0; res:boolean:= false;

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

127

Programaci n Concurrente o
--posicion libre del tablon pos_libre_tablon: Integer:=1; --nos da el id del ultimo vendedor que ha --vendido su titulo id_ultimo_vendido:Integer:=0; persona_comprando:Integer:=0;

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

end monitor; protected body monitor is entry poner_anuncio(t: in Titulo ) when (nanuncios < MAXANUNCIOS) is begin --inserto el anuncio en el tablon tablon_anuncios(pos_libre_tablon).Id:= t.Id; tablon_anuncios(pos_libre_tablon).Id_d:= t.Id_d; tablon_anuncios(pos_libre_tablon).R:= t.R; Put_Line("El vendedor con id : "& IntegerImage(tablon_anuncios(pos_libre_tablon).Id_d) &" ha puesto el anuncio de su titulo"); pos_libre_tablon:= pos_libre_tablon+1; nanuncios:=nanuncios+1; end poner_anuncio; procedure comprar_titulo (id : in integer; r: in t_riesgo; comprado: out boolean) is begin comprado:=false; --si le interesa el titulo lo compra y si no --lo descarta for i in 1..MAXANUNCIOS loop if tablon_anuncios(i).R = r then --si es del riesgo elegido, y si le --interesa lo compra if interesa = true then Put_Line("El comprador: "&IntegerImage(id)& " ha comprado el titulo " &IntegerImage(tablon_anuncios(i).Id)& " con un nivel de riesgo de : " &t_riesgoImage(tablon_anuncios(i).R)& " y del vendedor: " &IntegerImage(tablon_anuncios(i).Id_d)) ; --para indicarle al comprador que se ha --efectuado la compra comprado := true; --el tablon no estara disponible-tablon_anuncios(i).R := NADA; avisar_vendedor(tablon_anuncios(i).Id_d); quitar_anuncio(tablon_anuncios(i)); --ya ha comprado el titulo, se va.

112 113 114 115 116 117 118 119 120 121

128

Pr ctica 4 - Bolsa en Red a


exit; else --no le interesa Put_Line("El titulo " &IntegerImage(tablon_anuncios(i).Id)& " con un nivel de riesgo de: " &t_riesgoImage(tablon_anuncios(i).R)& " y del vendedor: " &IntegerImage(tablon_anuncios(i).Id_d)& " no le interesa al comprador: "& IntegerImage(id)); end if; end if; end loop; null; end comprar_titulo; procedure quitar_anuncio(t: in Titulo) is begin for i in 1..MAXANUNCIOS loop --quito el titulo vendido del tablon if(tablon_anuncios(i).Id = t.Id) then put_line("Se ha quitado el anuncio: " &IntegerImage(t.Id)& " del tablon"); tablon_anuncios(i).Id := -1; tablon_anuncios(i).Id_d := -1; tablon_anuncios(i).R:= NADA; --guardamos la posicion que queda libre en --el tablon pos_libre_tablon:=i; --ya hay hueco para los que quieran poner --anuncios nanuncios:= nanuncios-1; exit; end if; end loop; end quitar_anuncio; end monitor;

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

--cuerpo de la tarea persona task body Persona is id_persona: Integer; t: t_persona; i:Integer; r:t_riesgo; comprado:boolean:=false; begin accept init_persona(id: in Integer; tipo: in t_persona) do id_persona := id; t := tipo; if tipo = V then Put_Line("Creada Persona Vendedora: "

129

Programaci n Concurrente o
&IntegerImage(id_persona)); i:= Positive_Random(3); Titulos(id_persona).Id := id_persona; Titulos(id_persona).Id_d := id_persona; --elijo el riesgo de su titulo if i = 1 then r:= ALTO; elsif i=2 then r:= MEDIO; else r:=Bajo; end if; Titulos(id_persona).R := r; Put_Line("Titulo del vendedor: " &IntegerImage(id_persona) & "creado con riesgo: " &t_riesgoImage(Titulos(id_persona).R)); else Put_Line("Creada Persona compradora" &IntegerImage(id_persona)); i:= Positive_Random(3); if i = 1 then r:= ALTO; elsif i=2 then r:= MEDIO; else r:=Bajo; end if; end if; end init_persona; if t = V then --es vendedor delay(2.0); monitor.poner_anuncio(Titulos(id_persona)); Put_Line("Anuncio colocado"); select accept titulo_comprado do Put_Line("El titulo del vendedor: " &IntegerImage(id_persona) &" ha sido vendido"); end titulo_comprado; or delay(10.0); monitor.quitar_anuncio(Titulos(id_persona)); end select; else --es comprador delay(2.0); monitor.comprar_titulo(id_persona,r,comprado); if(comprado = false) then --si no se ha comprado Put_Line("El comprador: " &IntegerImage(id_persona)& " no ha encontrado un titulo que le interese") ; end if; end if; end Persona;

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225

226 227 228 229 230 231 232

130

Pr ctica 4 - Bolsa en Red a


begin --creo a los vendedores for i in 1..MAXVENDEDORES loop delay(1.0); vendedores(i).init_persona(i,V); end loop; --creo a los compradores for i in 1..MAXCOMPRADORES loop delay(1.0); compradores(i).init_persona(i,C); end loop; end bolsa_red;

233 234 235 236 237 238 239 240 241 242 243 244 245

131

Programaci n Concurrente o

4.3
4.3.1

Resoluci n por citas en Ada o


Explicaci n o

Para simplicar las estructuras de datos de esta pr ctica, en la resoluci n por citas hemos supuesto a o que cada vendedor y comprador s lo podr vender o comprar un ttulo. o a Para empezar esta pr ctica lo primero que hemos hecho es crear un registro record que repa resentar los ttulos que ser n puesto en venta y se comprar n. Estos registros tienen los siguientes a a a campos: id: es el identicador del ttulo. id d: es el identicador del due o del ttulo. n r: es el riesgo que tiene asociado ese ttulo. Tendremos dos tareas, Usuario y Sistema. Las tareas usuarios podr n ser vendedores o a compradores, seg n lo que sea ejecutar n una parte u otra de la tarea. Si es un vendedor, primero u a probar haber si puede poner un anuncio en el tabl n, de no caber tendr que esperar a que se libere a o a un hueco, si hubiese sitio libre lo publicar , y esperar un tiempo y si ha nadie le ha interesado ese a a tipo lo borrar . El comprador por el contrario, intentar comprar algo que le interese hasta que lo a a consiga, y de no haber nada que le interese en el tabl n y no haya nadie, ni nadie esperando a la o espera que publicar otro anuncio, terminar sin comprar nada. a El servidor, aceptar las peticiones de los vendedores y compradores, que podr n ser: a a PuedoAnuncio: determina si un vendedor puede publicar su anuncio en el tabl n de o tama o K. n PongoAnuncio: publica un anuncio del vendedor en el tabl n. o BorrarTitulo: borra un ttulo del tabl n. o QueComprar: el servidor indica a un comprador los ttulos que puede comprar. Comprar: el servidor realiza una compra entre un vendedor y un comprador. HayInteres: informa al vendedor de que su ttulo le interesa a un comprador. La funci n que devuelve si un ttulo interesa a un usuario (de tipo comprador), est determio a nado por el riesgo m ximo que acepta ese comprador y por tanto, podr comprar todos los ttulos a a que tengan un riesgo igual o menor que el que esta dispuesto a arriesgar. Adem s cuando a un a comprador la funci n QueComprar le devuelvan algo que le interesa nunca lo descartar , pues o a creo que es una tontera que no compre una oferta que le interesa (adem s que si no la compra en a cuanto la encuentra podra perderlo para siempre, e incluso podra quedarse sin comprar nada al nal). Para que adem s no se produzca interbloqueos entre dos o m s procesos compradores que a a est n interesados en una misma oferta, hemos utilizado un Turno, que es un sem foro binario, e a que no permita una vez que alguno haya transmitido su inter s, que otro haga lo mismo a la misma e oferta del tabl n. o 132

Pr ctica 4 - Bolsa en Red a Puede considerarse que se ha utilizado alg n punto de entrada de m s, pero se ha hecho de u a este modo para que parezca m s real, y por ejemplo la tarea cliente espere hasta que le paga el a comprador (a trav s del servidor), o por ejemplo que el comprador primero muestra su inter s de e e comprar (y el sistema lo transmite), y luego lo compra (a trav s del sistema). e En el c digo de la pr ctica hay muchos comentarios con los que se explica c mo est n impleo a o a mentados estos puntos de entrada, y los algoritmos utilizados

4.3.2

C digo fuente o
C digo fuente 4.2: Bolsa en Red por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

--Practica 4. Bolsa en red por citas with Ada.Text_Io; with Ada.Integer_Text_Io; with Ada.Numerics.Float_Random; with Ada.Exceptions; with Semaforos; use use use use use Ada.Text_Io; Ada.Integer_Text_Io; Ada.Numerics.Float_Random; Ada.Exceptions; Semaforos;

procedure Bolsa_Red_Citas is G:Generator; --numero maximo de anuncios K:Integer:=3; --numero de vendedores V:Integer:=5; --numero de compradores C:Integer:=5; --numero de titulos en total Max_Titulos:Integer:=V; Turno: Binary_Semaphore := Init(1); --tipo de persona type Tipo_Persona is (Vendedor,Comprador); --riesgo de cada titulo type Riesgo is (Bajo,Medio,Alto); --un titulo tiene type Titulo is record --un identificador (por defecto -1) Id:Integer:=-1; --identificador del propietario Id_d:Integer:=-1; --un riesgo R:Riesgo; end record;

133

Programaci n Concurrente o

43 44 45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

--Vectores con los titulos --vector que representa el tablon donde salen a la venta los titulos Tablon: array (1..K) of Titulo; --vector que representa todos los titulos disponibles --al principio el indice del titulo, corresponde con su d u e o Titulos: array (1..Max_Titulos) of Titulo; --vector de espera, valor a uno en una posicion cuando el --vendedor(pos) este esperando a publicar en el tablon Espera:array (1..V) of Integer; --Comprueba si hay algun vendedor esperando a poner un anuncio function HayVendedoresEspera return Boolean is Hay:Boolean:=False; begin for Ii in 1..V loop if Espera(Ii)=1 then Hay:=True; exit; end if; end loop; return Hay; end HayVendedoresEspera; --Comprueba que hay ofertas en el tablon function HayOfertasTablon return Boolean is Hay:Boolean:=False; begin for Ii in 1..K loop if Tablon(Ii).Id/=-1 then Hay:=True; exit; end if; end loop; return Hay; end HayOfertasTablon; --devuelve verdade en el caso de que el titulo exista function Existe(T:Titulo) return Boolean is Ex:Boolean:=False; begin if T.Id/=-1 then Ex:=True; end if; return Ex; end Existe; --devuelve el nivel de riesgo de un titulo function Nivel_Riesgo(T:Titulo) return Riesgo is begin return T.R; end Nivel_Riesgo; Function Interesa(Interes:riesgo;T:Titulo) return Boolean is

134

Pr ctica 4 - Bolsa en Red a


begin --Segun el maximo de interes(riesgo)que acepta el comprador --Comprara o no if Interes=T.R then return True; else if Interes=Alto then return True; else if Interes=Medio and T.R=Bajo then return True; else return False; end if; end if; end if; end Interesa; --Comprueba si hay hueco en el tablon de anuncios --si lo hay devuelve la posicion libre --Si no, devuelve -1 function HayLibre return Integer is Encontrado:Boolean:=False; Indice:Integer; begin for Ii in 1..K loop if Tablon(Ii).Id = -1 then Encontrado:=True; Indice:=Ii; exit; end if; end loop; if not Encontrado then return -1; else return Indice; end if; end Haylibre; --tipo de tarea Usuario task type Usuario is entry Inicializar(Id:Integer;Tipo:Tipo_Persona); --para saber cuando tengo sitio libre en el tablon entry TablonLibre(Pos_A:integer); entry EsperoInteres(Comprador:Integer); entry CompraHecha; end Usuario; --tarea servidor task Servidor is entry PuedoAnuncio(Id:Integer;T:Titulo;Ok:out Boolean;Ind:out integer); entry PongoAnuncio(Id:Integer;T:Titulo;Pos:integer); entry BorrarTitulo(Pos_T:Integer); entry QueComprar(Id:Integer;Int:Riesgo;Posible:out Titulo);

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

150 151 152

135

Programaci n Concurrente o
entry Comprar(Id:Integer;Pos_Tit:Integer;Ok:out boolean); entry HayInteres(Iv:Integer;Ic:Integer); end Servidor;

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

--Vectores de Usuarios Vendedores:array (1..V) of Usuario; Compradores:array (1..C) of Usuario; --procedimiento que imprime la informacion de todos los titulos procedure ImprimeTitulos is begin Put_Line("Resumen de compra y venta."); for Ii in 1..Max_Titulos loop if Existe(Titulos(Ii)) then Put_Line("Titulo id: "&IntegerImage(Titulos(Ii).id)&" pertenece a: " &IntegerImage(Titulos(Ii).Id_d)& "de tipo: "&RiesgoImage(Titulos(Ii).r)); end if; end loop; end ImprimeTitulos; --cuerpo de la tarea Usuario task body Usuario is I:Integer; T:Tipo_Persona; Retira:Boolean:=False; Comprado:Boolean:=False; Tespera:Integer:=V*3+C; Rand:float; Interesado:Riesgo; Pos_Tit:Integer; Pos_Anun:Integer; Ok:Boolean:=False; Posible:Titulo; begin --inicializamos al usuario segun su id y tipo de persona accept Inicializar(Id:Integer;Tipo:Tipo_Persona) do I:=Id; T:=Tipo; Pos_Tit:=Id; --para los numeros aleatorios Reset(G); Rand:=Random(G)*3.0; --asignamos un interes aleatorio if Rand<1.0 then Interesado:=Bajo; else if Rand<2.0 then Interesado:=Medio; else Interesado:=Alto; end if; end if;

169

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206

136

Pr ctica 4 - Bolsa en Red a


--Si es un comprador le asignamos un nivel de riesgo en el q esta interesado if T=Comprador then Interesado:=Interesado; Put_Line("Usuario ("&IntegerImage(Id)&","&Tipo_Persona Image(tipo)& ") creado, interesado: "&RiesgoImage( interesado)); else --Si es un vendedor asignamos un riesgo a su titulo Titulos(I).Id:=Id; Titulos(i).Id_D:=Id; Titulos(i).r:=Interesado; Put_Line("Usuario ("&IntegerImage(Id)&","&Tipo_Persona Image(tipo)& ") creado, tiene: "&RiesgoImage(interesado) ); end if; end Inicializar; --Segun el tipo de persona if T=Vendedor then --Es vendedor Servidor.PuedoAnuncio(I,Titulos(I),Ok,Pos_anun); --Si puedo anunciar mi venta (si cabe en el tablon) --Si no, espero a que haya hueco if not Ok then Put_Line("%% "& IntegerImage(I)&" Espera a poner el anuncio"); Espera(I):=1; accept TablonLibre(Pos_A:integer)do Pos_Anun:=Pos_A; end TablonLibre; end if; --Pongo el anuncio Servidor.PongoAnuncio(I,Titulos(I),Pos_anun); select --espero a un comprador accept EsperoInteres(Comprador:Integer)do Comprado:=True; end EsperoInteres; or --Transcurrido un tiempo, puede retirar el anuncio delay Duration(Integer(Random(G)*Float(Tespera))); --ultima oportunidad --por si alguien estaba interesado if EsperoInteresCount>0 then accept EsperoInteres(Comprador:Integer)do Comprado:=True;

207

208 209 210 211

212

213 214 215 216 217 218 219 220

221

222 223 224 225 226 227 228 229 230 231 232

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256

137

Programaci n Concurrente o
Put_Line("??? Ultima oportunidad, haceptamos al comprador " &IntegerImage(Comprador)); end EsperoInteres; end if; Retira:=True; Put_Line("<< "&IntegerImage(I)&" Pues si nadie me lo compra, me voy. "); end select; if Comprado=True then --Put_Line("++ Esperamos que se realize la transaccion, hacia "& -IntegerImage(I)&" con "&RiesgoImage( Titulos(I).r)); accept CompraHecha do Put_Line("++ "&IntegerImage(I)&" Transaccion realizada con exito"); end CompraHecha; end if; --Borramos el titulo del tablon Servidor.BorrarTitulo(Pos_anun); if Comprado=True then Signal(Turno); end if; else --busca continuamente una compra --hasta que revisa todas las posibles y no haya vendedores esperado --a publiclar un titulo en el tablon while not Ok and (HayVendedoresEspera or HayOfertasTablon) loop delay Duration(1); Wait(Turno); --Es comprador Servidor.QueComprar(I,interesado,Posible); --Si hay algun titulo que me interese if Existe(Posible) then --Put_Line("He encontrado algo... voy a ver si me interesa"); if Interesa(Interesado,Posible) then Servidor.Hayinteres(Posible.Id_D,I); --Si no lo ha retirado, lo compramos --comprar titulo Servidor.Comprar(I,Posible.Id,ok); else Signal(Turno); end if; else Signal(Turno); end if; end loop;

257

258 259 260 261 262 263

264 265 266 267

268

269 270

271 272 273 274 275 276 277 278 279 280 281 282 283

284 285

286 287 288 289 290 291 292

293 294 295 296 297 298 299 300 301 302 303 304

138

Pr ctica 4 - Bolsa en Red a


end if; end Usuario;

305 306 307 308 309 310 311 312 313 314 315 316 317 318

319 320 321 322

323 324 325 326 327 328 329 330 331 332 333 334

335

336 337 338 339

340 341 342 343

344 345 346 347 348 349 350 351 352 353

--cuerpo tarea servidor task body Servidor is Indice:Integer; begin loop select accept HayInteres(Iv:Integer;Ic:Integer) do Put_Line("%% Hay interes de "&IntegerImage(ic)&" por "&IntegerImage(Iv)); Vendedores(iv).EsperoInteres(ic); end HayInteres; or accept PuedoAnuncio(Id:Integer;T:Titulo;Ok:out Boolean; Ind:out integer) do Indice:=Haylibre; --hay hueco libre en el tablon if Indice/=-1 then Ok:=True; --Ponemos el anuncio Ind:=Indice; Tablon(ind):=T; end if; end PuedoAnuncio; or accept PongoAnuncio(Id:Integer;T:Titulo;Pos:integer) do Put_Line(" "&IntegerImage(id)&" Pongo anuncio tipo: "& RiesgoImage(T.r)&" en la pos:"&Integer Image(Pos)); Tablon(Pos):=T; end PongoAnuncio; or accept Comprar(Id:Integer;Pos_Tit:Integer;Ok:out boolean)do --Si exite el titulo if Existe(Titulos(Pos_Tit)) then Ok:=True; Put_Line("++ "&IntegerImage(Id)&" Compra a "& IntegerImage(Pos_Tit)); --cambiamos de propietario al titulo Titulos(Pos_Tit).Id_d:=Id; --Avisamos de que la compra fue realizada Vendedores(Titulos(Pos_Tit).Id).CompraHecha; else Ok:=False; end if; end Comprar; or --no devuelve un titulo del tablon que estamos interesados en comprar

139

Programaci n Concurrente o
accept QueComprar(Id:Integer;Int:Riesgo;Posible:out Titulo) do Put_Line("Comprador "&IntegerImage(id)&": estoy buscando ("&RiesgoImage(Int)&")"); for Ii in 1..K loop --Si existe y no ha sido comprada ya if Existe(Tablon(Ii)) and Tablon(Ii).Id=Tablon(Ii ).Id_D Then if Interesa(Int,Tablon(Ii)) then Posible:= Tablon(Ii); exit; end if; end if; end loop; end QueComprar; or --borramos titulo del tablon accept BorrarTitulo(Pos_T:Integer)do Put_Line("** Borramos titulo del tablon, posicion: " &IntegerImage(Pos_T)); --Borramos Tablon(Pos_T).Id:=-1; Tablon(Pos_T).Id_d:=-1; --Avisamos de hueco libre for Ii in 1..V loop if Espera(Ii)=1 then Espera(Ii):=0; Vendedores(Ii).TablonLibre(Pos_T); exit; end if; end loop; end BorrarTitulo; or terminate; end select; end loop; end Servidor; --total de usuarios a crear Total:integer:=C+V; --tiempo entre la llegada de los usuarios Tentre:Integer:=1;

354

355

356 357 358

359 360 361 362 363 364 365 366 367 368 369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405

begin Put_Line("Practica 4. citas"); New_Line; New_Line; Put_Line("Lanzamos "&IntegerImage(Total)&" usuarios."); New_Line; -- ImprimeTitulos; for Ii in 1..V loop --inicializamos la matriz de espera a cero Espera(Ii):=0;

140

Pr ctica 4 - Bolsa en Red a


--Inicializamos a los vendedores Vendedores(Ii).Inicializar(Ii,Vendedor); delay Duration (Tentre); end loop; for Ii in 1..C loop --Inicializamos a los compradores Compradores(Ii).Inicializar(Ii+V,Comprador); delay Duration (Tentre); end loop; end Bolsa_Red_Citas;

406 407 408 409 410 411 412 413 414 415 416 417

141

Programaci n Concurrente o

4.4
4.4.1

Resoluci n por monitores en Java o


Explicaci n o

Para resolver el problema con monitores en Java hemos diferenciado las distintas clases del problema, seg n el papel que juegan: u Monitor: Es la clase mediante la que implementamos los tipos protegidos. Esta clase representa al sistema de bolsa, y se encarga de mantener los anuncios de los vendedores y ofrecer a los compradores ttulos que respeten un nivel m ximo de riesgo. Cuando un a comprador encuentra interesante una oferta del sistema, Monitor se encarga de vend rsela e y noticar al vendedor de la misma. Vendedor: Los objetos de esta clase ponen ttulos en venta a trav s de Monitor. Cada e ttulo se pone en venta con un nivel de riesgo, que servir a los compradores para tomar sus a decisiones de compra. Comprador: Peri dicamente solicitan recomendaciones al sistema de bolsa objeto Monitor o y, si les interesa, realizan la compra del ttulo recomendado. Los vendedores ponen una serie de ttulos en venta a trav s del sistema de bolsa, y duermen e hasta que el sistema les notica que alguien ha comprado uno de sus ttulos. En ese momento, quitan de su lista dicho ttulo, para simbolizar la entrega del mismo. El sistema de bolsa (clase Monitor) mantiene una lista de valores en venta, y una de valores vendidos. Cuando un valor que comprende un ttulo y un nivel de riesgo es vendido, se elimina de la lista de valores disponibles y pasa a la lista de valores vendidos. Los compradores, por otra parte, mantienen una lista de los ttulos que han adquirido durante la simulaci n, para hacer m s realista el programa. Cabe destacar, por ultimo, que hemos dotado o a de una limitaci n a la ejecuci n de los compradores, ya que s lo intentar n adquirir un ttulo sin o o o a exito un n mero limitado de veces es decir, sin que el sistema les proporcione un ttulo acorde u con su nivel de riesgo, o proporcion ndole uno que no le interese. De esta forma, damos un poco a m s de realismo a la resoluci n. a o

4.4.2

C digo fuente o
C digo fuente 4.3: Bolsa en Red con Monitores en Java o

1 2 3 4 5 6 7 8 9 10 11 12

import java.util.LinkedList; enum nivelesDeRiesgo {ALTO, MEDIO, BAJO, NODEF}; //Nivel de riesgo public class BolsaEnRed { static final int C = 3; //Numero de compradores static final int V = 5; //Numero de vendedores public static void main(String[] args){ //Creamos el monitor

142

Pr ctica 4 - Bolsa en Red a


Monitor m = new Monitor(); m.start(); //Creamos los vendedores for(int i = 0; i < V; i++){ Vendedor aux = new Vendedor(m); aux.start(); try{ aux.sleep((long) Math.random() * 100 + 10); }catch(InterruptedException ex){ System.out.println("UPS!!! - ALGO FALLA"); } } //Creamos los compradores for(int i = 0; i < C; i++){ Comprador aux = new Comprador(m); aux.start(); try{ aux.sleep((long) Math.random() * 100 + 10); }catch(InterruptedException ex){ System.out.println("UPS!!! - ALGO FALLA"); } } } } //--------------------------------------------------------class Monitor extends Thread{ static final int NO_HAY = 1000; LinkedList<Valor> bolsa = new LinkedList<Valor>(); LinkedList<Valor> vendidos = new LinkedList<Valor>(); final int K = 20; //Numero maximo de anuncios //Obtiene el nivel de riesgo de un titulo synchronized nivelesDeRiesgo NivelDeRiesgo(int titulo){ nivelesDeRiesgo riesgo = nivelesDeRiesgo.NODEF; int pos = bolsa.indexOf(new Valor(titulo)); if(pos != -1){ riesgo = bolsa.get(pos).getRiesgo(); } return riesgo; } //Muestra todos los titulos en venta synchronized void showBolsa(){ System.out.print("Bolsa: "); for(int i = 0; i < bolsa.size(); i++){ System.out.print(bolsa.get(i).getTitulo() + ", "); } System.out.println(); } //Retira un anuncio, siempre y cuando sea del vendedor

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

143

Programaci n Concurrente o
synchronized boolean retiraAnuncio(int titulo, Vendedor v){ boolean borrado = false; //Encontramos el anuncio, creando un objeto auxiliar del que solo nos //importa el titulo, para que funcione el equals de la clase Anuncio int pos = bolsa.indexOf(new Valor(titulo)); if(pos != -1){ //El anuncio existe, lo borramos solo si es de ese vendedor if(bolsa.get(pos).getVendedor().equals(v)){ //Estamos autorizados a borrar el anuncio System.out.println("Al VENDEDOR " + v.getID() + " le apetece retirar el TITULO " + bolsa.get(pos). getTitulo() + ". El titulo es retirado"); bolsa.remove(pos); borrado = true; } } return borrado; } //Compra un titulo synchronized boolean compraTitulo(int titulo, Comprador c){ System.out.println("Comprador " + c.getID() + " en compraTitulo con titulo="+titulo); //Encontramos el anuncio, creando un objeto auxiliar del que solo nos //importa el titulo, para que funcione el equals de la clase Anuncio boolean comprado = false; int pos = bolsa.indexOf(new Valor(titulo)); if(pos != -1){ comprado = true; vendidos.add(bolsa.get(pos)); //Ponemos el valor como vendido System.out.println("COMPRADOR " + c.getID() + " compra el titulo " + bolsa.get(pos).getTitulo() + ". Se avisa al vendedor " + bolsa.get(pos).getVendedor(). getID()); Vendedor aux = bolsa.get(pos).getVendedor(); aux.ultimo_vendido = bolsa.get(pos).getTitulo(); aux.despierta(); bolsa.remove(pos); }else{ System.out.println("ALGO VA MAL. Esto no deberia imprimirse (se quiere comprar un titulo no existente ): el "+titulo); } showBolsa(); return comprado; } //Vende un titulo synchronized boolean ponALaVenta(Valor a){ boolean b = false;

69 70 71

72

73 74 75

76 77 78

79 80 81 82 83 84 85 86 87 88

89

90

91 92 93 94 95

96

97 98 99 100 101 102

103 104 105 106 107 108 109 110

144

Pr ctica 4 - Bolsa en Red a


if(bolsa.size() < K){ b = true; this.bolsa.add(a); System.out.println("VENDEDOR " + a.getVendedor().getID () + " pone en venta el titulo " + a.getTitulo() + " , con riesgo " + a.getRiesgo()); }else{ System.out.println("VENDEDOR " + a.getVendedor().getID () + " intenta poner en venta el titulo " + a. getTitulo() + ", pero la BOLSA esta LLENA"); } return b; } //Un comprador comprueba si le interesa un titulo o no synchronized boolean interesa(Comprador c, int titulo){ boolean i = false; if(Math.random()*2 > 0){ i = true; } System.out.println("COMPRADOR " + c.getID() + " comprueba si le interesa el titulo " + titulo + "... " + ((i)?("SI le interesa"):("NO le interesa"))); return i; } //Convierte un enumeracion riesgo en entero int riesgo2int(nivelesDeRiesgo r){ int riesgo = -1; if(r == r.ALTO){ riesgo = 2; }else if(r == r.MEDIO){ riesgo = 1; }else if(r == r.BAJO){ riesgo = 0; }else{ System.out.println("ALGO VA MAL. Esto no deberia imprimirse"); } return riesgo; } //Recomienda un titulo segun un nivel de riesgo maximo synchronized int recomiendame(nivelesDeRiesgo r, LinkedList< Integer> descartados){ int titulo = NO_HAY; //Significa que no hay ningun titulo apropiado int aux; for(int i = 0; i < this.bolsa.size(); i++){ aux = riesgo2int(bolsa.get(i).getRiesgo()); if(aux <= riesgo2int(r) && !descartados.contains(bolsa. get(i).getTitulo())){ titulo = bolsa.get(i).getTitulo(); } } if(bolsa.size()==0){

111 112 113 114

115 116

117 118 119 120 121 122 123 124 125 126 127

128 129 130 131 132 133 134 135 136 137 138 139 140 141

142 143 144 145 146 147

148

149 150 151 152

153 154 155 156

145

Programaci n Concurrente o
//Ya no hay titulos } //System.out.println("Monitor recomienda " + titulo); if(titulo == NO_HAY){ System.out.println("No quedan titulos de nivel de riesgo <= " + r); } this.showBolsa(); return titulo; } } //--------------------------------------------------------abstract class Persona extends Thread{ static enum tipoPersona {COMPRADOR, VENDEDOR}; static int contador = 0; //Contador de personas private int id; //Identificador private tipoPersona tipo; Monitor m; //Constructor Persona(tipoPersona tipo, Monitor m){ this.id = contador++; this.tipo = tipo; this.m = m; } //Obtiene el identificador int getID(){ return id; } //Convierte un entero en enumeracion riesgo nivelesDeRiesgo int2riesgo(int r){ nivelesDeRiesgo riesgo = nivelesDeRiesgo.NODEF; switch(r){ case 0: riesgo = riesgo.BAJO; break; case 1: riesgo = riesgo.MEDIO; break; default: riesgo = riesgo.ALTO; } return riesgo; } //Metodo equals @Override public boolean equals(Object o){

157 158 159 160 161 162

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

146

Pr ctica 4 - Bolsa en Red a


boolean iguales = o instanceof Persona; if(iguales) iguales = ((Persona)o).getID() == getID(); return iguales; } } class Comprador extends Persona{ static final int NO_HAY = 1000; LinkedList<Integer> titulos = new LinkedList<Integer>(); LinkedList<Integer> descartados = new LinkedList<Integer>(); //Constructor Comprador(Monitor m){ super(Persona.tipoPersona.COMPRADOR, m); } //Descarta un titulo void descarta(int titulo){ descartados.add(titulo); } //Ha adquirido un titulo void adquiere(int titulo){ titulos.add(titulo); } @Override public void run(){ int intentos_seguidos_restantes = 5; System.out.println("CREADO COMPRADOR " + getID()); int titulo = -1; boolean interesa = false; int riesgo; while(intentos_seguidos_restantes >= 0){ //Solicitamos valores hasta que nos den uno apropiado y nos interese o se acaben los intentos java.util.Random r = new java.util.Random(); riesgo = r.nextInt(3); while(titulo != NO_HAY && !interesa){ intentos_seguidos_restantes --; System.out.println("COMPRADOR " + getID() + " busca titulos con riesgo " + int2riesgo(riesgo)) ; titulo = m.recomiendame(int2riesgo(riesgo), descartados); if(titulo != NO_HAY){ if (!m.interesa(this, titulo)) { this.descarta(titulo); interesa = false; //Para seguir buscando }else{ interesa = true; }

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

251 252 253 254 255

256

257 258 259 260 261 262 263

147

Programaci n Concurrente o
} } if(titulo != NO_HAY){ //Hemos encontrado un titulo apropiado m.compraTitulo(titulo, this); interesa = false; //para buscar mas en la siguiente vuelta this.titulos.add(titulo); //Ponemos el titulo en nuestra lista de titulos adquiridos }else{ titulo = NO_HAY + 1; //Para buscar mas en la siguiente vuelta interesa = false; } try{ this.sleep(r.nextInt(100)); }catch(InterruptedException ex){ System.out.println("UPS!!! - ALGO FALLA"); } } System.out.println("COMPRADOR " + this.getID() + " abandona el sistema. NO HAY TITULOS ADECUADOS para el."); } } class Vendedor extends Persona{ LinkedList<Valor> valores = new LinkedList<Valor>(); int ultimo_vendido = -1; //Constructor Vendedor(Monitor m){ super(Persona.tipoPersona.VENDEDOR, m); } //Pone los titulos en venta void ponTitulosEnVenta(){ for(int i = 0; i < (int)Math.random()*2 + 3; i++){ Valor aux = new Valor(this); if(m.ponALaVenta(aux)){ //Lo hemos podido poner a la venta this.valores.add(aux); }else{ i = 100; //Para no intentar poner mas anuncios } } } //Quita un valor de nuestra lista void retira(int titulo){ this.valores.remove(new Valor(titulo)); ultimo_vendido = -1; } //Metodo de espera synchronized void espera(){

264 265 266 267 268 269

270

271 272

273 274 275 276 277 278 279 280 281

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314

148

Pr ctica 4 - Bolsa en Red a


try { wait(); //Dormimos hasta que alguien quiera comprar algo } catch (InterruptedException ex) { System.err.println("Error al dormir al vendedor " + getID()); } } //Metodo para despertarse synchronized void despierta(){ try{ notify(); }catch(Exception e){} } @Override public void run(){ java.util.Random r = new java.util.Random(); System.out.println("CREADO VENDEDOR " + getID()); ponTitulosEnVenta(); //Preparamos los valores y los ponemos en venta while(this.valores.size() > 0){ //Esperamos hasta que se venda algun titulo nuestro espera(); //Nos hemos despertado, el sistema ha vendido un valor nuestro retira(ultimo_vendido); //Puede que quite alguno de sus valores en venta if(r.nextBoolean() == true && this.valores.size() > 0){ int aux = this.valores.get(r.nextInt(this.valores. size())).getTitulo(); if(m.retiraAnuncio(aux, this)){ retira(aux); //Quitamos el valor de nuestra lista } } } System.out.println("Vendedor " + this.getID() + " TERMINA. No tiene mas valores en venta."); } } //--------------------------------------------------------class Valor{ private private private private static int contador = 0; //Contador de anuncios nivelesDeRiesgo riesgo; int titulo; Vendedor vendedor;

315 316

317 318

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

335 336 337 338 339

340 341 342 343

344 345

346 347 348 349

350 351 352 353 354 355 356 357 358 359 360 361 362 363

//Constructor Valor(Vendedor vendedor){

149

Programaci n Concurrente o
//Asignamos un identificador titulo = ++contador; //Asignamos un nivel de riesgo java.util.Random r = new java.util.Random(); switch(r.nextInt(3)){ case 0: riesgo = riesgo.BAJO; break; case 1: riesgo = riesgo.MEDIO; break; case 2: riesgo = riesgo.ALTO; break; } this.vendedor = vendedor; } //Constructor para servirnos del equals Valor(int id){ titulo = id; } //Metodo de obtencion el id public int getTitulo(){ return titulo; } //Metodo de obtencion del nivel de riesgo public nivelesDeRiesgo getRiesgo(){ return riesgo; } //Devuelve el vendedor public Vendedor getVendedor(){ return this.vendedor; } //Metodo equals @Override public boolean equals(Object o){ boolean iguales = o instanceof Valor; if(iguales) iguales = ((Valor)o).titulo == getTitulo(); return iguales; } //-----------------------------------------------------}

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409

150

Pr ctica 4 - Bolsa en Red a

4.5
4.5.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 25 o 26 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 10 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por monitores en Java: aproximadamente unas 12 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 10 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o

4.5.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

4.5.3

Dicultad

Por monitores en Ada: Dicultad de 5 sobre 10. Por monitores en Java: Dicultad de 5 sobre 10. Por citas en Ada: Dicultad de 5 sobre 10.

151

Programaci n Concurrente o

152

Pr ctica 5 - Directores Deportivos a

Pr ctica 5 a

Directores deportivos
5.1 Enunciado

Tenemos un conjunto de N jugadores que son objeto de deseo de los M Directores Deportivos (DP) asociados a cada uno de los M candidatos a la presidencia de cierto club de f tbol. Cada DP u maneja un presupuesto Pa para char jugadores, y piensa char jugadores de entre los de una lista de Na jugadores que maneja, si su presupuesto se lo permite. Por supuesto, no todos los jugadores tienen para el la misma importancia. As, dispone para cada jugador de su importancia dentro de su proyecto deportivo, y de la cantidad que estara dispuesto a ofrecerle para charlo. Un jugador va a escuchar ofertas durante un tiempo Tj, transcurrido el cual, se decidir por una (tambi n a e puede aceptarla inmediatamente si sobrepasa sus expectativas salariales), aceptando la de mayor cuanta, aunque se cuidar mucho de dejar la puerta abierta a una colaboraci n futura con el resto a o de propuestas que colmen sus aspiraciones monetarias. Puesto que las elecciones est n pr ximas, a o la validez de la oferta a los jugadores est limitada en el tiempo. a Hay dos tipos de Directores Deportivos: dpTV (del Todo Vale) que pretende char con una unica lista. dpS (Selectivo) que pretende char teniendo en cuenta las distintas posiciones en las que se desenvuelven los jugadores. S lo char a los jugadores que sean necesario en cada o a posici n. Por simplicidad vamos a suponer que cada jugador encaja en una unica posici n. o o En ning n caso los compromisos sobrepasar n el presupuesto. u a NOTA: Puede plantear dos versiones. 1. Se realizan ofertas sin sobrepasar el presupuesto. 2. Se realizan ofertas pudi ndose sobrepasar el presupuesto, pero se aceptan compromisos e mientras no se sobrepasa el presupuesto de los ya aceptados. Dise e un Programa Concurrente que simule el Sistema descrito. El programa ha de estar libre n de bloqueos e inaniciones.

153

Programaci n Concurrente o

5.2
5.2.1

Resoluci n por Citas en Ada o


Explicaci n o

En la resoluci n de la pr ctica por citas, tendremos tres tareas: jugador, director y reloj. El funo a cionamiento es igual que el de tipos protegidos. La diferencia est en el cuerpo de las tareas. a En la tarea director existen dos entrys: 1. init director 2. mandar decision que lo que hace recoger las decisiones de los jugadores a los que ha hecho la oferta. En la tarea jugador estan los entrys: 1. init jugador 2. ver oferta que se utiliza para que el jugador reciba la oferta de un director 3. decidir: este se utiliza para que el jugador se decida por una oferta y comunique a los direcores que le han ofrecido algo su decisi n. Y por ultimo el entry o 4. cuanto vales que sirve para que el director sepa el precio del jugador y cual es su posic n. o La tarea reloj hace la misma funcionalidad que en tipo protegidos.

5.2.2

C digo Fuente o
C digo fuente 5.1: Directores Deportivos por Citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure directores_citas is

MAXJUG: constant Integer:= 5; --numero de jugadores MAXDIR: constant INteger:= 3; --numero de directores deportivos TJ : Integer:= 10; --tiempo espera jugador MAXPRE : Integer:= 20000; --maximo presupuesto MAXPREJU : Integer:= 5000; --maximo precio de un jugador type clase is (TV,SE); -- tipo todo vale o selectivo type contestacion is (nose, si, no,nada); type lista_jugadores is array (1..MAXJUG) of Integer;

task type director is entry init_director(id_d: in Integer; tipo: clase); entry mandar_decision(id_j: in Integer; decision: contestacion);

154

Pr ctica 5 - Directores Deportivos a


end director; task type jugador is entry init_jugador(id_j:Integer; pos: Integer); --inicializar jugador entry ver_oferta(id_d:Integer; oferta: Integer; decision: out contestacion); --ver oferta entry decidir; --decidirse por una oferta entry cuanto_vales(aux_precio: out Integer;aux_posicion: out Integer); --para saber cuanto vale y en que posicion esta un jugador end jugador; task type reloj is entry init_reloj(id_j: Integer); end reloj; --creamos los directores directores: array (1..MAXDIR) of director; --creamos los jugadores jugadores: array (1..MAXJUG) of jugador; --cuerpo del jugador task body jugador is id: Integer;--id del jugador ultima_oferta: Integer;--ultima oferta precio: Integer;--precio del jugador mejor_oferta: Integer; --guardamos la mejor oferta mejor_director: Integer; -- guardamos al directo que --ha hecho la mejor oferta clock:reloj; vendido:Boolean; --para saber si esta vendido o no ofertas_espera: array (1..MAXDIR) of Integer; posicion:Integer; --posicion del jugador begin accept init_jugador(id_j: in Integer; pos: Integer) do id:=id_j; precio:= Positive_Random(MAXPREJU); vendido:= false; mejor_oferta:= 0; mejor_director:= 0; posicion:=pos; for i in 1..MAXDIR loop ofertas_espera(i):=0; end loop; end init_jugador; put_line("Jugador: "&IntegerImage(id)&" juega en la posicion : " &IntegerImage(posicion)&" y cuesta : "

21 22 23 24 25 26 27 28 29 30 31

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

74

155

Programaci n Concurrente o
&IntegerImage(precio)); clock.init_reloj(id); --se inicializa el temporizador --cuando se acabe el tiempo el jugador decide. loop select accept ver_oferta(id_d : Integer; oferta: Integer; decision : out contestacion) do --si el jugador todavia no ha dicho que si a nadie.. if vendido = false then put_line("Al Jugador: "&IntegerImage(id) &" le ha llegado una oferta del director " &IntegerImage(id_d)); if oferta > precio then vendido := true; -- acepta directamente. ultima_oferta:=id_d; decision:=si; put_line("VENDIDO DIRECTAMENTE"); else ofertas_espera(id_d):=oferta; if oferta > mejor_oferta then mejor_oferta := oferta; mejor_director:= id_d; end if; decision:=nose; end if; else put_line("El jugador "&IntegerImage(id) &" ya tiene director"); decision:=no; end if; end ver_oferta;

75 76 77 78 79 80 81 82 83 84 85 86

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

116 117 118 119 120 121 122 123 124 125 126 127

--en el caso de que directamente se acepta la oferta. if vendido = true then directores(ultima_oferta).mandar_decision(id,si); for i in 1..MAXDIR loop if i/= ultima_oferta and ofertas_espera(i) /= 0 then directores(i).mandar_decision(id,no); end if; end loop; end if; or

accept decidir do --si no se ha vendido if vendido = false and mejor_director /= 0 then put_line("El jugador: "&IntegerImage(id)&" decide"&

156

Pr ctica 5 - Directores Deportivos a


" por narices"); put_line("El mejor director para: "&IntegerImage (id) &" es: "&IntegerImage(mejor_director)); directores(mejor_director).mandar_decision(id,si) ; --aviso al director del que acepto la oferta vendido := true; for i in 1..MAXDIR loop if i/= mejor_director and ofertas_espera(i) /= 0 then directores(i).mandar_decision(id,no); end if; end loop; elsif vendido = false and mejor_director = 0 then put_line("El jugador: "&IntegerImage(id)& " no ha recibido ofertas"); else put_line("El jugador : "&IntegerImage(id)& " no tiene ofertas porque ha sido vendido"); end if; end decidir; or accept cuanto_vales(aux_precio: out Integer; aux_posicion: out Integer) do aux_precio:= precio; aux_posicion:= posicion; end cuanto_vales; or terminate; end select;

128 129

130 131

132 133 134 135

136 137 138 139 140 141 142 143 144

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

end loop;

end jugador; task body director is id:Integer; --identificador del director lista:lista_jugadores; --lista de jugadores decision: contestacion; posi:Integer; t:clase;--tipo de director aux_precio:Integer; aux_posicion:Integer; presupuesto:Integer;--presupuesto del director oferta:Integer; begin --inicializamos al director accept init_director(id_d: in Integer; tipo: clase) do

157

Programaci n Concurrente o
id:=id_d; posi:= Positive_random(3);--posicion que quiere el director presupuesto:= Positive_Random(MAXPRE); --asignamos presupuesto decision:=nada; oferta:=0; for i in 1..MAXJUG loop lista(i) := 0; --se inicializa la lista end loop; t:=tipo; end init_director; if t = TV then --el director de todo vale se crea su lista for i in 1..MAXJUG loop jugadores(i).cuanto_vales(aux_precio,aux_posicion); if aux_precio < presupuesto then --mientras haya presupuesto lista(i) := aux_precio; presupuesto:= presupuesto-aux_precio;--se lo restamos al --presupuesto para saber cuanto le queda end if; end loop; else for i in 1..MAXJUG loop jugadores(i).cuanto_vales(aux_precio,aux_posicion); if aux_precio < presupuesto and aux_posicion = posi then lista(i) := aux_precio; presupuesto:= presupuesto-aux_precio;--se lo restamos al --presupuesto para saber cuanto le queda end if; end loop; end if; put_line("El director: "&IntegerImage(id) &" ha hecho su lista");

180 181

182

183 184 185 186 187 188 189 190 191 192 193 194

195 196

197 198 199 200 201 202 203 204

205 206

207 208 209 210 211 212 213 214 215 216 217 218

219 220 221 222 223 224 225 226

--realizamos las ofertas for i in 1..MAXJUG loop if lista(i) /= 0 then --le hago oferta oferta:= Positive_Random(lista(i)+100); --hago la oferta jugadores(i).ver_oferta(id,oferta,decision); --se la hago ver end if; end loop; loop select accept mandar_decision(id_j: in Integer; decision: contestacion) do if decision = si then

227

158

Pr ctica 5 - Directores Deportivos a


put_line("El director "&IntegerImage(id)& " ha fichado al"& " jugador: "&IntegerImage(id_j)); else put_line("El director "&IntegerImage(id)& " NO ha fichado al"& " jugador : "&IntegerImage(id_j)); end if; end mandar_decision; or terminate; end select; end loop; end director;

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

task body reloj is id_jugador:Integer; --identificador del jugador begin loop select accept init_reloj(id_j : Integer) do id_jugador:=id_j; end init_reloj; delay (10.0); jugadores(id_jugador).decidir; or terminate; end select; end loop; end reloj;

tipo: clase; posi: Integer; begin

put_line("---------PRACTICA 5--------"); put_line("---DIRECTORES DEPORTIVOS---"); put_line("---------C I T A S--------"); for i in 1..MAXJUG loop posi:= Positive_random(3); jugadores(i).init_jugador(i,posi); delay duration(Positive_random(2)); end loop; for i in 1..MAXDIR loop if Positive_Random(2) = 1 then tipo:=TV; else

159

Programaci n Concurrente o
tipo:= SE; end if; directores(i).init_director(i,tipo); delay duration(Positive_random(2)); end loop; end directores_citas;

284 285 286 287 288 289 290

160

Pr ctica 5 - Directores Deportivos a

5.3
5.3.1

Resoluci n por monitores en Ada o


Explicaci n o

En la resoluci n de la pr ctica por monitores ada o tipos protegidos, se establece el tipo protegido o a jugador. Cada jugador ser un monitor. Tambi n tendremos las tareas director, que negociaran a e con los jugadores, y por ultimo tendremos una tarea reloj, cada jugador dispone de uno. El reloj delimitar el tiempo que cada jugador tiene para decidirse. a Pasamos a explicar las tareas una por una. 1. La tarea jugador es la principal de la pr ctica. Esta tarea representa el monitor, cada jugador a es un monitor. El monitor est formado por los siguientes procedimientos. a init jugador Inicializa todas las variables que utilizara el monitor. ver oferta Este procedimiento se utiliza cuando un director desea realizar una oferta a un jugador, el director llama a este procedimiento y puden ocurrir tres cosas: La primera es que la oferta realizada por el director, sea mayor que el precio del jugador, en ese caso el jugador acepta la oferta directamente. La segunda cosa que puede ocurrir es que el jugador se lo piense en ese caso no dar una respuesta denitiva al director. Y la tercera cosa que a puede pasar es que el jugador ya este vendido a otro director, en ese caso el jugador rechaza la oferta. decidir oferta Este procedimiento se utiliza cuando el director consulta peri dicamente o a los jugadores que a los que ha hecho una oferta, el jugador les puede responder, positivamente aceptando la oferta, puede decirle que todava no se ha decidido , o que ya est a vendido. decidir Este procedimiento se utiliza cuando se acaba el tiempo de decision del jugador, entonces el jugador tiene que decidirse por una oferta, en el caso de que tenga ofertas, y comunicar su decision al o los directores que le han hecho ofertas. cuanto vales Este procedimiento se utiliza para que el director sepa el precio y la posicion del jugador. cuantas ofertas Este procedimiento sirve para saber las ofertas que ha tenido un jugador. 2. La tarea director: esta tarea se ocupa de negociar con los jugadores, pueden existir dos tipos de directores de TodoVale y de selecci n, estos ultimos realizan su lista de jugadores o dependiendo de la posici n en que juga cada jugador. Este tipo de directores le interesa solo o una posici n en concreto. o Despu s de realizar su lista, el director hace ofertas a los jugadores, e ir preguntado a todos e a los jugadores a los que ha hecho ofertas hasta que cada uno de ellos le conteste, ya sea armativa o negativamente. 3. La tarea reloj, esta tarea espera un tiempo determinado TJ y despu s hace decidir obligatoe riamente a los jugadores.

5.3.2

C digo Fuente o
161

Programaci n Concurrente o C digo fuente 5.2: Directores Deportivos por monitores en Ada o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure directores_tp is MAXJU : Integer:=5;--numero de jugadores MAXDIR : Integer:=3;--numero de directores deportivos TJ : Integer:= 10; --tiempo espera jugador MAXPRE : Integer:= 20000; --maximo presupuesto MAXPREJU : Integer:= 5000; --maximo precio de un jugador type clase is (TV,SE); -- tipo todo vale o selectivo type ofertas is array (1..MAXDIR) of Integer; type contestacion is (nose, si, no,nada); --decision del jugador type lista_jugadores is array (1..MAXJU) of Integer; protected type jugador is --inicializa al jugador procedure init_jugador(id:in Integer; posicion: in Integer); --ve las ofertas de los directores procedure ver_oferta(id_director:in integer; oferta:in Integer; decision: out contestacion); --sirve para consultar is un jugador se ha decidido o no procedure decidir_oferta(id_director: in Integer; decision: out contestacion); --se decide definitivamente por una procedure decidir; --para saber el precio del jugador procedure cuanto_vales(aux_precio: out Integer; aux_posicion: out Integer); --para saber cuantas ofertas se le han realizado procedure cuantas_ofertas(n: out Integer); --para saber cuantas ofertas tiene

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

39 40 41 42 43

44 45 46 47 48 49 50 51

private precio: Integer; --coste del jugador nofertas: Integer; --numero de ofertas propuestas: ofertas; --se guarda las ofertas del los directores vendido: boolean; --saber si esta vendido o no id_j: Integer; -- id del jugador pos: Integer; --posicion del jugador director_jug: Integer; --director al que se vende mejor_oferta: Integer; --guarda la mejor oferta hasta el momento. mejor_director: Integer; --guarda el mejor director que le ha hecho oferta end jugador; --definicion tarea director task type director is entry init_director(id:Integer; tipo: clase); end director;

162

Pr ctica 5 - Directores Deportivos a

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

--definicion tarea reloj task type reloj is entry init_reloj(id_jugador:Integer); end reloj; protected body jugador is procedure init_jugador(id:Integer;posicion: in Integer) is begin id_j:= id; --id del jugador pos:= posicion; --posicion del jugador precio:= Positive_Random(MAXPREJU); -- coste del jugador vendido:= false; --todavia no esta vendido director_jug:= -1; --no tiene asignado un director nofertas:= 0; --numero de ofertas mejor_oferta:=-1;-- mejor oferta hasta el momento mejor_director:=-1; -- mejor director hasta el momento. put_line("Jugador: "&IntegerImage(id_j)&" juega en la posicion: " &IntegerImage(pos)&" y cuesta: "&IntegerImage( precio)); end init_jugador; procedure ver_oferta(id_director:in integer; oferta:in Integer; decision: out contestacion) is begin put_line("Al Jugador: "&IntegerImage(id_j) &" le ha llegado una oferta del director "& IntegerImage(id_director)); if vendido = false then if oferta > precio then --si la oferta es mayor que el precio, vendido. vendido := true; decision:= si; director_jug := id_director; nofertas:= 0; put_line("JUGADOR VENDIDO DIRECTAMENTE"); else put_line("JUGADOR ESPERA"); propuestas(id_director):=oferta; decision:=nose; nofertas:= nofertas+1; --tenemos una oferta mas if oferta > mejor_oferta then mejor_oferta:= oferta; --guardamos la mejor oferta mejor_director:= id_director; --guardamos el mejor director end if; end if; else decision:=no; --ya estoy vendido. La rechazo put_line("El jugador: "&IntegerImage(id_j) &" ha rechazado al director: "&

71

72 73 74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

95 96 97 98 99 100 101 102 103

163

Programaci n Concurrente o
IntegerImage(id_director)&" porque ya esta vendido"); nofertas:=0; end if; end ver_oferta; procedure decidir_oferta(id_director: in Integer; decision: out contestacion) is begin if vendido = true and director_jug = id_director then decision:= si; --acepta la oferta put_line("El jugador: "&IntegerImage(id_j) &" ha sido vendido al director: "& IntegerImage(id_director)); elsif vendido = true and director_jug /= id_director then decision:= no; -- le erechaza put_line("El jugador: "&IntegerImage(id_j) &" ha rechazado al director: "& IntegerImage(id_director)); else decision:= nose; end if; end decidir_oferta; procedure decidir is begin put_line("EL jugador"&IntegerImage(Id_j)&" decide por narices"); if vendido = false and nofertas > 0 then --el jugador no se ha decidido --entonces aceptamos la mejor oferta del mejor director put_line("El jugador: "&IntegerImage(id_j) &" ha sido vendido al director: "& IntegerImage(mejor_director) &" por la catidad de "&IntegerImage( mejor_oferta)); vendido := true;--es vendido director_jug:= mejor_director; -- se le asigna director else put_line("El jugador: "&IntegerImage(id_j) &" no tiene ofertas"); vendido := false; director_jug:=-2;--no tiene ofertas; end if; end decidir; --permite saber cual es el precio del jugador y su posicion procedure cuanto_vales(aux_precio: out Integer; aux_posicion: out Integer) is begin aux_precio:= precio; aux_posicion:= pos; end cuanto_vales;

104

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

131 132 133 134 135 136 137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

164

Pr ctica 5 - Directores Deportivos a

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

--permite saber el numero de ofertas del jugador procedure cuantas_ofertas(n: out Integer) is begin n:=nofertas; end cuantas_ofertas; end jugador;

jugadores: array(1..MAXJU) of jugador; task body reloj is id_j:Integer; t:Integer;--tiempo begin

--array de jugadores

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203

select accept init_reloj(id_jugador:Integer) do id_j:=id_jugador; --id del jugador al que pertence el reloj t:=TJ; --tiempo de espera del jugador end init_reloj; delay duration(t); jugadores(id_j).decidir; or terminate; end select; end reloj;

relojes: array(1..MAXJU) of reloj; --cada reloj tiene un jugador task body director is id_d: Integer;--id del director tipo_d: clase; --clase del director decision: contestacion; --decision del jugador lista:lista_jugadores; --lista de jugadores aux_precio:Integer; --variable auxiliar para guardar el precio del jugador aux_posicion:Integer; --variable auxiliar para guardar la posicion del jugador presupuesto: Integer; --el presupuesto con el que cuenta el director oferta:Integer;--la oferta que realizara le director ofertas_espera:Integer; n:Integer; --se utiliza para saber cuantas ofertas tiene posi:Integer;--la posicion que quiere el director en caso de que --sea tipo selectivo SE

204 205 206 207 208 209 210

begin accept init_director(id:Integer; tipo: clase) do id_d:= id; --id del director tipo_d:= tipo; --tipo de director

165

Programaci n Concurrente o
presupuesto:= Positive_Random(MAXPRE); --asignamos presupuesto aux_precio:=0; --precio auxiliar aux_posicion:=0; -- posicion auxiliar oferta:=0; --oferta del director decision:=nada; --decision del director ofertas_espera:=0; --ofertas en espera posi:= Positive_random(3); for i in 1..MAXJU loop lista(i) := 0; --se inicializa la lista end loop; if tipo_d = TV then --el director de todo vale se crea su lista for i in 1..MAXJU loop jugadores(i).cuanto_vales(aux_precio,aux_posicion); if aux_precio < presupuesto then --mientras haya presupuesto lista(i) := aux_precio; presupuesto:= presupuesto-aux_precio;--se lo restamos al --presupuesto para saber cuanto le queda end if; end loop; else for i in 1..MAXJU loop jugadores(i).cuanto_vales(aux_precio,aux_posicion); if aux_precio < presupuesto and aux_posicion = posi then lista(i) := aux_precio; presupuesto:= presupuesto-aux_precio;--se lo restamos al --presupuesto para saber cuanto le queda end if; end loop; end if; put_line("El director : "&IntegerImage(Id_d) &" y de tipo: " &claseimage(tipo_d) &" ha hecho su lista"); end init_director; for i in 1..MAXJU loop if lista(i) /= 0 then --le hago oferta oferta:= Positive_Random(lista(i)+100); --hago la oferta jugadores(i).ver_oferta(id_d,oferta,decision);--se la hago ver if decision = si then lista(i):=0; elsif decision = no then

211 212 213 214 215 216 217 218 219 220 221 222 223 224

225 226 227 228 229 230

231 232 233 234 235 236 237 238

239 240

241 242 243 244 245 246 247 248 249 250 251 252 253

254

255 256 257 258 259 260

166

Pr ctica 5 - Directores Deportivos a


lista(i):=0; elsif decision = nose then ofertas_espera:=ofertas_espera+1; jugadores(i).cuantas_ofertas(n); if n = 1 then relojes(i).init_reloj(i); end if; end if; end if; end loop; put_line("OFERTAS EN ESPERA: "&IntegerImage(ofertas_espera)) ; loop for i in 1..MAXJU loop if lista(i) /= 0 then jugadores(i).decidir_oferta(id_d,decision); if decision = si then lista(i):=0; ofertas_espera:=ofertas_espera-1; put_line("Al director: "&IntegerImage(id_d)& "le quedan:" &IntegerImage(ofertas_espera) &" ofertas por saber"); elsif decision = no then lista(i):=0; ofertas_espera:=ofertas_espera-1; put_line("Al director: "&IntegerImage(id_d) & "le quedan: "&IntegerImage( ofertas_espera) &" ofertas por saber"); end if; delay(2.0); end if; end loop; exit when ofertas_espera = 0; --cuando ya no quedan ofertas sale. end loop; put_line("el director: "&IntegerImage(id_d) & "termina de negociar "); end director;

261 262 263 264 265 266 267 268 269 270 271 272

273 274 275 276 277 278 279 280 281

282 283 284 285 286 287 288

289 290 291 292 293 294

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312

directores: array (1..MAXDIR) of director;

tipo: clase; posi: Integer; begin put_line("---------PRACTICA 5--------"); put_line("---DIRECTORES DEPORTIVOS---");

167

Programaci n Concurrente o
put_line("T I P O S P R O T E G I D O S");

313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333

for i in 1..MAXJU loop posi:= Positive_random(3); jugadores(i).init_jugador(i,posi); delay duration(Positive_random(2)); end loop; for i in 1..MAXDIR loop if Positive_Random(2) = 1 then tipo:=TV; else tipo:= SE; end if; directores(i).init_director(i,tipo); delay duration(Positive_random(2)); end loop;

end directores_tp;

168

Pr ctica 5 - Directores Deportivos a

5.4
5.4.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 25 o 26 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 7 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 8 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o

5.4.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

5.4.3

Dicultad

Por monitores en Ada: Dicultad de 6 sobre 10. Por citas en Ada: Dicultad de 6 sobre 10.

169

Programaci n Concurrente o

170

Pr ctica 6 - Servicio de Atenci n de Urgencias a o

Pr ctica 6 a

Servicio de Atenci n de Urgencias o


6.1 Enunciado

Se montado un dispositivo de atenci n urgente y est en periodo de pruebas. El dise o que se ha o a n hecho es que cuando se produce una llamada puede ser porque se est cometiendo un delito, o una a urgencia m dica. Una vez identicado el incidente, la llamada se deriva a la central de polica o al e hospital o centro de salud correspondiente. Si es un delito, la patrulla de la polica m s cercana disponible, se dirigir al lugar de los a a hechos. Puede ocurrir que la polica detenga al delincuente, o bien que escape. Si lo detiene, lo llevar a comisara. Tambi n puede que sea una falsa alarma. A veces, es necesario enviar a a e varias patrullas si el delito es grave o si se necesitan refuerzos. Una patrulla que lleva a un detenido puede que tenga que intervenir en otro incidente de camino a la comisara. En la comisara siempre hay alguien atendiendo el tel fono o haciendo otras cosas propias del papeleo administrativo. Y e tambi n, si no tiene mucho trabajo, puede echarse una siestecita. Ante una urgencia m dica, el e e centro de control correspondiente tomar una decisi n, que bien puede ser enviar una UVI m vil o a o o simplemente una ambulancia para recoger al enfermo. El tiempo que tarde en llegar tanto la polica como la ambulancia al lugar de los hechos va a depender de la distancia a la que se encuentren, y ser determinante para resolver satisfactoriamente el incidente. a A veces es necesario enviar tanto una ambulancia como a la polica, seg n el incidente. Otras u veces, ser la polica la que solicite una ambulancia, o los m dicos o el conductor de la ambulancia a e los que soliciten la presencia policial. Tanto ambulancias como coches patrulla disponen de una comunicaci n entre ellos, sin necesio dad de pasar por sus centrales. El sistema debe ser capaz de aprender de los incidentes, y por ejemplo, si en una zona se producen muchas llamadas de robos, puede que sea conveniente situar un coche patrulla por la zona (o varios) con el n de minimizar el tiempo de respuesta. Y lo mismo con las urgencias m dicas. e En el momento en el que se compruebe que se trata de una falsa alarma o que el incidente est a solucionado se pondr en contacto de las unidades que se dirijan a solucionar el problema, para a poder dedicar los recursos a otros incidentes. Las unidades cuando terminan su servicio diario vuelven a su central, y son relevadas por otras. El relevo se hace en varios turnos (al menos tres) con el objeto de mantener en alerta el sistema, y que no se produzcan tiempos muertos, que pudieran, para el caso de la polica, ser utilizados por los delincuentes. 171

Programaci n Concurrente o

6.2
6.2.1

Resoluci n por Citas en Ada o


Explicaci n o

Para resolver esta pr ctica, hemos creado las siguientes tareas (o tipos de tareas): a Comisara: Se encarga de atender a las llamadas de la polica y enviar los coches patrulla necesarios. Adem s, tambi n recibe a los delincuentes capturados por la polica. a e Hospital: Atiende las urgencias m dicas, enviando ambulancias y UVIs seg n sea la e u urgencia. Adem s recibe a los vehculos m dicos que terminan el servicio. a e Contolador: Sirve de ayuda a la hora de, por ejemplo, encontrar una patrulla cercana a un lugar de llamada, obtener el ID de una ambulancia libre, actualizar el estado de los vehculos (de libre a ocupado, y viceversa), etc. Ambulancia y UVI: Atiende avisos del Hospital. Si es necesario, una ambulancia puede solicitar una patrulla en el lugar de la urgencia. Patrulla: Atiende avisos de la comisara y va al lugar de urgencia. Trata de detener al delincuente, pidiendo ayuda si es necesario, y si lo consigue lo lleva a comisara. En caso de que el delincuente escape, la patrulla vuelve a comisara. Jornada: Simula las jornadas de trabajo de las patrullas, poni ndoles a trabajar o haci ndoles e e dormir. Central: Recibe las llamadas de urgencia, tanto de urgencias m dicas como policiales, y e se encarga de derivar esas llamadas al Hospital y a la Comisara, seg n sea necesario. u Generador de llamadas: Como su propio nombre indica, se encarga de generar llamadas aleatorias para la central. El generador de llamadas se encarga de llamar a la Central para avisar de una urgencia. La Central estudia el tipo de urgencia y deriva la urgencia al Hospital, a la Comisara, o a ambos. Estos buscan patrullas y/o ambulancias/uvis libres, y las envan al lugar de la urgencia.

6.2.2

C digo fuente o
C digo fuente 6.1: Servicio de Atenci n de Urgencias por citas en Ada o o

1 2 3 4 5 6 7 8 9 10 11

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure Urgencias is NUM_COCHES: constant Integer := 10; NUM_LUGARES: constant Integer := 10; NUM_AMBULANCIAS: constant Integer := 6; NUM_UVIS: constant Integer := 4; ESPERA_MAX: constant Integer := 3; --Tiempo de espera maximo sin llamadas

172

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


DURACION_JORNADA: constant Integer := 3; --Tiempo que dura una jornada. TIEMPO_LLEGAR: constant Integer := 2; TIEMPO_VUELTA_COMISARIA: constant Integer := 3; --Tiempo que se tarda en volver a la comisaria type Tipo_Urgencia is (DELITO, URGENCIA, AMBOS); type Tipo_Estado_Vehiculo is (Disponible, Ocupada, Descanso, Volviendo); type Lugar_Policia is array (1..NUM_COCHES) of Integer; type Distancia_Coches is array (1..2) of Integer; type Estado_Policias is array (1..NUM_COCHES) of Tipo_Estado_Vehiculo; type Estado_Ambulancias is array (1..NUM_AMBULANCIAS) of Tipo_Estado_Vehiculo; type Estado_Uvis is array (1..NUM_UVIS) of Tipo_Estado_Vehiculo; type Vehiculos_Sanitarios is (Amb, UviMov); type Num_Coches_Necesarios is array (1..2) of Integer; task Central is entry Init; entry Llamada(tipo: in Tipo_Urgencia; lugar: in Integer); end Central; task type Jornada is entry Init; end Jornada; task Generador_Llamadas is entry Init; end Generador_Llamadas; task Comisaria is entry Init; entry LlamadaPolicia(lugar: in Integer); entry LlevarDelincuente(x: in Integer); end Comisaria; task Hospital is entry Init; entry LlegadaVehiculo(tiempo: in Integer; numero: in Integer; tipo: in Vehiculos_Sanitarios); entry Urgencia(lugar: in Integer); end Hospital; task Controlador is entry Init; entry Policia_Optimo(sitio: in Integer; ok: out boolean; num: out Integer; distancia: out Integer); --Encuentra al policia libre mas cercano entry ObtenerEstado(x: in Integer; state: out Tipo_Estado_Vehiculo); entry VolverComisaria(coche: in Integer); -- Coche patrulla vuelve a comisaria

12

13 14

15 16 17

18 19 20 21

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

50 51 52 53 54 55

56

57

173

Programaci n Concurrente o
entry Ambulancia_Libre(num: out Integer; ok: out boolean); -Nos dice si una ambulancia esta libre entry UVI_Libre(num: out Integer; ok: out boolean); entry LlegaUvi(numero: in Integer); -- Una UVI llega al hospital entry LlegaAmbulancia(numero: in Integer);-- Una ambulancia llega al hospital entry LlegaPolicia(x: in Integer); entry Que_Patrulla_Vuelve(num: out Integer); -- Dice que coche de policia esta volviendo a la comisaria entry Descansa_Ahora(x: in Integer); -- Damos descanso a un policia entry A_Currar(x: in Integer); -- Se acaba el descanso end Controlador; task type Tipo_Tarea_Ambulancia is entry Init(x:in Integer); entry Pedido(lugar: in Integer); -- Llamada cuando se necesite la ambulancia end Tipo_Tarea_Ambulancia; task type Tipo_Tarea_UVI is entry Init(x: in Integer); entry Pedido(lugar: in Integer); --Se llamar cuando se necesite esta Uvi end Tipo_Tarea_UVI; task type Tipo_Tarea_Patrulla is entry Init(x: in Integer); entry Llamada(sit: in Integer; distancia: in Integer); --Se llamar cuando se necesite a esta coche de policia. entry AyudaPedida; end Tipo_Tarea_Patrulla; -- Elementos de la simulacion Ambulancias: array (1..NUM_AMBULANCIAS) of Tipo_Tarea_Ambulancia ; Coches_Patrulla: array (1..NUM_COCHES) of Tipo_Tarea_Patrulla; Uvis: array (1..NUM_UVIS) of Tipo_Tarea_UVI; JLaboral: Jornada; -- JORNADA: Controla que policias trabajan y cuales descansan -task body Jornada is x: Integer := 1; begin accept Init; loop for i in x..x+2 loop Controlador.Descansa_Ahora(i); end loop; delay Duration(DURACION_JORNADA); for i in x..x+2 loop Controlador.A_Currar(i); end loop; if x /= NUM_COCHES then

58

59 60

61

62 63

64

65 66 67 68 69 70

71 72 73 74 75

76 77 78 79 80

81 82 83 84 85

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

174

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


x := x+ 3; if x + 3 >= NUM_COCHES then x := NUM_COCHES; end if; else x := 1; end if; end loop; end Jornada; -- AMBULANCIA: Rerpesenta el funcionamiento de las ambulancias -task body Tipo_Tarea_Ambulancia is id: Integer; destino: Integer; distancia: Integer; distanciaAgente: Integer; agente: Integer; ok : boolean; begin accept Init(x:in Integer) do id := x; end Init; loop destino := 0; select accept Pedido(lugar: in Integer) do destino := lugar; put_line("AMBULANCIA"& IntegerImage(id) &" va al LUGAR"&IntegerImage(lugar)); end Pedido; or terminate; end select; if Positive_Random(3) = 1 then -- Se requiere de una patrulla put_line("Se requiere de policia en el lugar "&Integer Image(destino)&", buscando policia..."); Controlador.Policia_Optimo(destino, ok, agente, distanciaAgente); if ok then Coches_Patrulla(agente).Llamada(destino, distanciaAgente); --Si lo hemos encontrado lo llamamos. else put_line("NINGUN POLICIA DISPONIBLE para ir al lugar "&IntegerImage(destino)); end if; end if; delay Duration(TIEMPO_LLEGAR); distancia := Positive_Random(NUM_LUGARES); Hospital.LlegadaVehiculo(distancia, id, Amb); --Se vuelve al hospital end loop; end Tipo_Tarea_Ambulancia;

105 106 107 108 109 110 111 112 113 114 115

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

134 135 136 137 138

139

140

141 142

143 144

145 146 147 148 149

150 151

175

Programaci n Concurrente o

152 153

-- COCHE PATRULLA: Representa el funcionamiento de los policias -task body Tipo_Tarea_Patrulla is id: Integer; state: Tipo_Estado_Vehiculo; dist : Integer; destino: Integer; num: Integer; aux: Integer; numAyuda: Integer; ok: boolean; begin accept Init(x:in Integer) do id := x; end Init; loop select accept Llamada(sit: in Integer; distancia: in Integer) do put_line("COCHE PATRULLA"&IntegerImage(id)&" va al lugar"&IntegerImage(sit)); dist := distancia; destino := sit; end Llamada; or terminate; end select; if Positive_Random(2) = 1 then -- Se requieren refuerzos de los coches que vuelven put_line("COCHE PATRULLA"&IntegerImage(id)&" pide ayuda a un coche de los que estan volviendo."); Controlador.Que_Patrulla_Vuelve(num); --Buscaremos un coche que e s t volviendo para que nos ayude. if num /= 0 then Coches_Patrulla(num).AyudaPedida; end if; end if; aux := Positive_Random(4); if aux = 1 then -- Se necesita una ambulancia put_line("COCHE PATRULLA"&IntegerImage(Id)&" solicita ambulancia en el sitio "&IntegerImage(destino)); Controlador.Ambulancia_Libre(numAyuda,ok); if ok then Ambulancias(numAyuda).Pedido(destino); else put_line("NINGUNA AMBULANCIA DISPONIBLE para ir al lugar"&IntegerImage(destino)); end if; elsif aux = 2 then -- Se necesita una UVI put_line("COCHE PATRULLA"&IntegerImage(Id)&" solicita UVI en el sitio "&IntegerImage(destino)); Controlador.UVI_Libre(numAyuda,ok); if ok then Uvis(numAyuda).Pedido(destino);

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

171

172 173 174 175 176 177 178

179

180

181 182 183 184 185 186 187

188 189 190 191 192

193 194 195

196 197 198

176

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


else put_line("NINGUNA UVI DISPONIBLE para ir al lugar"& IntegerImage(destino)); end if; end if; delay Duration(TIEMPO_LLEGAR); if dist > NUM_LUGARES/2 then put_line("DELINCUENTE ESCAPA del lugar"&IntegerImage( destino)); Controlador.LlegaPolicia(id); else put_line("DELINCUENTE CAPTURADO en el lugar: "&Integer Image(destino)&". Se le lleva a comisaria."); Controlador.VolverComisaria(id); select accept AyudaPedida do put_line("COCHE PATRULLA"&IntegerImage(id)&" va a ayudar a otra patrulla."); end AyudaPedida; or delay Duration(TIEMPO_VUELTA_COMISARIA); Controlador.ObtenerEstado(id, state); -- Comprobamos si hay que ayudar a alguien if state = Ocupada then accept AyudaPedida do put_line("COCHE PATRULLA"&IntegerImage(id)&" va a ayudar a otra patrulla."); end AyudaPedida; end if; end select; Comisaria.LlevarDelincuente(id); --Volvemos a la comisaria. end if; end loop; end Tipo_Tarea_Patrulla; -- UVI: Simula el comportamiento de una unidad UVI de las del problema -task body Tipo_Tarea_UVI is id: Integer; dist: Integer; begin accept Init(x:in Integer) do id := x; end Init; loop select accept Pedido(lugar: in Integer) do put_line("UVI"&IntegerImage(id)&" va al lugar: "& IntegerImage(lugar)); end Pedido; or terminate; end select; delay Duration(TIEMPO_LLEGAR);

199 200

201 202 203 204 205

206 207 208

209 210 211 212

213 214 215 216

217 218 219

220 221 222 223

224 225 226 227 228

229 230 231 232 233 234 235 236 237 238 239 240

241 242 243 244 245

177

Programaci n Concurrente o
dist := Positive_Random(NUM_LUGARES); Hospital.LlegadaVehiculo(dist, id, UviMov); end loop; end Tipo_Tarea_UVI; -- CONTROLADOR -task body Controlador is totalAmbulancias: Integer := 0; --Numero de ambulancias ocupadas. totalUVIS: Integer := 0; --Numero de UVIS ocupadas. totalPolicias: Integer := 0; --Numero de policias ocupados. PoliciasLibres: Estado_Policias; --Guardamos el estado de cada policia. AmbulanciasLibres: Estado_Ambulancias; --Guardamos el estado de las ambulancias libres. UvisLibres: Estado_Uvis; --Guardamos el estado de las UVIS libres. i: Integer := 1; --auxiliar. CPolicias: Lugar_Policia; --Lugares donde e s t n los coches de policia. maxCercano: Integer; --Guardamos el policia m s cercano. escogido: Integer; --Guardamos el policia escogido. begin accept Init do for i in 1..NUM_AMBULANCIAS loop AmbulanciasLibres(i) := Disponible; end loop; for i in 1..NUM_UVIS loop UvisLibres(i) := Disponible; end loop; for i in 1..NUM_COCHES loop CPolicias(i) := Positive_Random(NUM_LUGARES); PoliciasLibres(i) := Disponible; end loop; end Init; loop maxCercano := 12; escogido := 0; i := 1; select accept Policia_Optimo(sitio: in Integer; ok: out boolean; num: out Integer; distancia: out Integer) do if totalPolicias < NUM_COCHES then for i in 1..NUM_COCHES loop if PoliciasLibres(i) = Disponible and CPolicias(i) < maxCercano then maxCercano := CPolicias(i); escogido := i; end if; end loop; PoliciasLibres(escogido) := Ocupada; CPolicias(escogido) := maxCercano; num := escogido; ok := true;

246 247 248 249 250 251 252 253 254

255 256 257

258

259

260 261

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

283 284 285

286 287 288 289 290 291 292 293

178

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


totalPolicias := totalPolicias + 1; distancia := maxCercano; else ok := false; num := 0; end if; end Policia_Optimo; or --Nos vale para indicar a un policia que tiene que ayudar. accept ObtenerEstado(x: in Integer; state: out Tipo_Estado_Vehiculo) do if PoliciasLibres(x) = Volviendo then PoliciasLibres(x) := Ocupada; end if; state := Volviendo; end ObtenerEstado; or --Cambia el estado de un policia para indicar que e s t volviendo a la comisaria. accept VolverComisaria(coche: in Integer) do PoliciasLibres(coche) := Volviendo; end VolverComisaria; or --Nos devuelve el n mero de una ambulancia que e s t libre. accept Ambulancia_Libre(num: out Integer; ok: out boolean) do if totalAmbulancias < NUM_AMBULANCIAS then while AmbulanciasLibres(i) /= Disponible loop i := i + 1; end loop; AmbulanciasLibres(i) := Ocupada; num := i; ok := true; totalAmbulancias := totalAmbulancias + 1; else ok := false; num := 0; end if; end Ambulancia_Libre; or --Nos devuelve el n mero de una UVI que e s t libre. accept UVI_Libre(num: out Integer; ok: out boolean) do if totalUVIS < NUM_UVIS then while UvisLibres(i) /= Disponible loop i := i + 1; end loop; UvisLibres(i) := Ocupada; num := i; ok := true; totalUVIS := totalUVIS + 1; else ok := false; num := 0; end if;

294 295 296 297 298 299 300 301 302

303

304 305 306 307 308 309 310

311 312 313 314 315

316

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344

179

Programaci n Concurrente o
end UVI_Libre; or --Cambia el estado de la UVI a libre. accept LlegaUvi(numero: in Integer) do UvisLibres(numero) := Disponible; totalUVIS := totalUVIS - 1; end LlegaUvi; or --Cambia el estado de la ambulancia a libre. accept LlegaAmbulancia(numero: in Integer) do AmbulanciasLibres(numero) := Disponible; totalAmbulancias := totalAmbulancias - 1; end LlegaAmbulancia; or --Cambia el estado del coche de policia a libre. accept LlegaPolicia(x: in Integer) do if PoliciasLibres(x) /= Descanso then PoliciasLibres(x) := Disponible; totalPolicias := totalPolicias - 1; CPolicias(x) := Positive_Random(NUM_LUGARES); end if; end LlegaPolicia; or --Nos devuelve un n mero de coche que e s t volviendo a comisaria. accept Que_Patrulla_Vuelve(num: out Integer) do while PoliciasLibres(i) /= Volviendo and i < NUM_COCHES+1 loop i := i + 1; end loop; if i /= NUM_COCHES + 1 then PoliciasLibres(i) := Ocupada; num := i; else num := 0; end if; end Que_Patrulla_Vuelve; or --Cambia el estado de un coche de policia a descansando . accept Descansa_Ahora(x: in Integer) do if PoliciasLibres(x) = Disponible then totalPolicias := totalPolicias + 1; end if; PoliciasLibres(x) := Descanso; end Descansa_Ahora; or --Cambia el estado de un coche de policia a disponible. accept A_Currar(x: in Integer) do PoliciasLibres(x) := Disponible; totalPolicias := totalPolicias - 1; CPolicias(x) := Positive_Random(NUM_LUGARES); end A_Currar; or terminate; end select;

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

369 370

371 372 373 374 375 376 377 378 379 380 381

382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

180

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


end loop; end Controlador; -- HOSPITAL: Simula el centro sanitario del problema -task body Hospital is Han_pedido_vehiculo: boolean := false; --Nos indica si nos han pedido un vehiculo. Tipo_vehiculo_pedido : Vehiculos_Sanitarios; --Indica que tipo de vehiculo nos han pedido. destino : Integer; --Indica al sitio donde tiene que ir. num: Integer; -- A q u tendremos el n mero de v e h culo que llamaremos. ok : boolean; --Variable auxiliar que nos dice si hemos encontrado un v e h culo . begin accept Init; loop Han_pedido_vehiculo := false; select accept Urgencia(lugar: in Integer) do --Aceptamos una Urgencia. destino := lugar; if Positive_Random(2) = 1 then Controlador.Ambulancia_Libre(num, ok); --Si necesitamos ambulancia. if ok then --Si hemos encontrado una ambulancia. put_line("Se manda una ambulancia al lugar: "& IntegerImage(lugar)); Han_pedido_vehiculo := true; Tipo_vehiculo_pedido := Amb; else put_line("No se puede mandar una Ambulancias porque no hay disponibles."); end if; else Controlador.UVI_Libre(num, ok); --Si necesito una UVI. if ok then --Si hemos encontrado una UVI. put_line("Se manda una UVI al lugar: "&Integer Image(lugar)); Han_pedido_vehiculo := true; Tipo_vehiculo_pedido := UviMov; else put_line("No se puede mandar una UVI porque no hay disponibles."); end if; end if; end Urgencia; or --Nos indica que un v e h culo sanitario vuelve. accept LlegadaVehiculo(tiempo: in Integer; numero: in Integer; tipo: in Vehiculos_Sanitarios) do if tiempo > NUM_LUGARES/2 then put_line("Se ha tardado mucho en llevar al enfermo y muere.");

398 399 400 401 402 403 404

405

406 407

408

409 410 411 412 413 414

415 416 417

418 419

420 421 422 423

424 425 426

427 428

429 430 431 432

433 434 435 436 437 438

439 440

181

Programaci n Concurrente o
else put_line("Se podra salvar al enfermo."); end if; if tipo = Amb then Controlador.LlegaAmbulancia(numero); else Controlador.LlegaUvi(numero); end if; end LlegadaVehiculo; or terminate; end select; if Han_pedido_vehiculo then --Si tenemos que mandar un v e h culo , se lo indicamos. if Tipo_vehiculo_pedido = Amb then Ambulancias(num).Pedido(destino); else Uvis(num).Pedido(destino); end if; end if; end loop; end Hospital; -- COMISARIA DE POLIC A -task body Comisaria is Han_pedido_vehiculo: boolean; --Nos indica si nos han pedido un vehiculo. destino: Integer; --Indica al sitio que tienen que ir; numeroCoches: Integer; --Si valor s e r el n mero de coches que hay que mandar. ok: boolean; --Variable booleana auxiliar. num: Num_Coches_Necesarios; --Coches que hay que mandar. distancia: Distancia_Coches; --Distancia de cada coche al lugar. begin accept Init; loop Han_pedido_vehiculo := false; numeroCoches := 0; select accept LlamadaPolicia(lugar: in Integer) do --Aceptamos una llamada. destino := lugar; numeroCoches := Positive_Random(2); for i in 1..numeroCoches loop --Podemos buscar varios policias. Controlador.Policia_Optimo(destino, ok, num(i), distancia(i)); --Buscamos un policia. if ok then Han_pedido_vehiculo := true; --Si lo encontramos despus lo llamamos. put_line("Se manda un policia al lugar: "& IntegerImage(lugar)); end if; end loop;

441 442 443 444 445 446 447 448 449 450 451 452 453

454 455 456 457 458 459 460 461 462 463 464 465 466

467 468

469 470 471

472 473 474 475 476 477 478

479 480 481

482

483 484

485

486 487

182

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


end LlamadaPolicia; or accept LlevarDelincuente(x: in Integer) do --Lleva un delincuente a la comisaria. put_line("Ha llegado a comisaria el coche: "&Integer Image(x)&" con un delincuente."); Controlador.LlegaPolicia(x); end LlevarDelincuente; or terminate; end select; if Han_pedido_vehiculo then --Si tenemos que mandar a l g n coche. for i in 1..numeroCoches loop if num(i) /= 0 then Coches_Patrulla(num(i)).Llamada(destino, distancia(i)); --Lo mandamos. end if; end loop; end if; end loop; end Comisaria;

488 489 490

491

492 493 494 495 496 497

498 499 500

501 502 503 504 505 506 507 508 509 510 511 512

513 514

515

516 517

518

519 520

521 522 523 524 525 526 527 528 529 530 531 532

task body Central is begin accept Init; loop accept Llamada(tipo: in Tipo_Urgencia; lugar: in Integer) do --Acepta urgencias. if tipo = DELITO then put_line("Se ha producido un delito en el lugar: "& IntegerImage(lugar)); Comisaria.LlamadaPolicia(lugar); --Si es un delito llama a la comisaria. elsif tipo = URGENCIA then put_line("Se ha producido una urgencia medica en el lugar: "&IntegerImage(lugar)); Hospital.Urgencia(lugar); --Si es una urgencia llama al Hospital. else put_line("Se ha producido una urgencia que necesita un policia y una ambulancia en el lugar: "& IntegerImage(lugar)); --Si se necesita ambos se llaman a ambos. Comisaria.LlamadaPolicia(lugar); Hospital.Urgencia(lugar); end if; end Llamada; end loop; end Central;

task body Generador_Llamadas is aux: Integer; tipo: Tipo_Urgencia;

183

Programaci n Concurrente o
begin accept Init; loop aux := Positive_Random(3); --Generamos un delito aleatorio . if aux = 1 then tipo := DELITO; elsif aux = 2 then tipo := URGENCIA; else tipo := AMBOS; end if; Central.Llamada(tipo, Positive_Random(10)); --Llamamos a la centralita. delay Duration(4.0); end loop; end Generador_Llamadas;

533 534 535 536

537 538 539 540 541 542 543 544

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572

begin Controlador.Init; Central.Init; Comisaria.Init; Hospital.Init; for i in 1..NUM_COCHES loop Coches_Patrulla(i).Init(i); end loop; for i in 1..NUM_AMBULANCIAS loop Ambulancias(i).Init(i); end loop; for i in 1..NUM_UVIS loop Uvis(i).Init(i); end loop; JLaboral.Init; Generador_Llamadas.Init; end Urgencias;

184

Pr ctica 6 - Servicio de Atenci n de Urgencias a o

6.3

Versi n simplicada o

Las siguientes soluciones (por citas y tipos protegidos) han sido planteadas para simplicar en gran medida la pr ctica. No son muy buenas, y desvirtuan en parte el problema inicial, pero las a mostraremos como a adido a la resoluci n de la pr ctica que ya hemos mostrado. n o a

6.3.1

Resoluci n por Citas en Ada o

Explicaci n o En esta versi n simplicada tenemos las siguientes tareas: o Central: Atiende los avisos de urgencias y avisa a la Comisaria y al Hospital seg n u sea el tipo de la urgencia. El tipo de urgencia es elegido aleatoriamente. Hospital: Procesa el aviso y notica, aleatoriamente, del envo de Ambulancia o UVI que se realizara. Comisara: Procesa las llamadas y, aleatoriamente, genera un resultado para el envo de una patrulla. Generador de llamadas: Genera llamadas aleatorias a la Central, indicando el lugar de la urgencia. El funcionamiento es el mismo que ya explicamos: el generador avisa a la Central, y esta al Hospital y a la Comisara. C digo fuente o

C digo fuente 6.2: Servicio de Atenci n de Urgencias (simplicado) por citas en Ada o o
1

with TEXT_IO,random,Ada.Exceptions; use TEXT_IO,random,Ada. Exceptions; procedure Urgencias_citas is type Lugar is record id: Integer; patrulla: Integer := 0; ambulancia: Integer := 0; UVI_movil: Integer := 0; end record; task Central is entry Init; entry llamada(Lug: in Integer); end Central; task type Hospital is entry Init(I: in Integer); entry avisar(Lug: in Integer);

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

185

Programaci n Concurrente o
end Hospital; task type Comisaria is entry Init(I: Integer); entry avisar(l: Integer); end Comisaria; task Generador_Llamadas is entry Init; end Generador_Llamadas; -- Constantes NUM_PATRULLAS: constant Integer := 3; NUM_AMBULANCIAS: constant Integer := 2; MAX_HOSPITAL: constant Integer := 3; NUM_COMISARIAS: constant Integer := 2; NUM_UVIS: constant Integer := 3; NUM_LUGARES:constant Integer := 5; -- Comisarias para atender los delitos Comisarias: array(1..NUM_COMISARIAS) of Comisaria; -- Hospitales para atender las urgencias Hospitales: array(1..MAX_HOSPITAL) of Hospital; -- Lugares donde ocurren las urgencias Lugares: array(1..NUM_LUGARES) of Lugar;

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

-- CENTRAL DE LLAMADAS -------------------------------task body Central is Aux, Hosp, Comis: Integer := 0; Contador, Lugar: Integer := 0; begin accept Init; loop select accept llamada(Lug: Integer) do Lugar := Lug; end llamada; put("[o] CENTRAL recibe llamada"&IntegerImage(Contador )&" (de "); Contador := Contador + 1; aux := Positive_Random(3); if Aux = 1 then -- Se trata de una urgencia Put_Line("URGENCIA)."); Hosp := positive_random(MAX_HOSPITAL); Put_Line(" -> Se avisa al Hospital "&IntegerImage( Hosp)&" desde el lugar "&IntegerImage(Lugar)&"." ); Hospitales(Hosp).avisar(lugar); elsif Aux = 2 then -- Se trata de un delito Put_Line("DELITO)."); Comis := positive_random(NUM_COMISARIAS); Put_Line(" -> Se avisa a la Comisaria"&Integer Image(Comis)& " desde el lugar "&IntegerImage( Lugar)&"."); Comisarias(Comis).avisar(lugar);

59 60 61 62 63 64

65 66 67 68 69

70

186

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


else -- Es un delito con urgencia Put_Line("DELITO Y URGENCIA)."); Comis := positive_random(NUM_COMISARIAS); Hosp := positive_random(MAX_HOSPITAL); Put_Line(" -> Se avisa a la Comisaria"&Integer Image(Comis)&" y al Hospital "&IntegerImage(Hosp )& " desde el lugar "&IntegerImage(Lugar)&"."); Comisarias(Comis).avisar(lugar); Hospitales(Hosp).avisar(lugar); end if; or terminate; end select; end loop; end Central; -- GENERADOR DE LLAMADAS -----------------------------task body Generador_Llamadas is begin accept Init; loop delay Duration(Positive_Random(5)); Central.llamada(Positive_Random(NUM_LUGARES)); end loop; end Generador_Llamadas;

71 72 73 74 75

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

-- TAREA HOSPITAL -------------------------------task body Hospital is Id, Lugar, a, u: Integer := 0; begin accept Init(I: in Integer) do Id := I; end Init; loop select accept avisar(Lug: Integer) do Lugar := Lug; end avisar; if positive_random(2)=1 then a := positive_random(NUM_AMBULANCIAS); Put_Line(" -> Se avisa a la ambulancia"&Integer Image(a)&"."); else u := positive_random(NUM_UVIS); Put_Line(" -> Se avisa a la UVI movil"&Integer Image(u)&"."); end if; or terminate; end select; end loop; end Hospital;

114 115 116

117 118 119 120 121 122

187

Programaci n Concurrente o

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

-- COMISARIA DE POLICIA -----------------------------task body Comisaria is Id, Lugar, AUX, Aux_Pat: Integer := 0; begin accept Init(I: in Integer) do Id := I; end Init; loop select accept avisar(l:Integer) do Lugar := l; end avisar; Aux_Pat := positive_random(NUM_PATRULLAS); Aux := positive_random(3); if Aux = 1 then Put_Line(" * El ladron ha sido detenido por la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 2 then Put_Line(" * El ladron ha escapado de la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 3 then Put_Line(" * Falsa alarma para la patrulla" &IntegerImage(Aux_Pat)&"."); else Put_Line("ERROR - PROBLEMA CON EL LADRON"); end if; end if; end if; if positive_random(10) < 4 and Aux /= 3 then -- Si es falsa alarma no va a ser delito grave Put_Line(" x El delito es grave => La patrulla "& IntegerImage(Aux_Pat)&" se queda en el Lugar"& IntegerImage(lugar)&"."); Lugares(Lugar).patrulla := Aux_Pat; end if; or terminate; end select; end loop; end Comisaria; begin Central.Init; for i in 1..MAX_HOSPITAL loop Hospitales(i).Init(i); end loop; for i in 1..NUM_COMISARIAS loop Comisarias(i).Init(i); end loop;

142 143 144

145 146 147

148 149 150 151 152 153 154

155

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

188

Pr ctica 6 - Servicio de Atenci n de Urgencias a o


Generador_Llamadas.Init; end Urgencias_citas;

173 174 175

6.3.2

Resoluci n por Monitores en Ada o

Explicaci n o Aqu s lo existe una tarea generadora de llamadas, y un monitor que realiza todo el trabajo de la o central, hospital y comisara. Esta soluci n no tiene ninguna dicultad propia de la concurrencia, o y unicamente se hizo con el n de compactar la soluci n simplicada anterior, concretamente las o tareas Central, Hospital y Comisara, en un unico monitor.

C digo fuente o

C digo fuente 6.3: Servicio de Atenci n de Urgencias (simplicado) por Monitores en Ada o o
1

with TEXT_IO,random,Ada.Exceptions; use TEXT_IO,random,Ada. Exceptions; procedure Urgencias_tp is type Turgencias is (DELITO, URGENCIA, AMBOS); protected Monitor is procedure Llamada_Urgencia(Lugar: in Integer); procedure Llamada_Delito(Lugar: in Integer); procedure Llamada_Ambos(Lugar: in Integer); private Aux, Aux_Pat, Hosp, Comis: Integer := 0; Contador: Integer := 0; a, u: Integer; end Monitor; task Generador_Llamadas is entry Init; end Generador_Llamadas; -- Constantes NUM_PATRULLAS: constant Integer := 3; NUM_AMBULANCIAS: constant Integer := 2; MAX_HOSPITAL: constant Integer := 3; NUM_COMISARIAS: constant Integer := 2; NUM_UVIS: constant Integer := 3; NUM_LUGARES:constant Integer := 5; -- MONITOR -------------------------------------------protected body Monitor is procedure Llamada_Urgencia(Lugar: in Integer) is

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

189

Programaci n Concurrente o
begin Contador := Contador + 1; Put_Line("[O] LLAMADA" &IntegerImage(Contador)&" recibida desde el LUGAR"&IntegerImage(Lugar)&" (URGENCIA)"); Hosp := positive_random(MAX_HOSPITAL); Put_Line(" -> Se avisa al hospital" &IntegerImage(Hosp)) ; if positive_random(2)=1 then a := positive_random(NUM_AMBULANCIAS); Put_Line(" -> Se avisa a la ambulancia"&Integer Image(a)&"."); else u := positive_random(NUM_UVIS); Put_Line(" -> Se avisa a la UVI movil"&IntegerImage (u)&"."); end if; end Llamada_Urgencia; procedure Llamada_Delito(Lugar: in Integer) is begin Contador := Contador + 1; Put_Line("[O] LLAMADA" &IntegerImage(Contador)&" recibida desde el LUGAR"&IntegerImage(Lugar)&" (DELITO)"); Comis := positive_random(NUM_COMISARIAS); Put_Line(" -> Se avisa a la comisaria" &IntegerImage( Comis)); -- En la comisaria se manda a una patrulla y se ve que ocurre Aux_Pat := positive_random(NUM_PATRULLAS); Aux := positive_random(3); if Aux = 1 then Put_Line(" * El ladron ha sido detenido por la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 2 then Put_Line(" * El ladron ha escapado de la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 3 then Put_Line(" * Falsa alarma para la patrulla" & IntegerImage(Aux_Pat)&"."); else Put_Line("ERROR - PROBLEMA CON EL LADRON"); end if; end if; end if; if positive_random(10) < 4 and Aux /= 3 then -- Delito grave Put_Line(" x El delito es grave => La patrulla "& IntegerImage(Aux_Pat)&" se queda en el Lugar"& IntegerImage(lugar)&"."); end if; end Llamada_Delito; procedure Llamada_Ambos(Lugar: in Integer) is begin

34 35 36

37 38

39 40 41

42 43 44

45 46 47 48 49 50 51

52 53

54

55 56 57 58

59 60 61

62 63 64

65 66 67 68 69 70

71

72 73 74 75 76

190

Pr ctica 6 - Servicio de Atenci n de Urgencias a o

77 78 79

Contador := Contador + 1; Put_Line("[O] LLAMADA" &IntegerImage(Contador)&" recibida desde el LUGAR"&IntegerImage(Lugar)&" (URGENCIA Y DELITO)"); -- Avisamos a un hospital y a una comisaria al azar Hosp := positive_random(MAX_HOSPITAL); Comis := positive_random(NUM_COMISARIAS); Put_Line(" -> Se avisa al hospital" &IntegerImage(Hosp)& " y a la Comisaria" &IntegerImage(Comis)); -- En el hospital se busca una ambulancia o Uvi al azar if positive_random(2)=1 then a := positive_random(NUM_AMBULANCIAS); Put_Line(" -> Se avisa a la ambulancia"&Integer Image(a)&"."); else u := positive_random(NUM_UVIS); Put_Line(" -> Se avisa a la UVI movil"&IntegerImage (u)&"."); end if; -- En la comisaria se manda a una patrulla y se ve que ocurre Aux_Pat := positive_random(NUM_PATRULLAS); Aux := positive_random(3); if Aux = 1 then Put_Line(" * El ladron ha sido detenido por la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 2 then Put_Line(" * El ladron ha escapado de la patrulla" &IntegerImage(Aux_Pat)&"."); else if Aux = 3 then Put_Line(" * Falsa alarma para la patrulla" & IntegerImage(Aux_Pat)&"."); else Put_Line("ERROR - PROBLEMA CON EL LADRON"); end if; end if; end if; if positive_random(10) < 4 and Aux /= 3 then -- Delito grave Put_Line(" x El delito es grave => La patrulla "& IntegerImage(Aux_Pat)&" se queda en el Lugar"& IntegerImage(lugar)&"."); end if; end Llamada_Ambos; end Monitor;

80 81 82 83 84

85 86 87 88 89

90 91 92

93 94 95

96 97 98 99

100 101 102

103 104 105

106 107 108 109 110 111

112

113 114 115 116 117 118 119 120

-- GENERADOR DE LLAMADAS ------------------------------

191

Programaci n Concurrente o

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

task body Generador_Llamadas is Aux, Lugar: Integer; begin accept Init; loop delay Duration(Positive_Random(5)); -- Generamos aleatoriamente un tipo de urgencia y lugar Aux := Positive_Random(3); Lugar := Positive_Random(NUM_LUGARES); -- Avisamos al monitor if Aux = 1 then Monitor.Llamada_Urgencia(Lugar); elsif Aux = 2 then Monitor.Llamada_Delito(Lugar); else Monitor.Llamada_Ambos(Lugar); end if; end loop; end Generador_Llamadas; begin Generador_Llamadas.Init; end Urgencias_tp;

192

Pr ctica 6 - Servicio de Atenci n de Urgencias a o

6.4
6.4.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 20 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por citas en Ada: aproximadamente unas 16 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Versi n simplicada por monitores en Ada: aproximadamente unas 2 hora, entre impleo mentaci n y documentaci n. o o Versi n simplicada por citas en Ada: aproximadamente unas 2 horas, entre implementaci n o o y documentaci n. o

6.4.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

6.4.3

Dicultad

Por citas en Ada: Dicultad de 9 sobre 10. Versiones simplicadas: Dicultad de 3 sobre 10

193

Programaci n Concurrente o

194

Pr ctica 7 - Becarios del servicio de Inform tica a a

Pr ctica 7 a

Becarios del servicio de Inform tica a


7.1 Enunciado

Varios alumnos ha sido contratados como becarios para el Servicio de Inform tica. Se les ha a distribuido en grupos de entre N0 y N componentes. Cada da cada grupo es enviado a un edicio del Campus de la universidad a resolver los problemas inform ticos que han sido comunicados al a Servicio de Inform tica. a Cuando el grupo llega al edicio el Jefe del grupo asigna a los componentes un problema seg n u su estimaci n de dicultad y duraci n del mismo, atendiendo a la destreza de cada componente. o o Cuando van terminando la tarea encomendada van eligiendo problemas para resolver. La estimaci n del tiempo de resoluci n del problema es orientativa, el becario puede tardar o o m s o menos seg n el trabajo real que deba hacer. Puede que lo resuelva por s mismo, o que a u tenga que consultar su problema con el jefe del grupo, o con la unidad de soporte t cnico, o con e alg n compa ero del grupo. Conforme van resolviendo problemas van adquiriendo m s destreza, u n a lo que hace se enfrenten a otras situaciones con m s probabilidad de exito, y m s ecientemente a a en tiempo. El jefe va a llevar un control de los problemas que ha resuelto para controlar su rendimiento. No s lo se jara en el n mero de problemas resueltos, tambi n tendr en cuenta la dicultad de o u e a los problemas (asignados/resueltos). Aunque al principio tienen una lista de problemas a resolver, puede que surjan casos en el centro que deban atender con cierta urgencia. No se interrumpir la resoluci n de un problema a o para resolver otro, pero si puede ser necesario resolverlo en cuanto se pueda, eso lo va a evaluar el jefe del grupo. El grupo est resolviendo problemas el tiempo que dura su jornada laboral, si un caso no va a a poder ser resuelto a tiempo de nalizar la jornada con un cierto margen, entonces no se comienza la resoluci n (a veces se parchea para que no parezca que est n ociosos, pero esto solo lo hacen o a al nal de la jornada). Las dicultades para resolver un caso no est n s lo en la dicultad del mismo, porque por a o el centro suele pulular un elemento entorpecedor, harto curioso, que se dedica a preguntar a los becarios, qu est n haciendo, porqu lo hacen as, sugerirles como un experto la forma de e a e resolverlo, etc. Lo cierto es que nadie en el centro ha acertado a saber la funci n que desempe a el o n entorpecedor en la universidad, adem s de la rese ada. Todo esto puede hacer que el becario vaya a n 195

Programaci n Concurrente o distray ndose de su tarea, demor ndose en su resoluci n, e incluso si tiene poca experiencia en el e a o trato sacarle de sus casillas y largarse. Otras veces, las m s, consigue terminarla. El entorpecedor a nunca abandona una dependencia si no est resuelto el caso, o consigue que abandone el becario. a Dise e un Programa Concurrente, libre de bloqueos e inaniciones, que simule el Sistema den scrito.

196

Pr ctica 7 - Becarios del servicio de Inform tica a a

7.2
7.2.1

Resoluci n por citas en Ada o


Explicaci n o

Lo primero hemos de decir, que se ha simplicado la pr ctica bastante debido al poco tiempo para a resolverla, tanto en su resoluci n por citas como por tipos protegidos. Una de las simplicaciones o es, que todos los grupos tienen el mismo n mero de becarios, otas es que no hemos tenido en u cuenta los aciertos o fallos (ni dicultad, ni pericia del becario) al resolver los problemas. Para resolver este enunciado, hemos creado 4 tipos de tareas Entorpecedor, Becario, Grupo, Edificio. Cada edicio tiene asignado un grupo de becarios y tambi n un entorpecee dor. En esta pr ctica los becarios podr n ayudarse entre s para resolver los problemas, tambi n a a e podr n pedir ayuda a su jefe (que se corresponde con el becario 0 del mismo grupo). a Algunos de los puntos de entradas de algunas tareas son: Becario Init(I:Integer;Gi:Integer): inicializaci n del becario, se pasamos su ideno ticador dentro del grupo, y el identicador del grupo al que pertenece. Reparar: punto de entrada en el que se le asigna una tarea al becario. Para resolverla pordr pedir ayuda a alguno de sus compa eros o al jefe del grupo, y estar en peligro de a n a ser hacechado por el entorpecedor. PedirAyuda(Id Pregunta:Integer;Gid Pregunta:integer): han pedido ayuda al becario, seg n quien sea al que han pedido ayuda, ser el jege o un compa ero. u a n Grupo Init(I:Integer): inicializaci n del grupo, y de los becarios que contiene. o HayQueTerminar: Se ha acabado la jornada, y ya no se asignar n m s trabajos a a aunque queden por resolver. MandoTareas(T:Integer): Manda a cada becario del grupo desocupado un tarea distinta. Terminado(I:Integer): Indica que el becario I ha acabado la tarea asignada. Si quedaban tareas por asignar, se le asignar una nueva. a

7.2.2

C digo fuente o
C digo fuente 7.1: Becarios del servicio de Inform tica por citas en Ada o a

1 2 3 4 5 6 7 8 9

--Practica 7 (becarios informatica) --Programacion Concurrente --Resolucion por citas with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; use Ada.Numerics.Float_Random;

197

Programaci n Concurrente o
use ada.integer_text_io; use ada.text_io; procedure Becarios_Citas is G:Generator; --Cada grupo I estara destinado a ir al edificio I, que tendra un entorpecedor I --El primer becario del grupo, es el jefe del grupo = grupos(g) (1), y no se le asginan tareas ---------------------------------------------------------------------------------- Declaraciones tareas---------------------task type Entorpecedor is entry Init(I:Integer); entry Terminado(Fin:Boolean); entry VenCansino(I:Integer;Desisto: out Boolean;Trep:out Standard.Duration); entry VeteCansino; end Entorpecedor; task type Becario is entry Init(I:Integer;Gi:Integer); entry Reparar; entry PedirAyuda(Id_Pregunta:Integer;Gid_Pregunta:integer); end Becario; task type Grupo is entry Init(I:Integer); entry HayQueTerminar; entry MandoTareas(T:Integer); entry Terminado(I:Integer); end Grupo; task type Edificio is entry Init(I:Integer); entry HemosTerminado; end Edificio;

10 11 12 13 14 15 16 17

18

19 20 21 22 23 24 25 26

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

--------------------------------------------------------------------------------------Variables ----------------------------numero de grupos = numero de edificios Ngrupos:integer:=3; --numero de becarios por grupo (debe ser mayor que 1) Nbecarios:integer:=3; --Numero de tareas Ntareas:Integer:=Nbecarios; --vector de edificios Edificios:array (1..Ngrupos) of Edificio; --vector de becarios type Vbecarios is array (1..Nbecarios) of Becario; --vector de grupos de vectores de becarios

198

Pr ctica 7 - Becarios del servicio de Inform tica a a


Grupos:array (1..Ngrupos) of Vbecarios; --vector de grupos Gid:array (1..Ngrupos) of Grupo; --vector de ocupados type Ocu is array (1..Nbecarios) of Boolean; Ocupados:array (1..Ngrupos)of Ocu; --vector de cansinos Cansinos:array (1..Ngrupos)of Entorpecedor;

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

---------------------------------------------------------------------------------- Cuerpos ---------------------------------task body Entorpecedor is Id:Integer; A:Float; Ocupado:Boolean:=False; Mevoy:Boolean:=False; begin accept Init(I:Integer)do Id:=I; --Put_Line("Ini. Cansino "&IntegerImage(id)); end Init; loop select accept Terminado(Fin:Boolean)do Put_Line("** Cansino: "&IntegerImage(id)&"... terminando de molestar"); Mevoy:=True; end Terminado; or when not Ocupado => accept VenCansino(I:Integer;Desisto: out Boolean; Trep:out Standard.Duration) do if not Mevoy then Ocupado:=True; Reset(G); A:=Random(G); Put_Line("** Becario: ("&IntegerImage(id)&"," &IntegerImage(I) &") me estan cansando "); if A>0.9 then Put_Line("** Becario:("&IntegerImage(id)&" ,"&IntegerImage(I)&")" &" Desisto...Cansino!!!"); Desisto:=True; Trep:=0.0; else --el cansino retarda el trabajo Trep:=Trep+Standard.Duration(A*3.0); end if; end if; end Vencansino; or

91 92 93 94 95 96

97 98 99 100 101

102 103 104

105 106 107 108 109 110 111 112 113 114

199

Programaci n Concurrente o
accept VeteCansino do Ocupado:=false; end VeteCansino; or terminate; end select; end loop; end Entorpecedor;

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

function PrimerCompLibre(Gru:integer) return Integer is Comp:Integer:=0; begin for Ii in 2..Nbecarios loop if not Ocupados(Gru)(Ii) then Comp:=Ii; exit; end if; end loop; return Comp; end PrimerCompLibre; task body Becario is Id:Integer; Trep:Standard.Duration:=3.0; A:Float; Desisto:Boolean:=False; Gru:Integer; Salir:Boolean:=False; Co:Integer; begin accept Init(I:Integer;gi:integer)do Id:=I; Gru:=Gi; Ocupados(Gru)(Id):=False; --Put_Line("Ini. becario "&IntegerImage(gru)&","&Integer Image(id)); end Init; loop select accept Reparar do if not Ocupados(Gru)(Id) and not Salir then Ocupados(Gru)(Id):=True; Desisto:=False; Put_Line(">> Becario:("&IntegerImage(gru)&","& IntegerImage(Id)&") reparar algo"); end if; end Reparar; if Ocupados(Gru)(Id) then --aleatoriamente Reset(G); A:=Random(G)*3.0; --Comprobamos si necesitamos ayuda

151 152 153 154 155 156 157 158 159

160 161 162 163 164 165 166 167 168

200

Pr ctica 7 - Becarios del servicio de Inform tica a a


if A<1.0 then --lo resuelve el mismo Put_Line("??? Becario ("&IntegerImage(Gru)&","& IntegerImage(id)&") Puedo hacerlo SOLO."); elsif A<2.0 then --llama al jefe, si no es el propio jefe y esta libre if Id/=1 and not Ocupados(Gru)(1) then --Put_Line("? "&IntegerImage(gru)&","&Integer Image(id)&" Necesito ayuda, llamo al jefe "); Grupos(Gru)(1).PedirAyuda(Gru,Id); end if; else --a un compi --busco un compi libre, si no sigo Co:=PrimerCompLibre(Gru); if Co/=0 then Grupos(Gru)(Co).PedirAyuda(Gru,Id); exit; end if; Put_Line("??? Becario ("&IntegerImage(Gru)&", " &IntegerImage(id)&") NADIE puede AYUDARME."); end if; Cansinos(Gru).VenCansino(Id,Desisto,Trep); --si no hemos desistido al cansino, hacemos el trabajo if not Desisto then --tardo en hacer la reparacion delay (Trep); end if;

169 170 171

172 173

174 175

176 177 178 179 180 181 182 183 184 185 186 187

188

189 190 191 192 193

194 195 196 197 198 199 200 201 202 203 204 205

Cansinos(Gru).VeteCansino; --avisamos al grupo de que hemos terminado Gid(gru).Terminado(Id); end if; or accept PedirAyuda(Id_Pregunta:Integer;Gid_Pregunta: integer) do if Id/=1 then Put_Line("??? "&"Becario ("&IntegerImage( Id_pregunta) &IntegerImage(Gid_Pregunta)&") pregunta a COMPI (" &IntegerImage(gru)&","&IntegerImage( Id)&")"); else Put_Line("??? "&"Becario ("&IntegerImage( Id_pregunta)

206 207

208

209

210 211

201

Programaci n Concurrente o
&IntegerImage(Gid_Pregunta)&") pregunta a JEFE del grupo: " &IntegerImage(gru)); end if; end PedirAyuda; or terminate; end select; end loop; end Becario; task body Grupo is Id:Integer; --numero de tareas a realizar Nt:Integer; Salir:Boolean:=False; Falta_Id:Integer; begin accept Init(I:Integer)do Id:=I; --Put_Line("Ini. grupo "&IntegerImage(id)); --inicializamos a los becarios del grupo for Ii in Grupos(Id)Range loop Grupos(Id)(Ii).Init(Ii,id); end loop; end Init; loop select --el edificio nos dice las tareas a realizar (T) accept MandoTareas(T:Integer)do Nt:=T; Put_Line("Grupo: "&IntegerImage(id)&" tiene que hacer: "&IntegerImage(nt)&" reparaciones"); --mandamos trabajo a los becarios for Ii in Grupos(Id)Range loop if Nt>0 then --no mandamos reparar al jefe ni a los que esten ocupados if Ii/=1 and not Ocupados(id)(Ii) then Grupos(Id)(Ii).Reparar; Nt:=Nt-1; end if; delay(1.0); end if; end loop; end MandoTareas; or accept HayQueTerminar do Salir:=True; Put_Line("Vamos chicos (g:"&IntegerImage(id)&") a comer..."); end HayQueTerminar; or accept Terminado(I:Integer) do

212

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244

245 246 247 248

249 250 251 252 253 254 255 256 257 258 259 260

261 262 263

202

Pr ctica 7 - Becarios del servicio de Inform tica a a


Ocupados(id)(I):=False; Put_Line("<< Becario: ("&IntegerImage(id)&","& IntegerImage(I)&") he terminado"); Falta_Id:=I; end Terminado; --si quedan trabajos por asignar, asignamos uno if Nt>0 and not Salir then Nt:=Nt-1; Put_Line("--->>>>>> Nuevo Trabajo para ("&Integer Image(id)&"," &IntegerImage(Falta_Id)&") quedan: "& IntegerImage(nt)); Grupos(Id)(Falta_id).Reparar; end if; or terminate; end select; end loop; end Grupo; task body Edificio is Id:Integer; R:Integer; Cansino:Entorpecedor; begin accept Init(I:Integer)do Id:=I; --Put_Line("Ini. edificio "&IntegerImage(id)); --inicizalizamos al cansino de ese edificio Cansinos(Id).Init(Id); --inicializamos al grupo asignado Gid(Id).Init(Id); end Init; Reset(G); --numero de tareas aleatorio R:=Integer(Random(G)*3.0+Float(Ntareas)); Gid(Id).MandoTareas(R); --esperamos una jornada, y avisamos de que tiene que terminar delay (Standard.Duration(Random(G)*5.0)+Standard.Duration(Id +10)); Put_Line("Edificio "&IntegerImage(Id)&" Jornada Terminada.") ; Gid(Id).HayQueTerminar; Cansinos(Id).Terminado(True); select accept HemosTerminado; or terminate; end select; end Edificio;

264 265

266 267 268 269 270 271

272

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

300

301 302 303 304 305 306 307 308 309 310 311 312 313 314

begin Put_Line("-------------------------------------------"); Put_Line("Practica 7: Becarios de informatica (citas)");

203

Programaci n Concurrente o
Put_Line("-------------------------------------------"); --inicializamos los edificios for Ii in 1..Ngrupos loop Edificios(Ii).Init(Ii); end loop; end Becarios_Citas;

315 316 317 318 319 320 321

204

Pr ctica 7 - Becarios del servicio de Inform tica a a

7.3
7.3.1

Resoluci n por tipos protegidos en Ada o


Explicaci n o

Como ya hemos dicho, se ha simplicado el problema. Para resolverlo por tipos protegidos, hemos creado dos tipos de monitores Cansino, Grupo, y un tipo tarea Becario. De esta forma, el cansino de cada grupo s lo podr estar molestando a un becario a la vez. o a La soluci n es bastante sencilla, ya que no se complican los algoritmos utilizados en la o soluci n anterior. S lo destacar, que en esta soluci n los becarios no pueden pedir ayuda a nadie, o o o y de nuevo cada grupo corresponde con un edicio, que tiene un grupo de becarios y un cansino. Algunos procedimientos son: Cansino procedure Molestame(Ok:out Boolean): podr molestar a un becario, si a no est ocupado molestando a otro. a procedure Dejame: libera a un becario de su pesadez. entry Cansineando(Desisto:out Boolean): est molestando al becario, a aleatoriamente el becario podr desistir de su intento de reparaci n o no. a o procedure Init(I:Integer): inicializaci n del monitor que simboliza al eno torpecedor. Grupo procedure DarTarea(Ok:out Boolean): asigna una tarea a un becario si hay sucientes. procedure TerminarTarea(I:integer): el becario informa al grupo de que ha completado su tarea de reparaci n. o procedure Init(I:Integer;N:integer): inicializa el grupo, pasandole su identicador y el n mero de tareas que deben resolver sus becarios. u

7.3.2

C digo fuente o
C digo fuente 7.2: Becarios del servicio de Inform tica por monitores en Ada o a

1 2 3 4 5 6 7 8 9 10 11 12 13 14

--Practica 7:Becarios (tipos protegidos)

with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; use Ada.Numerics.Float_Random; use ada.integer_text_io; use ada.text_io;

procedure Becarios_Tp is

205

Programaci n Concurrente o
G:Generator; Ntareas:integer:=5; Ngrupos:integer:=3; Nbecarios:integer:=4; Trep:Duration:=Duration(3.0+Random(G)*2.0);

15 16 17 18 19 20 21 22 23 24

-----------------------------------------------------------------------

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

task type Becario is entry Init(I:Integer;Gi:integer); end Becario; protected type Cansino is procedure Molestame(Ok:out Boolean); procedure Dejame; entry Cansineando(Desisto:out Boolean); procedure Init(I:Integer); private Id:Integer; Ocupado:Boolean:=False; end Cansino; protected type Grupo is procedure DarTarea(Ok:out Boolean); procedure TerminarTarea(I:integer); procedure Init(I:Integer;N:integer); private Id:Integer; Nt:Integer:=Ntareas; end Grupo; -----------------------------------------------------------------------

49 50 51 52 53 54 55 56

Grupos:array (1..Ngrupos) of Grupo; type Beca is array (1..Nbecarios)of Becario; Becarios:array (1..Ngrupos)of Beca; Cansinos: array (1..Ngrupos) of Cansino;

-----------------------------------------------------------------------

57 58 59 60 61 62 63 64

task body Becario is Id:Integer; Gid:Integer; Hay:Boolean; Molesta:Boolean; Desisto:Boolean; T:Duration:=Trep;

206

Pr ctica 7 - Becarios del servicio de Inform tica a a


begin accept Init(I:Integer;Gi:Integer) do Id:=I; Gid:=Gi; end Init; delay duration(1.0+Random(G)*Float(Gid*Id)); loop Grupos(Gid).DarTarea(Hay); if Hay then Put_Line(">> Becario ("&IntegerImage(gid)&","&Integer Image(id)&") reparando..."); Cansinos(Gid).Molestame(Molesta); if Molesta then Put_Line("** Becario ("&IntegerImage(gid)&","& IntegerImage(id)&") cansandose..."); Cansinos(Gid).Cansineando(Desisto); Reset(G); delay duration(3.0+Random(G)*2.0); Cansinos(Gid).Dejame; Put_Line("** Becario ("&IntegerImage(gid)&","& IntegerImage(id)&") se ha ido el pesado"); end if; if not Desisto then --tarda en reparar delay (T); Grupos(Gid).TerminarTarea(Id); else Put_Line("-- Becario ("&IntegerImage(gid)&","& IntegerImage(id)&") ha desistido"); end if; end if; exit when not Hay; end loop; end Becario; protected body Grupo is procedure DarTarea(Ok:out Boolean) is begin if Nt>0 then Nt:=Nt-1; Ok:=True; else Ok:=False; end if; end DarTarea; procedure TerminarTarea(I:integer) is begin Put_Line("<< Becario: ("&IntegerImage(id)&","&Integer Image(I)&") ha terminado."); end TerminarTarea; procedure Init(I:Integer;N:integer) is begin Id:=I;

65 66 67 68 69 70 71 72 73 74

75 76 77

78 79 80 81 82

83 84 85 86 87 88 89 90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

111 112 113 114 115

207

Programaci n Concurrente o
Nt:=N; end Init; end Grupo; protected body Cansino is procedure Molestame(Ok:out Boolean)is begin if not Ocupado then Ok:=True; else Ok:=False; end if; end Molestame; procedure Dejame is begin Ocupado:=False; end Dejame; entry Cansineando(Desisto:out Boolean) when not Ocupado is begin Reset(G); if Random(G)>0.9 then --hacemos que desista el becario Desisto:=True; else Desisto:=False; end if; end Cansineando; procedure Init(I:Integer)is begin Id:=I; end Init;

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

end Cansino; R:Float; begin Put_Line("--------------------------------------"); Put_Line("Practica 7:Becarios (tipos protegidos)"); Put_Line("--------------------------------------"); for Ii in GruposRange loop Reset(G); R:=Random(G)*3.0+Float(Nbecarios); Grupos(Ii).Init(Ii,Integer(R)); Cansinos(Ii).Init(Ii);

208

Pr ctica 7 - Becarios del servicio de Inform tica a a


for Jj in Becarios(Ii)Range loop Becarios(Ii)(Jj).Init(Jj,ii); end loop; end loop; end Becarios_Tp;

172 173 174 175 176 177

209

Programaci n Concurrente o

7.4
7.4.1

Anexo
Tiempo de trabajo

Tiempo general Teniendo en cuenta el tiempo de dise o, la implementaci n, as como el tiempo empleado en n o resolver las dicultades con la que nos hemos encontrado, hemos tardado aproximadamente unas 17 horas en resolver la totalidad de la pr ctica. a Tiempo por apartados Por monitores en Ada: aproximadamente unas 2 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o Por citas en Ada: aproximadamente unas 15 horas, mas lo empleado en realizar la documentaci n (aproximadamente una hora). o

7.4.2

Distribuci n de trabajo o

El trabajo ha sido repartido entre todos los componentes del grupo. Hemos repartido el trabajo entre cada persona lo m s equitativamente posible. Adem s, todos hemos participado activamente a a en la resoluci n de las partes que no tenamos asignadas, ayudando, por lo que no nos parece o correcto destacar a ning n miembro del grupo por encima de los dem s. u a

7.4.3

Dicultad

Por monitores en Ada: Dicultad de 6 sobre 10. Por citas en Ada: Dicultad de 8 sobre 10.

210

Parte II

Ejercicios inventados

211

Ejercicio inventado - Julimocho

Ejercicio inventado 1

Julimocho
1.1 Enunciado

Los j venes de hoy en da son muy acionados al calimocho. Todos los jueves un grupo de o universitarios, cansados de las duras clases, quedan por la noche para beber esta refrescante bebida isot nica y practicar un juego que se ha puesto de moda recientemente: el Julimocho. o El grupo de jugadores se re ne alrededor de una mesa, en cuyo centro hay una botella de u vino. Dos jugadores, aleatoriamente elegidos, empiezan la partida con un vaso lleno cada uno. Cuando un jugador tiene un vaso, debe beb rselo lo m s r pido posible, llenarlo y pas rselo e a a a a otro jugador. Si un jugador se bebe su vaso y la botella est siendo utilizada por otro jugador, el primero a esperar hasta que la botella est disponible. En ese momento llenar el vaso y lo pasar , tal a e a a y como dicta el juego. Si la botella se termina, avisar n al camarero para que la llene. Despu s seguir n jugando. a e a Como los individuos van vi ndose afectados a medida que avanza el juego, es posible que e cuando reciban el vaso lo tiren, derramando todo el contenido del mismo. En ese caso, ese jugador queda eliminado y deja de jugar. Como castigo, el jugador eliminado rellena el vaso, lo pasa a otro jugador y se va a dormir la mona. Cuando unicamente quedan dos jugadores, ganar el que menos tiempo tarde en beberse el a vaso. Si unicamente queda un jugador al nal, el es autom ticamente el ganador de la ronda. a Juli n es el estudiante m s responsable de todos, y nunca bebe. El se dedica a controlar que a a todo el juego se desarrolle correctamente de ah el nombre del juego. Cuando alg n jugador u necesita saber algo a cerca del juego (qui n est eliminado, quienes tienen el vaso en un instante e a dado...) recurren a Juli n. a Simule el funcionamiento del juego.

213

Programaci n Concurrente o

1.2
1.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para resolver el problema, hemos creado las siguientes tareas: Botle: Se trata de la botella del centro de la mesa. Es una tarea sencilla. Los jugadores la emplean para simular el llenado del vaso, bloque ndola mientras la utilizan y liber ndola al a a terminar. El camarero tambi n la bloquea mientras la est llenando. e a Waiter: Es el camarero. Cuando un jugador se encuentra la botella vaca (porque el jugador anterior termin con su contenido) le avisa. El camarero se encarga de llenar la o botella. Julian: Es el estudiante responsable. Cuando se produce cualquier evento del juego (alguien queda eliminado, alguien recibe un vaso, etc) los jugadores se lo notican. Del mismo modo, cuando alg n jugador necesita conocer alg n aspecto del estado actual del juego u u (como qui nes tienen vaso, si alguien est eliminado o no, etc) le preguntan a Julian. e a Student: Representa a los jugadores. Esta tarea recibe un vaso, bebe, lo llena y lo pasa, noticando a Julian para cada uno de esos eventos. Tal como dice el enunciado, dos de los jugadores empiezan con un vaso. Cada uno bebe y lo pasa aleatoriamente a otro jugador. Cuando un jugador recibe el vaso, si no lo tira, bebe, lo llena y lo vuelve a pasar. En el caso de que lo tire, lo llena sin beber y lo pasa, avisando a Juli n de que a queda eliminado. Al quedar eliminado, ning n otro jugador podr pasarle el vaso. u a Cuando quedan dos jugadores en pie al nal, ambos avisan a Juli n de que se hayan en lo a que hemos llamado FinalFight, que es la ultima batalla, en la que ambos beben lo m s r pido a a posible. Julian decide qui n de ellos gana, que ser el que menos tiempo tarde en beberse el e a vaso.

1.2.2

C digo fuente o
C digo fuente 1.1: Julimocho por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

-- Julimocho (Citas en Ada) with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure Julimocho is -- Constants N_STUDENTS: constant Integer := 10; task Julian is entry IHaveAGlass(Id: in Integer); entry IDontHaveAGlass(Id: in Integer); entry HavingAGlass(Id: in Integer; Ok: out Boolean); entry ImOut(Id: in Integer);

214

Ejercicio inventado - Julimocho


entry IsOut(Id: in Integer; Ok: out Boolean); entry HowManyPlayers(N: out Integer); entry IsFinalFight(Ok: out Boolean); entry InFinalFight(Id: in Integer; Time: in Integer); end Julian; task Bottle is entry UseIt(Id: in Integer; Ok: out Boolean); entry Release(Id: in Integer); entry Fill; end Bottle; task Waiter is entry MoreDrink(Id: in Integer); end Waiter; task type Student is entry Init(Identity: in Integer; Glass: in Boolean); entry GetAGlass(From: in Integer; Ok: out Boolean); entry FinalFightFinish; end Student; Students: array (Integer range 1..N_STUDENTS) of Student; -- THE BOTTLE ------------------------------------------task body Bottle is Using, Empty: Boolean := False; begin loop select when not Using => accept UseIt(Id: in Integer; Ok: out Boolean) do if not Empty then Put_Line("Student" & IntegerImage(Id) & " is filling a glass with the bottle..."); Using := True; Ok := True; else -- The bottle is empty Ok := False; end if; end; or accept Release(Id: in Integer) do Put_Line("Student" & IntegerImage(Id) & " releases the bottle"); Using := False; if Positive_Random(20) < 5 then -- The bottle is empty Empty := True; Put_Line("Student" & IntegerImage(Id) & " has spent the bottle. The BOTTLE is EMPTY"); end if; end; or when (not Using) and Empty =>

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59

60 61 62 63 64

65 66 67 68

215

Programaci n Concurrente o
accept Fill do Using := True; Put_Line("WAITER is filling the bottle"); delay(3.0); Put_Line("WAITER finishes filling the bottle"); Empty := False; Using := False; end; end select; end loop; end Bottle; -- THE WAITER ------------------------------------------task body Waiter is begin loop accept MoreDrink(Id: in Integer) do Put_Line("Student" & IntegerImage(Id) & " requests more drink to the waiter."); Bottle.Fill; end; end loop; end Waiter; -- THE RESPONSIBLE STUDENT -----------------------------task body Julian is With_Glass: array (Integer range 1..N_STUDENTS) of Boolean; Playing: array (Integer range 1..N_STUDENTS) of Boolean; Final_Fight: Boolean := False; -- Data of the final Fight Id1: Integer := -1; Id2: Integer := -1; Time1: Integer := -1; Time2: Integer := -1; Aux: Integer; procedure ShowPlayers is begin Put("Playing: ["); for I in 1..N_STUDENTS loop Put(IntegerImage(I) & "("& BooleanImage(Playing(I))&" ), "); end loop; Put_Line("]"); end ShowPlayers; procedure ShowGlasses is begin Put("With_Glass: ["); for I in 1..N_STUDENTS loop Put(IntegerImage(I) & "("& BooleanImage(With_Glass(I) )&"), "); end loop; Put_Line("]");

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

111 112 113 114 115 116 117 118 119

120 121

216

Ejercicio inventado - Julimocho


end ShowGlasses; begin -- Init data for I in 1..N_STUDENTS loop With_Glass(I) := False; Playing(I) := True; end loop; loop -- The main loop select accept IHaveAGlass(Id: in Integer) do With_Glass(Id) := True; end; or accept IDontHaveAGlass(Id: in Integer) do With_Glass(Id) := False; end; or accept HavingAGlass(Id: in Integer; Ok: out Boolean) do Ok := With_Glass(Id); end; or accept ImOut(Id: in Integer) do Playing(Id) := False; ShowPlayers; end; or accept IsOut(Id: in Integer; Ok: out Boolean) do Ok := not Playing(Id); end; or accept HowManyPlayers(N: out Integer) do Aux := 0; for I in 1..N_STUDENTS loop if Playing(I) then Aux := Aux + 1; end if; end loop; N := Aux; end; or accept IsFinalFight(Ok: out Boolean) do Ok := Final_Fight; end; or accept InFinalFight(Id: in Integer; Time: in Integer) do if Final_Fight then -- Another student has called before Id2 := Id; Time2 := Time; if Time2 < Time2 then Put_Line("Student" &IntegerImage(Id2)& " won the game"); else

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

169 170 171 172 173 174

175

217

Programaci n Concurrente o
if not (Time2 = Time1) then Put_Line("Student" &IntegerImage(Id1)& " won the game"); else Put_Line("Students" &IntegerImage(Id2)& " and" &IntegerImage(Id2)& "have tied"); end if; end if; else -- Is the first student calling Id1 := Id; Time1 := Time; Final_Fight := True; end if; end; -- Wake up two finalist if Final_Fight then Students(Id1).FinalFightFinish; Students(Id2).FinalFightFinish; end if; end select; end loop; end Julian; -- STUDENTS --------------------------------------------task body Student is Id: Integer; HasAGlass: Boolean; Playing: Boolean := True; Students_Playing: Integer := N_STUDENTS; GlassOut: Boolean := False; -- Has thrown the glass out Time: Integer := 0; Target: Integer; FinalFight: Boolean := False; procedure PassTheGlass is Wrong, Passed: Boolean; N: Integer; begin Passed := False; while not Passed loop Wrong := True; while Wrong loop Julian.HowManyPlayers(N); if (Playing and N > 2) or (not Playing and N >= 2) then Target := Positive_Random(Students_Playing); if Target /= Id then Julian.IsOut(Target, Wrong); if not Wrong then

176 177

178 179

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

225 226 227 228

218

Ejercicio inventado - Julimocho


Julian.HavingAGlass(Target, Wrong); end if; end if; else Wrong := False; Target := -1; end if; end loop; if Target /= -1 then Students(Target).GetAGlass(Id, Passed); else Passed := True; -- To stop looping end if; end loop; if Target = -1 then Put_Line("Student" &IntegerImage(Id)&" cant pass his glass because all players are OUT"); else Julian.IdontHaveAGlass(Id); HasAGlass := False; end if; end PassTheGlass; procedure FillTheGlass is Ok: Boolean; begin Put_Line("Student" & IntegerImage(Id) & " is going to catch the bottle."); Bottle.UseIt(Id, Ok); while not Ok loop Waiter.MoreDrink(Id); Bottle.UseIt(Id, Ok); end loop; Bottle.Release(Id); end FillTheGlass; begin -- Init the player accept Init(Identity: in Integer; Glass: in Boolean) do Id := Identity; HasAGlass := Glass; Playing := True; end; Put_Line("Student" & IntegerImage(Id) & " starts playing. HasAGlass = " & BooleanImage(HasAGlass)); if HasAGlass then -- Is one of the students who starts with a glass Julian.IHaveAGlass(Id); Put_Line("Student" & IntegerImage(Id) & " is drinking..." ); delay(Positive_Random(3)*1.0);

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

248 249 250 251 252 253 254 255 256 257

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

275 276 277 278 279

280

219

Programaci n Concurrente o
-- Now the student fill the glass FillTheGlass; -- The student pass the glass to otherone PassTheGlass; delay 3.0; end if; -- Starts the main loop loop Julian.HowManyPlayers(Students_PLaying); -- How many students are playing? Put_Line(">!< Students playing =" &IntegerImage( Students_Playing)); if Playing then Put_Line("[+] Student" & IntegerImage(Id)& " is READY" ); else Put_Line("[-] Student" & IntegerImage(Id)& " is OUT"); end if; select accept GetAGlass(From: in Integer; Ok: out Boolean) do Ok := Playing; if Playing then if Positive_Random(10) < 6 then -- Throw the glass out Put_Line("Student" & IntegerImage(From) & " passes the glass to Student" &IntegerImage (Id)& ", but he falls it out ==> STUDENT" & IntegerImage(Id) & " IS OUT"); Julian.ImOut(Id); GlassOut := True; Students_Playing := Students_Playing - 1; else -- Catch the glass correctly Julian.IHaveAGlass(Id); HasAGlass := True; Put_Line("Student" & IntegerImage(From) & " passes the glass to Student" &IntegerImage (Id)& " succesfully"); end if; end if; end; if Playing then if HasAGlass then -- He didnt drop the glass if Students_Playing = 1 then Put_Line("Student" & IntegerImage(Id) & " WON THE GAME!"); Playing := False; Julian.ImOut(Id); else Put_Line("Student" & IntegerImage(Id) & " is drinking..."); delay(Positive_Random(3)*1.0); -- Only drink

281 282 283 284 285 286 287 288 289 290 291

292

293 294 295

296 297 298 299 300 301 302 303 304 305

306 307 308 309 310 311 312 313

314 315 316 317 318 319 320 321

322 323 324 325

326

220

Ejercicio inventado - Julimocho


FillTheGlass; -- The student pass the glass to otherone Julian.HowManyPlayers(Students_Playing); PassTheGlass; delay 3.0; end if; else Playing := False; FillTheGlass; -- The student pass the glass to otherone PassTheGlass; delay 3.0; end if; end if; exit when Students_Playing = 0 or Target = -1; if Students_Playing = 2 and Playing then -- Final fight Put_Line("Student" & IntegerImage(Id) & " is in Final Fight. Drinking..."); -- Calculate the time drinking and notify Julian Time := Positive_Random(3); FinalFight := True; Julian.InFinalFight(Id, Time); Playing := False; Julian.ImOut(Id); accept FinalFightFinish; exit; end if; or delay(10.0); Put_Line("Student"&IntegerImage(Id)&" is bored because nobody pass him a glass. He left the game"); Julian.ImOut(Id); exit; end select; end loop; Put_Line("Student" & IntegerImage(Id) & " ends"); end Student; begin -- Create the players for I in 1..2 loop Students(I).Init(I, True); end loop; for I in 3..N_STUDENTS loop Students(I).Init(I, False); end loop; end Julimocho;

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

347 348 349 350 351 352 353 354 355 356 357 358

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378

221

Programaci n Concurrente o

222

Ejercicio inventado - StarWars: Andr meda vs Ori n o o

Ejercicio inventado 2

StarWars: Andr meda vs Ori n o o


2.1 Enunciado

La gran rivalidad entre las civilizaciones de Andromeda y Orion ha causado una guerra estelar, en la que ya ha habido millares de bajas. Las naves de batalla est n equipadas, y entrenadas para a vencer, cueste lo que cueste. Dos escuadrones de naves, uno de Andr meda y otro de Ori n, se aproximan para llevar a o o cabo la batalla nal, en la que se decidir el destino de ambas civilizaciones. a En estas batallas, Orion siempre cuenta con la ventaja de tener m s naves preparadas para a la lucha. Por otro lado, los pilotos de Andromeda est n mejor entrenados, y son capaces de a hacer disparos m s certeros (quitando m s vida a sus contrincantes). a a Las naves que han sufrido da os, solicitan las reparaciones a trav s del centro mec nico, n e a indic ndole el dinero m ximo que est n dispuestas a pagar. El Centro Mecanico asigna a a a la reparaci n a una Nave Mecanica libre. Si no hay ninguna libre, a una al azar. o Existe una serie de naves mec nicas, que no son de ning n bando, y reparan las naves del a u mejor postor. Dada una petici n de arreglo de uno de los bandos para una nave, espera cierto o tiempo por si recibe una oferta mejor. Si no recibe ninguna oferta repara la nave. Pero en caso de recibir una oferta mejor, reparar la nave que hace mejor oferta, desestimando la a petici n de la primera nave que solicit el arreglo. o o Si desestiman la petici n de arreglo de una nave, esta no podr solicitar m s reparaciones o a a hasta que no vuelva a ser atacada y sufra m s da os. De esta manera, el ofrecer una mala a n oferta a las naves mec nicas produce sus consecuencias. a Cada nave empieza con una vida de 100 unidades, y esta ir disminuyendo a medida que a sufra ataques de sus rivales. Las reparaciones aumentar n la vida, pero en mucha menor a medida de lo que los ataques la hacen disminuir. Cada nave puede disparar a cualquier nave del equipo contrario. Se trata de simular la gran batalla nal, ilustrando cada ataque, el estado de cada bando tras cada baja, y el resultado del combate.

223

Programaci n Concurrente o

2.2
2.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para resolver este problema, hemos creado las siguientes tareas, una por cada elemento principal del problema: Nave: Cada unidad de batalla. Inicialmente, tal y como dicta el enunciado, el bando de Ori n cuenta con m s naves que el bando de Andr meda. Cada nave, tras ser inicializada, o a o entra en un bucle en el que recibe disparos y dispara. Para disparar, hemos creado un procedimiento, Dispara, que se encarga de encontrar una nave v lida a la que disparar, y dispara. a Nave Mecanica: Se trata de naves independientes, que reciben ofertas de reparaci n o y, seg n sea la mejor oferta, reparan dicha nave. El funcionamiento es el siguiente: una u vez que reciben una oferta, esperan un peque o tiempo; si en ese tiempo no reciben otra n oferta reparan la primera nave, y si reciben otra oferta, reparan la nave que m s dinero haya a ofertado. Las ofertas no le vienen directamente a trav s de las naves de batalla, sino que vienen del e Centro Mecanico, que hace de intermediario entre ambos conjuntos de naves. Centro Mecanico: Recibe peticiones de reparaciones de las naves de batalla, y encuentra una nave mec nica a la que traspasarle la oferta. Si hay alguna nave mec nica libre, ser a a a a esta; en caso contrario a una nave mec nica cualquiera. a El problema m s grande de este ejercicio radica en la posibilidad de que dos naves se disparen a entre si, quedando en interbloqueo. Para evitar esto, cuando una nave quiere disparar a otra, hace una especie de reserva (a trav s de la entrada Voy A Disparar) para que la nave objetivo no e trate de disparar a la primera al tiempo. Para que lo anterior funcione correctamente, hemos evitado el hecho de que dos naves disparen simultaneamente a una tercera, ya que una segunda llamada a Voy A Disparar s lo ser o a atendida cuando la primera nave que hizo reserva haya disparado.

2.2.2

C digo fuente o
C digo fuente 2.1: StarWars: Andr meda y Ori n por citas en Ada o o o

1 2 3 4 5 6 7 8 9 10 11

with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure StarWars is type TypeBando is (ANDROMEDA, ORION, NONE); -- Tarea de las naves de batalla task type Nave is entry Init(Identity: in Integer; Bando_Lucha: in TypeBando); entry Voy_A_Disparar(Quien: in Integer);

224

Ejercicio inventado - StarWars: Andr meda vs Ori n o o


entry Recibe_Disparo(Source: in Integer; Vida_Source: in Integer; Bando_Source: in TypeBando; Gravedad: in Integer) ; entry Repara(Mecanico: in Integer; Arreglo: in Integer); end Nave; -- Tarea de las naves mecanicas task type Nave_Mecanica is entry Init(Identity: in Integer); entry Repara(Nave: in Integer; Bando: in TypeBando; Oferta: in Integer); end Nave_Mecanica; -- Tarea del gestor de naves mecanicas task Centro_Mecanico is entry Reparacion(Nave: in Integer; Bando: in TypeBando; Oferta: in Integer); end Centro_Mecanico; -- Numero de naves de cada equipo NUM_NAVES_ANDROMEDA: constant Integer := 3; NUM_NAVES_ORION: constant Integer := 4; -- Maximo dano causado al rival FUERZA_ANDROMEDA: constant Integer := 40; FUERZA_ORION: constant Integer := 20; -- Para saber cuando termina la batalla Num_Naves_Vivas_Andromeda: Integer := 0; Num_Naves_Vivas_Orion: Integer := 0; NUM_NAVES_VIVAS: Integer := 0; -- Los dos equipos Andromeda_Team: array (1..NUM_NAVES_ANDROMEDA) of Nave; Orion_Team: array (1..NUM_NAVES_ORION) of Nave; -- Naves mecanicas (que reparan otras naves) NUM_NAVES_MECANICAS: constant Integer := 2; MAX_REPARACION: constant Integer := 10; Mecanicas: array (1..NUM_NAVES_MECANICAS) of Nave_Mecanica; Mecanicas_Libres: array (1..NUM_NAVES_MECANICAS) of Boolean; Andromeda_Vivas: array (1..NUM_NAVES_ANDROMEDA) of Boolean; Orion_Vivas: array (1..NUM_NAVES_ORION) of Boolean; -- Procedimiento para mostrar el estado de los dos equipos procedure Ver_Naves_Vivas is begin Put(">> ANDROMEDA_VIVAS: "); for I in 1..NUM_NAVES_ANDROMEDA loop Put(IntegerImage(I)&" "&BooleanImage(Andromeda_Vivas(I)) &","); end loop; Put_Line(" "); Put(">> ORION_VIVAS: "); for I in 1..NUM_NAVES_ORION loop

12

13 14 15 16 17 18 19

20 21 22 23 24

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

58 59 60 61

225

Programaci n Concurrente o
Put(IntegerImage(I)&" "&BooleanImage(Orion_Vivas(I))&"," ); end loop; Put_Line(" "); end Ver_Naves_Vivas; -- Procedimiento para finalizar la batalla Fin: Boolean; procedure Fin_Batalla is begin if not Fin then -- para solo hacerlo una vez aunque llamen mas luego Fin := True; Put_Line("LA BATALLA HA FINALIZADO"); if Num_Naves_Vivas_Orion < Num_Naves_Vivas_Andromeda then Put_Line("Ganador: ANDROMEDA"); else if Num_Naves_Vivas_Orion > Num_Naves_Vivas_Andromeda then Put_Line("Ganador: ORION"); else Put_Line("Batallas sin ganadores. Todos muertos."); end if; end if; end if; end Fin_Batalla; -- CENTRO MECANICO ----------------------------task body Centro_Mecanico is Nave_Asignada: Integer; procedure Nave_Mecanica_Libre(Nave: out Integer) is Cual: Integer := -1; begin for I in 1..NUM_NAVES_MECANICAS loop if Mecanicas_Libres(I) then Cual := I; end if; end loop; Nave := Cual; end Nave_Mecanica_Libre; begin loop select accept Reparacion(Nave: in Integer; Bando: in TypeBando ; Oferta: in Integer) do Nave_Mecanica_Libre(Nave_Asignada); if Nave_Asignada = -1 then Nave_Asignada := Positive_Random( NUM_NAVES_MECANICAS); end if; Mecanicas(Nave_Asignada).Repara(Nave, Bando, Oferta) ;

62

63 64 65 66 67 68 69 70 71

72 73 74 75 76 77

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

107 108 109

110 111

226

Ejercicio inventado - StarWars: Andr meda vs Ori n o o


end; end select; end loop; end Centro_Mecanico; -- NAVE ---------------------------------------task body Nave is Vida: Integer := 100; Bando: TypeBando; Id: Integer; Target: Integer; -- Destino del disparo Oferta: Integer; Me_Disparara: Integer := -1; -- Procedimiento que dispara a cualquier nave rival excepto la indicada por Quien_no procedure Dispara(Quien_No: in Integer) is begin if Bando = ANDROMEDA then -- Disparamos a una nave de Orion Target := Positive_Random(NUM_NAVES_ORION); while Target = Quien_No loop Put_Line("*"); Target := Positive_Random(NUM_NAVES_ORION); end loop; Orion_Team(Target).Voy_A_Disparar(Id); Orion_Team(Target).Recibe_Disparo(Id, Vida, Bando, Positive_Random(FUERZA_ANDROMEDA) + 20); else -- Disparamos a una nave de Andromeda Target := Positive_Random(NUM_NAVES_ANDROMEDA); while Target = Quien_No loop Put_Line("*"); Target := Positive_Random(NUM_NAVES_ANDROMEDA); end loop; Andromeda_Team(Target).Voy_A_Disparar(Id); Andromeda_Team(Target).Recibe_Disparo(Id, Vida, Bando, Positive_Random(FUERZA_ORION) + 20); end if; end Dispara; begin -- Inicializamos la nave accept Init(Identity: in Integer; Bando_Lucha: in TypeBando) do Bando := Bando_Lucha; Id := Identity; Put_Line("["&TypeBandoImage(Bando)&" "&IntegerImage(Id)& "] preparada."); end; -- Actualizamos la informacion sobre naves vivas if Bando = ANDROMEDA then Andromeda_Vivas(Id) := True;

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

129 130 131 132 133 134 135 136 137 138 139

140 141 142 143 144 145 146 147 148

149 150 151 152 153 154 155

156 157 158

159 160 161 162

227

Programaci n Concurrente o
Num_Naves_Vivas_Andromeda := Num_Naves_Vivas_Andromeda + 1; else Orion_Vivas(Id) := True; Num_Naves_Vivas_Orion := Num_Naves_Vivas_Orion + 1; end if; NUM_NAVES_VIVAS := NUM_NAVES_VIVAS + 1; delay(Positive_Random(2)*1.0 + 2.0); -- La nave va hacia la batalla -- Bucle principal while Num_Naves_Vivas_Andromeda > 0 and Num_Naves_Vivas_Orion > 0 loop select -- Aviso de disparo para evitar interbloqueo when Me_Disparara = -1 => accept Voy_A_Disparar (Quien: in Integer) do Me_Disparara := Quien; end; or -- Disparo accept Recibe_Disparo(Source: in Integer; Vida_Source: in Integer; Bando_source: in TypeBando; Gravedad: in Integer) do Me_Disparara := -1; -- Anulamos la reserva de disparo if Vida > 0 then -- Si sigue viva Vida := Vida - Gravedad; if Vida > 0 then Put_Line("[" &TypeBandoImage(Bando_source)&"" &IntegerImage(Source)&" ("&IntegerImage( Vida_source)&"%)] dispara a ["&TypeBando Image(Bando)&" "&IntegerImage(Id)&"] => Esta queda al"&IntegerImage(Vida)&"%"); else -- La nave ha sido destrozada Put_Line("[" &TypeBandoImage(Bando_source)&"" &IntegerImage(Source)&" ("&IntegerImage( Vida_source)&"%)] dispara a ["&TypeBando Image(Bando)&" "&IntegerImage(Id)&"] => Esta queda DESTROZADA"); NUM_NAVES_VIVAS := NUM_NAVES_VIVAS - 1; if Bando = ANDROMEDA then Andromeda_Vivas(Id) := False; Num_Naves_Vivas_Andromeda := Num_Naves_Vivas_Andromeda - 1; else Orion_Vivas(Id) := False; Num_Naves_Vivas_Orion := Num_Naves_Vivas_Orion - 1; end if; Ver_Naves_Vivas; end if; end if; end; if Vida > 0 and Positive_Random(5) < 2 Then

163

164 165 166 167 168 169 170

171 172 173

174 175 176 177 178 179 180 181 182

183

184 185 186 187

188 189

190 191 192 193

194 195 196

197 198 199 200 201 202

228

Ejercicio inventado - StarWars: Andr meda vs Ori n o o


-- Ahora solicitamos una reparacion Oferta := Positive_Random(10); Put_Line("[" &TypeBandoImage(Bando)& " "&Integer Image(Id)&"] solicita reparacion al centro mecanico."); Centro_Mecanico.Reparacion(Id, Bando, Oferta); end if; if Vida > 0 then Dispara(Me_Disparara); end if; or accept Repara(Mecanico: in Integer; Arreglo: in Integer ) do if Vida > 0 then Put_Line("[< ] NAVE_MECANICA"&IntegerImage( Mecanico)&" reparando NAVE"&IntegerImage(Id)& " de "&TypeBandoImage(Bando)); Vida := Vida + Arreglo; if Vida > 100 then Vida := 100; end if; Put_Line("["&TypeBandoImage(Bando)&" "&Integer Image(Id)&"] al"&IntegerImage(Vida)&"%"); else Put_Line("[< ] NAVE_MECANICA"&IntegerImage( Mecanico)&" va a reparar NAVE"&IntegerImage( Id)&" de "&TypeBandoImage(Bando)&". Pero ya es tarde: ESTA DESTROZADA"); end if; end; or delay(Positive_Random(2)*1.0 + 1.0); if Vida > 0 and Positive_Random(10) < 7 then Dispara(Me_Disparara); end if; end select; end loop; Fin_Batalla; end Nave;

203 204 205

206 207 208 209 210 211 212

213 214

215 216 217

218 219

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

-- NAVE_MECANICA -------------------------------------task body Nave_Mecanica is Nave1, Nave2: Integer; Oferta1, Oferta2: Integer; Bando1, Bando2: TypeBando; Id: Integer; begin accept Init(Identity: in Integer) do Id := Identity; end; loop Mecanicas_Libres(Id) := True; accept Repara(Nave: in Integer; Bando: in TypeBando; Oferta: in Integer) do Put_Line("[M] NAVE_MECANICA"&IntegerImage(Id)&" recibe oferta de reparacion para NAVE"&IntegerImage(Nave)

247

229

Programaci n Concurrente o
&" de "&TypeBandoImage(Bando)&", OFERTA ="&Integer Image(Oferta)); Nave1 := Nave; Oferta1 := Oferta; Bando1 := Bando; end; Mecanicas_Libres(Id) := False; select accept Repara(Nave: in Integer; Bando: in TypeBando; Oferta: in Integer) do Put_Line("[M] NAVE_MECANICA"&IntegerImage(Id)&" recibe oferta de reparacion para NAVE"&Integer Image(Nave)&" de "&TypeBandoImage(Bando)&", OFERTA ="&IntegerImage(Oferta)); Nave2 := Nave; Oferta2 := Oferta; Bando2 := Bando; end; -- Ahora reparamos la nave que mejor oferta haga if Oferta1 > 0 and Oferta2 > 0 then if Oferta1 > Oferta2 then -- Reparamos la primera nave if Bando1 = ANDROMEDA then Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ANDROMEDA"&IntegerImage( Nave1)&"]"); Andromeda_Team(Nave1).Repara(Id, Positive_Random(MAX_REPARACION)); else Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ORION"&IntegerImage(Nave1 )&"]"); Orion_Team(Nave1).Repara(Id, Positive_Random( MAX_REPARACION)); end if; else -- Reparamos la segunda nave if Bando2 = ANDROMEDA then Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ANDROMEDA"&IntegerImage( Nave2)&"]"); Andromeda_Team(Nave2).Repara(Id, Positive_Random(MAX_REPARACION)); else Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ORION"&IntegerImage(Nave2 )&"]"); Orion_Team(Nave2).Repara(Id, Positive_Random( MAX_REPARACION)); end if; end if; else Put_Line("HAY ALGO MAL: Una oferta es negativa"); end if; or delay(2.0);

248 249 250 251 252 253 254

255

256 257 258 259 260 261 262 263 264 265

266

267 268

269

270 271 272 273 274

275

276 277

278

279 280 281 282 283 284 285

230

Ejercicio inventado - StarWars: Andr meda vs Ori n o o


-- Va a reparar la nave que hizo la primera oferta if Bando1 = ANDROMEDA then Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ANDROMEDA"&IntegerImage(Nave1)&"]"); Andromeda_Team(Nave1).Repara(Id, Positive_Random( MAX_REPARACION)); else Put_Line("NAVE_MECANICA"&IntegerImage(Id)&" yendo a reparar [ORION"&IntegerImage(Nave1)&"]"); Orion_Team(Nave1).Repara(Id, Positive_Random( MAX_REPARACION)); end if; end select; -- Ahora limpiamos los datos Nave1 := -1; Nave2 := -1; Oferta1 := -1; Oferta2 := -2; Bando1 := NONE; Bando2 := NONE; end loop; end Nave_Mecanica; begin -- Inicializamos las naves mecanicas for I in 1..NUM_NAVES_MECANICAS loop Mecanicas(I).Init(I); end loop; -- Inicializamos los bandos for I in 1..NUM_NAVES_ANDROMEDA loop Andromeda_Team(I).Init(I, ANDROMEDA); end loop; for I in 1..NUM_NAVES_ORION loop Orion_Team(I).Init(I, ORION); end loop; Put_Line("Las naves de ambos bandos se desplazan al lugar de la batalla ..."); end StarWars;

286 287 288

289

290 291

292

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

316 317

231

Programaci n Concurrente o

232

Ejercicio inventado - F brica de chocolate a

Ejercicio inventado 3

F brica de chocolate a
3.1 Enunciado

En una f brica de bombones tienen N m quinas para batir el chocolate. El chocolate tiene que a a estar lo sucientemente lquido para que las m quinas puedan batirlo, si no es as, las m quinas a a podran estropearse. Las m quinas tienen unos sensores que indican al operario si el chocolate a est lquido o espeso, en el caso de que est espeso, el operario parar la m quina ir hacie ella e a e a a a introducira un ingrediente que hace que el chocolate se vuelva m s lquido inmediatamente. Una a vez hecho esto el operario volver a encender la m quina. Cuando una m quina termine de batir a a a el chocolate, los chocolateros(encargados de hacer los bombones) recoger n el chocolate batido, a y a adir n m s para que las m quinas sigan batiendo. n a a a Las m quinas pueden estropearse por un fallo interno en ese caso..el operario deber arreglar a a la m quina lo antes posible. a cuando los bombones est n hechos un catador experto lo probar si est en su punto la caja a a a ste despide a un chocolatero por el error. En sale a la venta si no se lo comunica al jefe y e el caso de que ya no queden chocolateros por despidos..la f brica cerrar su producci n. El a a o reloj del alcalde le avisa para hacer la ronda, al igual que el reloj de los jardineros, que les indica el inicio de una nueva jornada.

233

Programaci n Concurrente o

3.2

Resoluci n por citas en Ada o

En la resoluci n de este ejercicio tendremos: o Tarea operario: El operario s lo se encarga de reponer el chocolate cuando el sensor o de la m quina detecta que est espeso. Lo cambia, y activa otra vez la m quina para que a a a vuelva a batir. Puede ocurrir que la m quina se estrope, entonces se avisara tabi n al operario a e para que solucione el problema. Tarea jefe:La tarea jefe act a cuando el catador avisa de que est bien la mezcla, enu a tonces el jefe decide despedir al chocolatero que ha recogido la mezcla del chocolate. Tarea catador: El catador se encarga de probar el chocolate una vez sacado de la batidora y mezclado por el chocolatero. Tareas chocolateros: Los chocoloateros se encargan de sacar el chocolate de la batidora una vez haya terminado de batir. Tareas mquinas: Las m quinas se encargan de batir el chocolate, si este es espeso, a a sta se estropea avisa tambi n al operario llamaran al operario para que cabie el chocolate, si e e para que cambie el chocolate. Una vez haya terminado su proceso, avisa al chocolatero para que recoja el chocolate.

3.2.1

C digo Fuente o
C digo fuente 3.1: F brica de chocolate por citas en Ada o a

1 2 3 4 5 6 7 8

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions; procedure fabrica is

9 10

11 12 13 14 15 16

17 18 19 20 21 22 23

MAX_MAQUINAS: constant Integer:=5; --numero maximo de maquinas MAX_CHOCOLATEROS: constant Integer:=3; --numero maximo de chocolateros total_chocolateros: integer:=MAX_CHOCOLATEROS; despidos: array(1..MAX_CHOCOLATEROS) of integer;--para saber si estan despedidos type Aestado_maquinas is record estropeada:boolean:=false; --para saber si esta estropeada on:boolean:=false;-- para saber si esta encendida. finalizado:boolean:=false; --para saber si ha finalizado espeso:boolean:=false; --para saber si el chocolate eta espeso. operario:integer:=-1; --si hay operario o no end record; estado_maquinas: array(1..MAX_MAQUINAS) of Aestado_maquinas; --tarea maquina task type maquina is

234

Ejercicio inventado - F brica de chocolate a


entry init_maquina(id:integer); entry batir; end maquina; maquinas: array (1..MAX_MAQUINAS) of maquina; --tarea operario task operario is entry init_operario; entry cambiar_chocolate(id_m:integer); entry arreglar(id_m:integer); end operario; -- tarea jefe task jefe is entry init_jefe; entry despedir(id_c:integer); end jefe; --tarea chocolatero task type chocolatero is entry init_chocolatero(id: Integer); entry recoger_chocolate(id_m:integer); end chocolatero; chocolateros: array (1..MAX_CHOCOLATEROS) of chocolatero; --tarea catador task catador is entry init_catador; entry probar(id_c:integer); end catador;

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

task body operario is maquina:Integer; --maquina atiendo.. begin accept init_operario; loop select --when total_chocolateros > 0 => accept cambiar_chocolate(id_m:integer) do estado_maquinas(id_m).operario:=0; --hay operario put_line("Operario cambiando chocolate de maquina : "& IntegerImage(id_m)); delay duration(Positive_random(3)); put_line("Cchocolate cambiado de maquina: "& IntegerImage(id_m)); maquina:=id_m; estado_maquinas(id_m).espeso:=false; --ya no esta espeso end cambiar_chocolate; maquinas(maquina).batir; --la maquina vuelve a batir or accept arreglar(id_m:integer) do estado_maquinas(id_m).operario:=0; --hay operario; put_line("Operario arreglando maquina : "&

66 67 68 69 70 71

72 73 74 75 76 77

235

Programaci n Concurrente o
IntegerImage(id_m)); delay duration(Positive_random(3)); put_line("reparada maquina : "& IntegerImage(id_m)); maquina:=id_m; estado_maquinas(id_m).estropeada:=false; --ya esta arreglada end arreglar; maquinas(maquina).batir; --la maquina vuelve a batir or terminate; end select; end loop; end operario; task body maquina is id_m:integer; aux:integer; aux_chocolatero:integer; begin accept init_maquina(id:integer) do id_m:=id; --asignamos el id a la maquina end init_maquina; loop select --when total_chocolateros > 0 => accept batir do estado_maquinas(id_m).finalizado:=false;--la maquina no ha --de batir estado_maquinas(id_m).operario:=-1;--ya no hay operario. estado_maquinas(id_m).on:=true;--maquina encendida. put_line("Maquina : "&IntegerImage(id_m)&" batiendo..."); delay duration(Positive_random(2));--batiendo aux:=Positive_Random(3); if aux = 1 then --chocolate espeso estado_maquinas(id_m).espeso:=true; estado_maquinas(id_m).on:= false; --apagada put_line("Maquina : "&IntegerImage(id_m)&" con chocolate espeso"); elsif aux = 2 then estado_maquinas(id_m).estropeada:=true; -estropeada estado_maquinas(id_m).on:=false; -- apagada put_line("Maquina : "&IntegerImage(id_m)&" estropeada");

78 79 80 81 82 83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

110 111

112

113

114 115 116 117 118 119 120 121

122 123

124 125

236

Ejercicio inventado - F brica de chocolate a


else delay duration (Positive_random(2)); put_line("Maquina "&IntegerImage(id_m)&" ha terminado de "& " batir el chocolate"); estado_maquinas(id_m).finalizado:=true; --ha finalizado end if; end batir; if aux = 1 then operario.cambiar_chocolate(id_m); --el operario cambia el chocolate elsif aux = 2 then operario.arreglar(id_m); --el operario arregla else loop aux_chocolatero:=positive_random(MAX_CHOCOLATEROS ); if total_chocolateros > 0 then if despidos(aux_chocolatero) /= 0 then estado_maquinas(id_m).on := false;-apagamos la maquina chocolateros(aux_chocolatero). recoger_chocolate(id_m); --se llama a un chocolatero al azar exit; end if; else put_line("NO HAY CHOCOLATEROS"); exit; end if; end loop; end if; or terminate; end select; end loop; end maquina;

126 127 128

129 130

131 132 133 134

135 136 137 138 139 140 141

142 143 144 145

146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

171 172 173

task body jefe is begin accept init_jefe; loop select accept despedir(id_c:integer) do put_line("No ha salido como se esperaba tendre que despedir"& " al chocolatero: "&IntegerImage(id_c)); despidos(id_c):= 0; total_chocolateros:=total_chocolateros-1; --despide a un chocolatero

237

Programaci n Concurrente o
delay duration(Positive_random(2)); end despedir; or terminate; end select; end loop; end jefe; task body chocolatero is id_c:integer; aux_m:integer; begin accept init_chocolatero(id:integer) do id_c:=id; --asignamos un id de chocolatero. end init_chocolatero; loop select accept recoger_chocolate(id_m:integer) do put_line("El chocolatero "&IntegerImage(id_c)&" esta recogiendo"& " el chocolate del la maquina: "&Integer Image(id_m)); delay duration(positive_random(3)); aux_m := id_m; end recoger_chocolate; catador.probar(id_c); --el catador prueba el chocolate or terminate; end select; end loop; end chocolatero; task body catador is begin accept init_catador; loop select accept probar(id_c:integer) do if positive_random(2) = 1 then put_line("El chocolate no le gusta al catador"); jefe.despedir(id_c); --el catador dice que despida al chocolatero end if; end probar; or terminate; end select; end loop; end catador;

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

196

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217

218 219 220 221 222 223 224 225 226

238

Ejercicio inventado - F brica de chocolate a

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

begin for i in 1..MAX_CHOCOLATEROS loop despidos(i):=1; end loop; for i in 1..MAX_MAQUINAS loop maquinas(i).init_maquina(i); maquinas(i).batir; end loop; for i in 1..MAX_CHOCOLATEROS loop chocolateros(i).init_chocolatero(i); end loop; operario.init_operario; catador.init_catador; jefe.init_jefe; end fabrica;

239

Programaci n Concurrente o

240

Ejercicio inventado - Party

Ejercicio inventado 4

Party
4.1 Enunciado

Debido a la universidad, y a haber estado encerrado sin salir de tu habitaci n por ciertas asignaturas o en contreto, te ves obligado a ir a la ultima esta del curso. En la esta hay dos barras (en cada una hay un camarero) donde sirven bebida, una para las copas de Whisky y otra para los minis de vino. Para no perder tiempo y que salga rentable la noche, eliges la barra del bar que menos cola tenga y esperas a que te sirvan. Despu s de esto te vas a bailar o a ligar un rato, hasta que se te e gaste la bebida y de nuevo tengas que ir a por otra bebida. Para evitar problemas alcoh licos, las personas como m ximo podr n tomar 5 bebidas en total o a a pero tampoco tienen porqu tomar nada. e La esta no termina hasta que los ultimos borrachos desalojen el bar. Dise e un programa concurrente que cumpla estas restricciones (en la medida de lo posible), n sin bloqueos ni inanici n. o

241

Programaci n Concurrente o

4.2
4.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para solucionar el problema he creado tres tareas: People, Waiter, Queue Consult que representan respectivamente a los universitarios esteros, los camareros (o barras de bar) y una tarea que he creado para que act e como un monitor para consultar el n mero de personas que hay u u en cada cola de las barras del bar. La verdad, es que se podra haber resuelto y enfocado de muchas formas diferentes, pero he elegido esta por circunstancias temporales. El universitario que est de esta, lo unico que har e a ser mirar la cola de espera m s corta, irse hacia ese lado y pedir el turno, hasta que el camarero a a le atienda, despu s se marchar de la cola de esa barra. e a Algunos de los puntos de entrada del problema son: Waiter Turno: piden el turno al camarero, que atender de uno en uno, a los que no atiende a est n esperando tener el turno. a Thanks: se despiden del camarero (ceden el turno a otro estero). Queue Consult a a Tellme Side(S:out Side Type): consulta cu l de las dos colas del bar es m s corta, y seg n la que sea vas a una barra o a la otra. u LeftQueue(S:Side Type ): dejas la barra del bar (seg n el lado que sea), habr u a uno menos esperando a ser atendido.

4.2.2

C digo fuente o
C digo fuente 4.1: Party por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

--Problema inventado: party --Programacion Concurrente --David Antonio Perez Zaba with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; use Ada.Numerics.Float_Random; use ada.integer_text_io; use ada.text_io; procedure Party_ci is G:Generator; type side_type is (Rigth,Left); task type people is entry Init(I:Integer);

242

Ejercicio inventado - Party


end People; task type waiter is entry Init(I:Integer;D:side_type); entry Turno(I:Integer); entry Thanks; end waiter;

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

Npeople:Integer:=20; Max_Ntimes:Integer:=3; Tserve:duration:=3.0; Tdance:Duration:=3.0; Queue_Rigth:Integer:=0; Queue_Left:Integer:=0; Vpeople:array (1..Npeople) of People; R:waiter; L:waiter;

task Queue_Consult is entry Tellme_Side(S:out Side_Type); entry LeftQueue(S:Side_Type); end Queue_Consult; task body Queue_Consult is Busy:Boolean:=False; begin loop --Put_Line("Queue: "&IntegerImage(Queue_left)&" - "& IntegerImage(Queue_rigth)); select accept Tellme_Side(S:out Side_Type) do --choose the best side if Queue_Rigth>=Queue_Left then S:=Left; Queue_left:=Queue_left+1; else S:=Rigth; Queue_rigth:=Queue_Rigth+1; end if; end Tellme_Side; or accept LeftQueue(S:Side_Type) do if S=left then Queue_left:=Queue_Left-1; else Queue_rigth:=Queue_Rigth-1; end if; end LeftQueue; or terminate; end select;

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

243

Programaci n Concurrente o
end loop; end Queue_Consult;

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

task body People is Id:Integer; Ntimes:Integer; Counter:Integer:=0; Side:side_type; Consulting:Boolean:=False; begin accept Init(I:Integer) do Id:=I; Reset(G); Ntimes:=Integer(Random(G)*Float(Max_Ntimes)); end Init; loop exit when Counter>=Ntimes; --choose the shortest queue Queue_Consult.Tellme_Side(Side); Put_Line(">> Guy "&IntegerImage(id)&" wait on "&Side_Type Image(Side) &" queue"); --go to the bar if Side=Rigth then R.Turno(Id); R.Thanks; else L.Turno(Id); L.Thanks; end if; Queue_Consult.LeftQueue(Side); Put_Line("** Guy "&IntegerImage(Id)&" is dancing..."); --dancing delay (Tdance); --one more drink Counter:=Counter+1; end loop; --dont drink anything if Ntimes=0 then Put_Line("<< Guy "&IntegerImage(Id)&" i dont like this party"); else Put_Line("<< Guy "&IntegerImage(Id)&" say goodby"); end if; end People;

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

121 122 123 124 125 126 127 128 129

task body waiter is Id:Integer;

244

Ejercicio inventado - Party


busy:Boolean:=False; side:side_type; begin accept Init(I:Integer;D:side_type) do Id:=I; side:=D; end Init; loop select --ask for a drink when not busy => accept Turno(I:Integer) do busy:=True; if Side=Rigth then Put_Line("++ Waiter("&Integerimage(Id)&"): Your Whisky... "&IntegerImage(I)); else Put_Line("++ Waiter("&Integerimage(Id)&"): Your wine... "&IntegerImage(I)); end if; end Turno; delay (Tserve); or --say goodby accept Thanks do busy:=False; end Thanks; or terminate; end select; end loop; end waiter;

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

146 147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

begin R.Init(1,Rigth); L.Init(2,Left); for Ii in VpeopleRange loop Vpeople(Ii).Init(Ii); delay(1.0); end loop; end Party_ci;

245

Programaci n Concurrente o

246

Ejercicio inventado - Florentino P rez e

Ejercicio inventado 5

Florentino P rez e
5.1 Enunciado

Florentino Perez, presidente del mejor club del mundo, Real Madrid F.C, se ha dispuesto ha realizar obras en el campo para que sea considerado, si cabe, el mejor estadio del mundo. Con la llegada del mundial tienen que jugar los restantes partidos de liga muy r pidamente y la Federaci n a o Espa ola de F tbol les avisa con unas horas antes del comienzo del partido. No tienen posibilidad n u de aplazarlo ni anularlo. Florentino ha dicho que las obras comiencen de inmediato a n sabiendo que un partido se u pueda jugar en cualquier momento. La empresa que se encarga de las obras es una constructura perteneciente a Florentino, por lo que estr n a sus ordenes. Cuando a Florentino le avisen de que a hay partido, este avisar al entrenador de que deber convocar r pidamente a 20 jugadores de entre a a a los N que tiene el equipo, y estos se dirigir n al estadio, si alguno de ellos no puede jugar, se lo a tendr que comunicar al entrenador para que convoque a otro; como convocar a un jugador que a a no es titular, tendr muchas ganas de jugar, por lo que aceptar de inmediato. a a Cuando todos los jugadores se encuentren en el estadio, el presidente ordenar parar las obras, a y el partido comenzar . Una vez terminado el partido, orentino ordenar que continuen las obras. a a Se supone que el quipo contrario llega al campo justo cuando va a comenzar el partido. Quedan M partidos de liga. La obra entera conlleva un tiempo, cada vez que trabajan consumen un poco de ese tiempo, si el Madrid gana los obreros trabajar n m s r pido pero si pierde trabajar n m s lentos. a a a a a

247

Programaci n Concurrente o

248

Ejercicio asignado - I.O.

Ejercicio inventado 6

I.O.
6.1 Enunciado

J.R. es un profesor que tiene la mala costumbre de que con cada tema nuevo manda a sus alumnos de I.O. diferentes tareas: hacer ejercicios, hacer el examen y despu s hacer los ejercicios e del examen de nuevo. Adem s de esto, los alumnos tambi n tienen que realizar una pr ctica por cada tema, que por a e a suerte pueden y deben realizarse en pareja. As que los alumnos tendr n que hacer frente a los problemas que J.R. les plantea, y cuando a tengan algo de tiempo libre (casi nunca) realizar la pr ctica. a Por suerte s lo hay cuatro temas. Y los compa eros de pr cticas est n pactados antes de o n a a comenzar el curso. N Habr N alumnos a parejas , siendo N un n mero par, y como ya hemos dicho J.R. u 2 mandar 4 ejercicios,4 ex menes y 4 ejercicios del examen a cada alumno (no todos de golpe, si a a no que con el paso del tiempo mandar primero los del tema uno, luego los del dos... hasta llegar a al cuarto tema). Dise e un programa concurrente que cumpla estas restricciones (en la medida de lo posible), n sin bloqueos ni inanici n. o

249

Programaci n Concurrente o

250

Parte III

Ejercicios asignados

251

Ejercicio asignado - Turismo de Almorox

Ejercicio asignado 1

Turismo de Almorox
1.1 Enunciado

En la Plaza Mayor de Almorox se encuentra un Punto de Informaci n Turstica regentado por un o encargado. Se han dise ado un n mero de rutas que recorren distintos puntos de inter s de la n u e ciudad. A disposici n de los grupos de turistas hay tres guas, cada uno de ellos especializado en ciertas o rutas. La misi n del encargado es atender a los turistas que lleguen hasta el Punto de Informaci n y o o facilitarles la documentaci n para que disfruten de todos los puntos de inter s de la ciudad. Cada o e cierto tiempo, el encargado necesita salir del punto de informaci n para darse una vuelta y que o no se le duerman las piernas por estar tanto tiempo sentado. Adem s, como es un poco vago, si a pasados 30 minutos no llega ning n turista a requerir sus servicios, el encargado saldr a tomar u a un caf . Cuando un grupo de turistas llega a la Plaza Mayor de Almorox, se da una vuelta hasta e que localiza el Punto de Informaci n Turstica y entonces se acerca a preguntar por la ruta en la o que est interesado. Si el encargado se encuentra en el Punto de Informaci n en ese momento, les a o indicar si esa ruta puede visitarse con la ayuda de un gua. Entonces el grupo decide si realiza a la ruta solo o acompa ado por el gua. En caso de que el gua est ocupado, el grupo espera a n e que regrese al Punto de Informaci n para recorrer su ruta. Si el encargado ha salido, el grupo de o turistas leer los carteles informativos que se encuentran en el Tabl n del Punto de Informaci n y a o o realizar n solos su ruta para no perder tiempo. a Cada Punto de Inter s tendr un horario de apertura y cierre y un aforo limitado. Cuando un e a grupo de turistas llega a un Punto de Inter s cerrado, sigue su camino al no poder visitar dicho e punto. Si el Punto de Inter s est abierto y el n mero de componentes del grupo no supera el aforo e a u del local, entrar a verlo. En caso de no poder entrar porque se superara el aforo, el grupo espera a en la entrada hasta que les indican que ya pueden entrar. En este ultimo caso, el grupo puede cansarse de esperar y marcharse. Si hay varios grupos en la cola de entrada, se dar prioridad a los a que vayan acompa ados de un gua. n

253

Programaci n Concurrente o

1.2
1.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para resolver este problema, hemos creado las siguientes tareas: Guia: Es una tarea sencilla, que se asocia a un grupo de turistas. Tras la visita, el grupo le libera y, as, puede ser asignada a otro grupo. El gua no hace nada en s mismo, y s lo es o una tarea util para ilustrar el problema mejor. Punto de Informacion: Representa, no s lo al punto de informaci n, sino tambi n al o o e encargado del mismo. Con el n de simplicar, para simular las ausencias del encargado nos servimos de la generaci n aleatoria de n meros. De esta forma, no es preciso contar o u con una tarea Encargado en s. e Punto de Interes: Es cada punto de inter s de una ruta. Cuando un grupo trata de visitarlo, este decide si puede o no entrar, dependiendo del n mero de componentes del u grupo y la capacidad del punto de inter s. Cuando un grupo sale del punto de inter s, lo e e simbolizamos mediante una llamada a Salir, un punto de entrada de esta tarea. o Grupo Turistas: Deciden una ruta y van al punto de informaci n. Puede ser que se encuentren con que el puesto est cerrado (no est el encargado), en cuyo caso visitan la a a ruta directamente, por su cuenta. Si el encargado est en el punto de informaci n y les a o asigna un gua, le esperar n hasta que est disponible. a e Para simplicar el problema, hemos creado tantos guas como rutas, y hemos asignado un gua a cada ruta. De esta manera, cuando un grupo de turistas llega al punto de informaci n para visitar o una ruta, qu gua asignarle resulta inmediato. e

1.2.2

C digo fuente o
C digo fuente 1.1: Turismo de Almorox por citas en Ada o

1 2 3 4 5 6

with Ada.Text_Io, Ada.Integer_Text_Io, random; use Ada.Text_Io, Ada.Integer_Text_Io, random; procedure Almorox is NUM_GRUPOS: constant Integer := 5; -- Numero de grupos de turistas PUNTOS_POR_RUTA: constant Integer := 3; -- Puntos de interes que tiene una ruta Contador_Puntos: Integer; task Punto_De_Informacion is -- Representa al punto de informacion y al encargado entry Clientes(Grupo: in Integer; Ruta: in Integer; Guia: out Integer); end Punto_De_Informacion; task type Guia is

8 9 10

11

12 13 14

254

Ejercicio asignado - Turismo de Almorox


entry Init(Identidad: in Integer); entry Coger(Grupo: in Integer); entry Liberar; end Guia; -- Cada ruta es un conjunto de puntos de interes task type Punto_De_Interes is entry Init(Num_Punto: in Integer; Capacidad: in Integer); entry Entrar(Grupo: in Integer; Cuantos: in Integer; Ok: out Boolean); -- Si caben pasan, si no se marchan entry Salir(Grupo: in Integer); entry Cerrar; end Punto_De_Interes; type Ruta is array (1..PUNTOS_POR_RUTA) of Punto_De_Interes; -- Vamos a tener 3 rutas, una por guia Rutas: array (1..3) of Ruta; Guias: array (1..3) of Guia; task type Grupo_Turistas is entry Init(Num_Grupo: in Integer; Ruta_Elegida: in Integer); end Grupo_Turistas; Grupos: array (1..NUM_GRUPOS) of Grupo_Turistas; -- TAREA PUNTO DE INFORMACION -------------------------task body Punto_De_Informacion is Abierto: Boolean := True; begin Put_Line("[i] PUNTO DE INFORMACION LISTO"); while Abierto loop select accept Clientes(Grupo: in Integer; Ruta: in Integer; Guia: out Integer) do if Positive_Random(10) > 8 then -- Significa que no hay encargado en el puesto Guia := -1; Put_Line("[i] Llega el grupo"&IntegerImage(Grupo )&" para ver la ruta"&IntegerImage(Ruta)&". El encargado no esta"); else -- Significa que si esta el encargado. Asignamos al grupo el guia apropiado Guia := Ruta; Put_Line("[i] Llega el grupo"&IntegerImage(Grupo )&" para ver la ruta"&IntegerImage(Ruta)&". Se le asigna el guia"&IntegerImage(Ruta)); end if; end; or delay(10.0); Put_Line("[i] No hay mas grupos. El puesto de informacion se cierra"); Abierto := False; end select; end loop;

15 16 17 18 19 20 21 22 23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

48

49 50

51

52 53

54 55 56 57 58

59 60 61

255

Programaci n Concurrente o
end Punto_De_Informacion;

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

-- TAREA PUNTO DE INTERES -----------------------------task body Punto_De_Interes is Id, Capac: Integer; -- Identidad Visitandolo: Boolean := False; Abierto: Boolean := True; begin -- Inicializamos accept Init(Num_Punto: in Integer; Capacidad: in Integer) do Id := Num_Punto; Capac := Capacidad; end; while Abierto loop select when not Visitandolo => accept Entrar(Grupo: in Integer; Cuantos: in Integer; Ok: out Boolean) do if Capac >= Cuantos then Visitandolo := True; Ok := True; Put_Line("[T] GRUPO"&IntegerImage(Grupo)&" ("& IntegerImage(Cuantos)&" personas) viendo el PUNTO DE INTERES"&IntegerImage(Id)); else Ok := False; Put_Line("[T] GRUPO"&IntegerImage(Grupo)&" ("& IntegerImage(Cuantos)&" personas) no puede entrar al PUNTO DE INTERES"&IntegerImage(Id)& ". Son demasiados."); end if; end; or accept Salir(Grupo: in Integer) do Visitandolo := False; Put_Line("[T] GRUPO"&IntegerImage(Grupo)&" sale del PUNTO DE INTERES"&IntegerImage(Id)); end; or accept Cerrar do Put_Line("[ ] El punto de interes"&IntegerImage(Id) &" se cierra"); Abierto := True; end; end select; end loop; end Punto_De_Interes; -- TAREA GUIA ---------------------------------------task body Guia is Id: Integer; Libre: Boolean := True; begin

81 82 83 84

85 86 87

88 89 90 91 92 93

94 95 96 97

98 99 100 101 102 103 104 105 106 107 108 109

256

Ejercicio asignado - Turismo de Almorox


accept Init(Identidad: in Integer) do Id := Identidad; end; loop select when Libre => accept Coger(Grupo: in Integer) do Libre := False; end; or accept Liberar do Libre := True; end; end select; end loop; end Guia;

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

-- GRUPO DE TURISTAS -----------------------------task body Grupo_Turistas is Id, Ruta, Guia: Integer; N: Integer; -- Numero de componentes del grupo Ok: Boolean; begin accept Init(Num_Grupo: in Integer; Ruta_Elegida: in Integer) do Id := Num_Grupo; Ruta := Ruta_Elegida; N := Positive_Random(7); end; -- Van al punto de informacion Put_Line("[T]>GRUPO"&IntegerImage(Id)&" ("&IntegerImage(N)& " personas) quiere visitar la ruta"&IntegerImage(Ruta)); Punto_De_Informacion.Clientes(Id, Ruta, Guia); if Guia = -1 then -- No hay nadie en el punto de informacion, el grupo hace la visita por su cuenta Put_Line("[T] GRUPO"&IntegerImage(Id)&" encuentra el punto de informacion vacio. Inician la visita por su cuenta"); else -- Se le ha asignado un guia, ahora le esperan si es necesario Put_Line("[T] GRUPO"&IntegerImage(Id)&" en espera del GUIA"&IntegerImage(Guia)); Guias(Guia).Coger(Id); Put_Line("[G] GUIA"&IntegerImage(Guia)&" se encuentra con el GRUPO"&IntegerImage(Id)); end if; -- Ahora recorremos la ruta for I in 1..PUNTOS_POR_RUTA loop Rutas(Ruta)(I).Entrar(Id, N, Ok); if Ok then delay(Positive_Random(10)*1.0); Rutas(Ruta)(I).Salir(Id);

136 137 138 139 140 141

142 143 144

145

146 147

148

149 150

151 152 153 154 155 156 157

257

Programaci n Concurrente o
end if; end loop; -- Hemos terminado de ver la ruta Put_Line("[T]<GRUPO"&IntegerImage(Id)&" ("&IntegerImage(N)& " personas) termina de visitar la RUTA"&IntegerImage(Ruta )); if Guia /= -1 then -- Liberamos al guia Guias(Guia).Liberar; end if; end Grupo_Turistas; begin -- Creamos los guias for I in 1..3 loop Guias(I).Init(I); end loop; -- Creamos las rutas (sus puntos de interes) Contador_Puntos := 0; for I in 1..3 loop for J in 1..PUNTOS_POR_RUTA loop Contador_Puntos := Contador_Puntos + 1; Rutas(I)(J).Init(Contador_Puntos, Positive_Random(10)); end loop; end loop; -- Creamos los grupos de turistas for I in 1..NUM_GRUPOS loop delay(Positive_Random(5)*1.0); Grupos(I).Init(I, Positive_Random(3)); end loop; end Almorox;

158 159 160 161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

258

Ejercicio asignado - Jardineros

Ejercicio asignado 2

Jardineros
2.1 Enunciado

La cuadrilla de jardineros. En un pueblo existen N jardineros todos ellos muy amigos y perezosos. Cada da el alcalde del ayuntamiento obliga a trabajar a estos jardineros en sus tareas. Dichas tareas consisten, entre otras, en podar los arboles de las avenidas, regar los arboles, las macetas del alcalde, o plantar ores en las rotondas. Al principio de cada da a los jardineros se les dicen las tareas a realizar, y no terminan su jornada hasta que las completan. El alcalde no les deja que dos est n haciendo la misma tarea al e mismo tiempo pues como son perezosos se ponen a hablar. Algunos jardineros suelen trabajar a ritmo r pido (una minora) y el resto a ritmo lento, pero a de vez en cuando el se or alcalde se da vueltas y bajo su mirada todos los jardineros trabajan a n ritmo r pido. El grupo trabajar al ritmo el m s lento. a a a Puesto que el trabajo asignado debe ser realizado en el da, los componentes del grupo pueden reprender al lento o los lentos y hacen que trabaje siempre cuando los lentos no superen m s de a un porcentaje del total de grupo (por ejemplo el 25%). Si el alcalde, al hacer ronda, encuentra alg n jardinero trabajando a ritmo lento, le rega ara y u n le pondr una amonestaci n. Si supera las M amonestaciones ser despedido. a o a Hay gente que de vez en cuando estropea los jardines o el mobiliario urbano, y hay que reparar los da os. El alcalde en sus rondas detectar dichos da os y mandar a un jardinero al azar a n a n a repararlos. Los jardineros despedidos suelen ser buenos candidatos a saboteadores para vengarse del alcalde.

259

Programaci n Concurrente o

2.2
2.2.1

Resoluci n por citas en Ada o


Explicaci n o

En la resoluci n de este problema por citas, tendremos cuatro tareas: una tarea alcalde the mayor, o tareas jardineros,gardener, una tarea reloj para el alcade clock mayor y una tarea reloj para los jardineros que les indicar el inicio de una jornada. clock gardener. a A los jardineros se les manda trabajar, cada uno a su manera: lento o r pido. El alcalde har a a su ronda si hay alg n jardinero lento lo sanciona, a las 3 sanciones lo despide. Los jardineros se u ponen a trabajar en modo r pido pero cuando el alcalde se va vuelven a su estado antiguo. a El reloj del alcalde le avisa para hacer la ronda, al igual que el reloj de los jardineros, que les indica el inicio de una nueva jornada.

2.2.2

C digo Fuente o
C digo fuente 2.1: Jardineros por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

with TEXT_IO,random,Ada.Exceptions; use TEXT_IO,random,Ada.Exceptions; procedure jardineros is --constant an variables MAX_GARDENER: constant Integer:= 5; --max of gardeners FAST_TIME: constant Integer:= 2; LOW_TIME: CONSTANT Integer:= 5; type mode is (fast,low); damage:boolean:=false; --damage in some place init_mode: array(1..MAX_GARDENER) of mode; MAX_W:Integer:=3; --max gardeners warnings total_gardeners:Integer:=MAX_GARDENER; MAX_TIME_WORK:integer:= 5; MAX_TIME_REVIEW:integer:=6; type work_mode is (FastFreq,SlowFreq); --work mode-type gardener_state is record id : integer; --id m : mode; --mode of gardener low or fast working : boolean:=false; --if work or not time : duration; warning : integer; --mayors warnings fired : boolean:=false; --fired or not end record;

gardenerState: array (1..MAX_GARDENER) of gardener_state;

--task gardener task type gardener is entry init_gardener(x : integer);

260

Ejercicio asignado - Jardineros


entry work; entry repair; --entry Fix end gardener; gardeners : array (1..MAX_GARDENER) of gardener;

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

--task mayor task the_mayor is entry init_mayor; entry revision; end the_mayor; --task clock mayor task clock_mayor is entry init; end clock_mayor; --task clock gardener task clock_gardener is entry init; end clock_gardener;

70 71 72

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

task body gardener is id:integer; begin accept init_gardener(x:integer) do id:=x; end init_gardener; loop select when gardenerState(id).working = false and gardenerState(id).fired = false and total_gardeners>0 => accept work do --gardener working gardenerState(id).working:=true; --is working put_line("gardener: "&IntegerImage(id)&" is working in mode "& modeImage(gardenerState(id).m)); if gardenerState(id).m = fast then delay duration(FAST_TIME); else delay duration(LOW_TIME); end if; end work; gardenerState(id).working := false; or accept repair do if gardenerState(id).m = fast then delay duration(FAST_TIME); else delay duration(LOW_TIME); end if;

261

Programaci n Concurrente o

90 91

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

put_line("gardener : "&IntegerImage(id)&" is reparing in mode "& modeImage(gardenerState(id).m)); damage:= false; end repair; or terminate; end select; end loop; end gardener; task body the_mayor is begin accept init_mayor; loop select accept revision do put_line("THE MAYOR IS REVISES"); for i in 1..MAX_GARDENER loop init_mode(i):= gardenerState(i).m; --save the init_mode if gardenerState(i).m = low then gardenerState(i).warning := gardenerState(i). warning+1; put_line("The gardener: "&IntegerImage(i)& " has been baned"); gardenerState(i).m := fast; end if; if gardenerState(i).warning >= MAX_W and gardenerState(i).fired = false then --if gardener not fired put_line("The gardener: "&IntegerImage(i)& " has been fired"); gardenerState(i).fired:=true; total_gardeners:=total_gardeners -1; if positive_random(2) = 1 then damage := true; --the gardener demage some place end if; end if; end loop; if damage = true then gardeners(Positive_random(MAX_GARDENER)).repair; end if; for i in 1.. MAX_GARDENER loop if gardenerState(i).working = false and gardenerState(i).fired = false then gardenerState(i).m:=init_mode(i); end if; end loop;

112 113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

262

Ejercicio asignado - Jardineros


end revision; or terminate; end select; end loop; end the_mayor; task body clock_mayor is begin accept init; loop delay duration(5); the_mayor.revision; end loop; end clock_mayor; task body clock_gardener is begin accept init; loop delay duration(6); for i in 1..MAX_GARDENER loop if gardenerState(i).working = false and gardenerState(i).fired = false then gardeners(i).work; end if; end loop; end loop; end clock_gardener;

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

begin for i in 1..MAX_GARDENER loop gardenerState(i).id:=i; gardenerState(i).working:=false; gardenerState(i).fired:=false; gardenerState(i).warning:=0; if Positive_Random(2) = 1 then gardenerState(i).m:=fast; else gardenerState(i).m := low; end if; gardeners(i).init_gardener(i); gardeners(i).work; end loop; the_mayor.init_mayor; clock_mayor.init; clock_gardener.init; end jardineros;

263

Programaci n Concurrente o

264

Ejercicio asignado - Restaurante

Ejercicio asignado 3

Restaurante
3.1 Enunciado

Un restaurante tiene tres salas cada una con un conjunto de mesas con distintas capacidades. Debido a la normativa gubernamental no pueden mezclar fumadores y no fumadores. As, una vez que se ha asignado una sala a fumadores (no fumadores), no pasar n a ella no a fumadores (respectivamente, fumadores), salvo que la sala quede libre. Para que pueda darse servicio a todos, se establece que no puede haber m s de dos salas dedicadas bien a fumadores, o a bien a no fumadores. El mecanismo de asignaci n de las mesas es el siguiente. Cuando un grupo de clientes llega o al restaurante indica al matre si son fumadores o no fumadores, y el n mero de componentes del u grupo (todo el grupo se clasica como fumador o no fumador). Los grupos se entienden indivisibles, esto es, comer n juntos en la misma mesa. As, si existe una mesa libre que pueda albergarlos a a todos, se les asigna, en otro caso, esperar n en una sala de espera que ha habilitado ex-profeso a el restaurante a que se les llame al quedar libre una mesa. Ahora bien, no esperar n eternamente, a y si transcurre un tiempo determinado y no han sido llamados se marchan del restaurante. Dise e un programa concurrente que simule el sistema, supuesto que se pretende maximizar n el n mero de clientes atendidos. u

265

Programaci n Concurrente o

3.2
3.2.1

Resoluci n por citas Ada o


Explicaci n o

Se tienen dos tareas, la tarea grupo y la tarea metre. El grupo lo primero que har ser pedir mesa a a al metre, este les madar comer si tiene una mesa de la capacidad del grupo y adem s del tipo a a del grupo (fumador o no fumador). En caso de que no haya sitio, el metre les mandar esperar en a una sala de espera de capacidad limitada, si hay sitio en la sala de espera el grupo espera, si no, el grupo se marcha. Si el grupo tiene que esperar, no va a aesperar eternamente, preguntar de vez en cuando al a metre si tiene una mesa, si ha pasado un tiempo y no le han dado mesa al grupo, el grupo se marchar enfadado. a Cuando una sala est vacia y entra un grupo a esa sala se le asigna el tipo del grupo, es decir la a sala ser para fumadores o no fumadores dependiendo del tipo que sea el primer grupoq ue entre a a la sala, siempre y cuando el n mero de salas de un grupo no sea mayor de dos. u

3.2.2

C digo Fuente o
C digo fuente 3.1: Restaurante por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions;

12 13 14

15 16 17

18 19 20 21 22 23 24 25 26 27 28

procedure restaurante_citas is type Respuesta is(NADA,Comer,Esperar,Marcharse); --Respuesta del Metre cuando lleguen al restaurante MaximoGrupos: constant Integer:=25; --Indica el numero maximo de grupos que quieren comer MaximoComponentes: constant Integer:=10; --Indica el numero maximo de componentes que van a integrar el grupo type Vicio is (Fumador, NoFumador,Nada); --Indica si el grupo o sala es de tipo fumador o no MaximoTimepoEspera: constant Integer:= 5;-- tiempo que espera un grupo --para pasar a comer. MaximoSalas: constant Integer:= 3; --maximo n mero de salas. MaximaCapSala: constant Integer:=10;--maximo de personas por sala nsalasF : Integer:=0; --numero de salas fumadoras. nsalasNF : Integer:=0; --numero de salas no fumadoras. capacidad_espera : Integer:= 10; type Sala is record Id:Integer:=-1; -- id de la sala capacidad:Integer; --capacidad de la sala vic: Vicio:= Nada; --fumadora no fumadora end record;

266

Ejercicio asignado - Restaurante

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

salas: array(1..3) of Sala;

task type grupo is entry init_grupo(id: in Integer; ncomponentes: in Integer; vic: in Vicio); entry comer; entry esperar; end grupo; --creamos los grupos grupos: array(1..MaximoGrupos) of grupo; task metre is entry init_metre; entry dar_mesa(idd: in Integer; ncomponentes: in Integer; vicc: in Vicio; pasar_comer: out Respuesta; s: out Integer; estado: out Respuesta); entry salir(id: in Integer; ncomponentes: Integer; s:Integer) ; entry salir_enfadado(id: in Integer; ncomponentes:Integer); end metre; task body grupo is idd:Integer; ncomponentess: Integer; vicc:Vicio; pasar_comer:Respuesta;--para saber si pasa a comer o no. --estado: Respuesta; --para ver como se encuentra el grupo s:Integer:=0; estado: Respuesta; begin accept init_grupo (id: in Integer; ncomponentes: in Integer; vic: in Vicio) do idd:=id; ncomponentess:= ncomponentes; vicc:= vic; pasar_comer:=NADA; estado:= NADA; end init_grupo; metre.dar_mesa(idd,ncomponentess,vicc,pasar_comer,s,estado); loop select accept comer do put_line("El grupo: "&IntegerImage(idd)& " esta comiendo en la sala"&IntegerImage(s )); delay duration(Positive_random(5));--tarda un tiempo en comer; --se marcha cuando ha terminado de comer

46 47 48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

76

77

267

Programaci n Concurrente o
estado:= Comer; end comer; if estado = Comer then metre.salir(idd, ncomponentess,s);--ha comido y se sale end if; or accept esperar do put_line("El grupo: "&IntegerImage(idd)& " esta esperando en la sala de espera"); pasar_comer:= Esperar; estado:=Esperar; end esperar; if estado = Esperar then for i in 1.. MaximoTimepoEspera loop delay(2.0); metre.dar_mesa(idd,ncomponentess,vicc,pasar_comer ,s,estado); exit when pasar_comer = comer; end loop; if pasar_comer /= comer then metre.salir_enfadado(idd,ncomponentess); end if; end if; end select; end loop; end grupo; task body metre is ultimo_grupo:Integer; --ultimo grupo atendido. pasa_a_comer:Respuesta; begin loop select accept init_metre do for i in 1..MaximoSalas loop salas(i).Id := i; salas(i).capacidad:= MaximaCapSala; Put_Line("Sala : "&IntegerImage(i)&" tiene una capacidad de: "& IntegerImage(salas(i).capacidad)); end loop; end init_metre; or accept dar_mesa(idd: in Integer; ncomponentes: in Integer; vicc: in Vicio; pasar_comer: out Respuesta; s: out Integer; estado: out Respuesta) do ultimo_grupo:=idd;--guardamos el ultimo grupo --busco hueco libre entre las 3 salas. for i in 1..MaximoSalas loop

78 79 80 81

82 83 84 85 86 87 88 89 90 91 92 93 94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

117 118 119 120 121 122

123

124

125 126 127

268

Ejercicio asignado - Restaurante


pasar_comer := NADA; if (salas(i).vic = vicc or salas(i).vic = NADA) and salas(i).capacidad >= ncomponentes then --si es del mismo tipo que el grupo y hay sitio, entro en la sala. --asigno a la sala el tipo, fumador o no fumador, controlando que no haya m s de dos iguales. if vicc = Fumador and nsalasF<2 and salas(i). vic = NADA then nsalasF:= nsalasF+1; salas(i).vic := Fumador; elsif vicc = NoFumador and nsalasNF<2 and salas(i).vic = NADA then nsalasNF:=nsalasNF+1; salas(i).vic := NoFumador; end if; Put_Line("El grupo: "&IntegerImage(idd)&" con : " &IntegerImage(ncomponentes)& " componentes, y que son : " &VicioImage(vicc)&" va a comer en la sala"&IntegerImage(i)); salas(i).capacidad:= salas(i).capacidad ncomponentes; --le quito capacidad a la sala. --se reserva el sitio al grupo. pasar_comer := Comer; --van a pasar a comer s:= i; --se le asigna una sala al grupo exit; -- si tienen sitio dejan de buscar. end if; end loop; put_line(" pasa_comer : "&RespuestaImage( pasar_comer)& "y estado: "&RespuestaImage(estado )); if pasar_comer /= Comer and estado = NADA then --si hay sitio en la sala de espera deben esperar if capacidad_espera >= ncomponentes then pasar_comer:= Esperar; estado:= Esperar; capacidad_espera:= capacidad_esperancomponentes; --van a la sala de espera else --si no hay sitio se marcharan pasar_comer:= Marcharse; estado:= Marcharse; end if; end if; pasa_a_comer:=pasar_comer; end dar_mesa;

128 129

130

131

132

133 134 135

136 137 138 139

140

141

142

143 144 145 146 147 148 149 150

151 152 153 154 155 156 157 158

159 160 161 162 163 164 165 166 167 168

269

Programaci n Concurrente o
if pasa_a_comer = Comer then grupos(ultimo_grupo).comer; elsif pasa_a_comer = Esperar then grupos(ultimo_grupo).esperar; end if; or accept salir(id: Integer; ncomponentes: Integer; s: Integer) do --se van del restaurante y de la sala salas(s).capacidad:= salas(s).capacidad+ncomponentes ; put_line("El grupo : "&IntegerImage(id)&" se va del restaurante. ADIOS"); if salas(s).capacidad = MaximaCapSala then -- si las salas se quedan sin gente pueden ser de otro tipo if salas(s).vic = Fumador then nsalasF:= nsalasF-1; else nsalasNF:= nsalasNF-1; end if; salas(s).vic:= NADA; --la sala no tiene asignado un tipo de vicio. end if; end salir; or accept salir_enfadado(id: in Integer; ncomponentes: Integer) do put_line("El grupo : "&IntegerImage(id)&" se ha ido enfadado porque no le atienden"); capacidad_espera:= capacidad_espera+1; end salir_enfadado;

169 170 171 172 173 174 175 176

177 178

179

180 181

182 183 184 185 186 187 188 189 190 191 192

193

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

end select; end loop; end metre;

209 210 211 212

begin metre.init_metre; for i in 1..MaximoGrupos loop if(Positive_Random(2) = 1) then grupos(i).init_grupo(i,Positive_Random(MaximoComponentes), Fumador); delay duration(Positive_Random(5)); else grupos(i).init_grupo(i,Positive_Random(MaximoComponentes), NoFumador); delay duration(Positive_Random(5)); end if; end loop; end restaurante_citas;

213 214 215 216

270

Ejercicio asignado - Restaurante

271

Programaci n Concurrente o

3.3
3.3.1

Resoluci n por monitores en Ada o


Explicaci n o

El comportamiento es el mismo que para citas, aqu tendremos un monitor que ser el metre, al que a los grupos se dirigira para coger mesa, comer, salir o salir enfadados. Todo el funcionamiento es n el mismo que en citas lo unico que cambia es lo descrito al principio.

3.3.2

C digo Fuente o
C digo fuente 3.2: Restaurante por monitores en Ada o

1 2 3 4 5 6 7 8 9 10 11

with TEXT_IO, random, Ada.Exceptions; use TEXT_IO, random, Ada.Exceptions;

12 13 14

15 16 17

procedure restaurante is type Respuesta is(NADA,Comer,Esperar,Marcharse); --Respuesta del Metre cuando lleguen al restaurante MaximoGrupos: constant Integer:=25; --Indica el numero maximo de grupos que quieren comer MaximoComponentes: constant Integer:=10; --Indica el numero maximo de componentes que van a integrar el grupo type Vicio is (Fumador, NoFumador,Nada); --Indica si el grupo o sala es de tipo fumador o no MaximoTimepoEspera: constant Integer:= 5;-- tiempo que espera un grupo --para pasar a comer. MaximoSalas: constant Integer:= 3; --maximo n mero de salas. MaximaCapSala: constant Integer:=10;--maximo de personas por sala

18 19 20 21 22 23 24 25 26 27 28 29

type Sala is record Id:Integer:=-1; -- id de la sala capacidad:Integer; --capacidad de la sala vic: Vicio:= Nada; --fumadora no fumadora end record; protected metre is procedure init;--inicializa al metre procedure coger_mesa(id:Integer; ncomponentes: in Integer; vic: in Vicio; pasar_comer: out Respuesta; estado: out Respuesta; s: out Integer); procedure comer(id:Integer; ncomponentes: in Integer;vic: in Vicio; estado: in Respuesta); procedure salir(id:Integer; ncomponentes: in Integer;vic: in Vicio; estado: in Respuesta; s: in Integer); procedure salir_enfadado(id:Integer; ncomponentes: in Integer ; s: in Integer);

30

31

32

33

272

Ejercicio asignado - Restaurante

34 35 36 37 38 39 40 41 42 43 44 45 46

private nsalasF:Integer:=0; --numero de salas fumadoras. nsalasNF:Integer:=0; --numero de salas no fumadoras. capacidad_espera:Integer:= 10; end metre; task type grupo is entry init_grupo(id: in Integer; ncomponentes: in Integer; vic: in Vicio); --pasamos un id de grupo, el numero de componentes y si fuman o no. end grupo; grupos: array(1..MaximoGrupos) of grupo; salas: array(1..3) of Sala; task body grupo is idd:Integer; ncomponentess: Integer; vicc:Vicio; pasar_comer:Respuesta;--para saber si pasa a comer o no. estado: Respuesta; --para ver como se encuentra el grupo s:Integer:=0; begin accept init_grupo(id : in Integer; ncomponentes: in Integer; vic : in Vicio) do idd:=id; ncomponentess:= ncomponentes; vicc:= vic; end init_grupo;

47 48

49 50 51 52 53 54 55 56 57 58 59 60 61 62

63 64 65 66 67 68 69

70 71 72 73 74 75 76

metre.coger_mesa(idd,ncomponentess,vicc,pasar_comer,estado,s) ; --el grupo pide mesa delay duration(Positive_random(2)); if pasar_comer = Comer then --si le dan mesa pasa a comer metre.comer(idd,ncomponentess,vicc,estado); delay duration(Positive_random(5));--come metre.salir(idd,ncomponentess,vicc,estado,s); --el grupo se va elsif pasar_comer = Esperar then --el grupo debe esperar en la sala de espera put_line("El grupo : "&IntegerImage(idd)&" no tiene mesa, " &"por tanto espera"&" ESTADO : "&Respuesta Image(estado)); for i in 1..MaximoTimepoEspera loop --esperan no mas de 10 segundos

77

78

79

80

273

Programaci n Concurrente o
delay duration(Positive_random(2)); put_line("Preguntando..al metre grupo : "&IntegerImage (idd)); metre.coger_mesa(idd,ncomponentess,vicc,pasar_comer, estado,s); --vuelven a pedir mesa exit when pasar_comer = Comer; end loop; if pasar_comer = Comer then --si tienen mesa comen metre.comer(idd,ncomponentess,vicc,estado); delay duration(Positive_random(5));--comen metre.salir(idd,ncomponentess,vicc,estado,s);--el grupo se va else metre.salir_enfadado(idd,ncomponentess,s);--el grupo se va enfadad, no tienen mesa end if; else put_line("El grupo: "&IntegerImage(idd)&" no tiene mesa, " &"y no hay hueco en la sala de espera, por tanto se marcha"&RespuestaImage(estado)); --el grupo no tiene mesa y no hay sitio para esperar en la sala de espera. end if;

81 82

83

84 85 86 87 88 89 90

91 92

93 94 95

96

97

98 99 100 101 102 103 104 105 106 107 108 109 110

end grupo; protected body metre is procedure init is begin --el metre prepara las salas. for i in 1..3 loop salas(i).Id := i; salas(i).capacidad:= MaximaCapSala; Put_Line("Sala: "&IntegerImage(i)&" tiene una capacidad de: "& IntegerImage(salas(i).capacidad)); end loop; end init; procedure coger_mesa(id:Integer; ncomponentes: in Integer;vic : in Vicio; pasar_comer: out Respuesta; estado: out Respuesta;s: out Integer) is begin Put_Line("El grupo: "&IntegerImage(id)&" quiere comer, son: " &IntegerImage(ncomponentes)& " componentes, y son: " &VicioImage(vic));

111 112 113 114 115 116

117

118 119 120 121 122

123

124

274

Ejercicio asignado - Restaurante

125 126 127 128 129 130

131

132

133 134 135

136 137 138 139 140

141

142

143 144 145 146 147 148 149 150

--busco hueco libre entre las 3 salas. for i in 1..MaximoSalas loop pasar_comer := NADA; if (salas(i).vic = vic or salas(i).vic = NADA) and salas(i).capacidad >= ncomponentes then --si es del mismo tipo que el grupo y hay sitio, entro en la sala. --asigno a la sala el tipo, fumador o no fumador, controlando que no haya m s de dos iguales. if vic = Fumador and nsalasF<2 and salas(i).vic = NADA then nsalasF:= nsalasF+1; salas(i).vic := Fumador; elsif vic = NoFumador and nsalasNF<2 and salas(i). vic = NADA then nsalasNF:=nsalasNF+1; salas(i).vic := NoFumador; end if; Put_Line("El grupo: "&IntegerImage(id)&" con: " &IntegerImage(ncomponentes)& " componentes , y que son : " &VicioImage(vic)&" va a comer en la sala"& IntegerImage(i)); salas(i).capacidad:= salas(i).capacidad ncomponentes; --le quito capacidad a la sala. --se reserva el sitio al grupo. pasar_comer := Comer; --van a pasar a comer s:= i; --se le asigna una sala al grupo exit; -- si tienen sitio dejan de buscar. end if; end loop; put_line(" pasa_comer: "&RespuestaImage(pasar_comer)& "y estado: "&RespuestaImage(estado)); if pasar_comer /= Comer and estado = NADA then --si hay sitio en la sala de espera deben esperar if capacidad_espera >= ncomponentes then pasar_comer:= Esperar; estado:= Esperar; capacidad_espera:= capacidad_espera-ncomponentes; --van a la sala de espera else --si no hay sitio se marcharan pasar_comer:= Marcharse; estado:= Marcharse; end if; end if; end coger_mesa; procedure comer(id:Integer; ncomponentes: in Integer;vic: in Vicio; estado: in Respuesta) is begin

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

169 170

275

Programaci n Concurrente o
if estado /= NADA then --si estaban en la sala de espera. capacidad_espera:= capacidad_espera+ncomponentes; --se van de la sala de espera. end if; Put_Line("El grupo: "&IntegerImage(id)&" con: " &IntegerImage(ncomponentes)& " componentes, y que son : " &VicioImage(vic)&" e s t n comiendo");

171 172 173 174 175 176

177 178 179 180 181 182

end comer; procedure salir(id:Integer; ncomponentes: in Integer;vic: in Vicio; estado: Respuesta; s: in Integer) is begin --se van del restaurante y de la sala salas(s).capacidad:= salas(s).capacidad+ncomponentes; put_line("El grupo: "&IntegerImage(id)&" se va del restaurante. ADIOS"); if salas(s).capacidad = MaximaCapSala then -- si las salas se quedan sin gente pueden ser de otro tipo if salas(s).vic = Fumador then nsalasF:= nsalasF-1; else nsalasNF:= nsalasNF-1; end if; salas(s).vic:= NADA; --la sala no tiene asignado un tipo de vicio. end if; end salir; procedure salir_enfadado(id:Integer; ncomponentes: in Integer ; s: in Integer) is begin put_line("El grupo: "&IntegerImage(id)&" se ha ido enfadado porque no le atienden"); capacidad_espera:=capacidad_espera+1; end salir_enfadado; end metre; begin metre.init; for i in 1..MaximoGrupos loop if(Positive_Random(2) = 1) then grupos(i).init_grupo(i,Positive_Random(MaximoComponentes), Fumador); delay duration(Positive_Random(5)); else grupos(i).init_grupo(i,Positive_Random(MaximoComponentes), NoFumador); delay duration(Positive_Random(5)); end if; end loop; end restaurante;

183 184 185 186

187 188

189 190 191 192 193 194 195 196 197 198

199 200

201 202 203 204 205 206 207 208 209

210 211 212 213

214 215 216 217

276

Ejercicio asignado - Aeropuerto

Ejercicio asignado 4

Aeropuerto
4.1 Enunciado

El aeropuerto de Chinchilla de los Montes es famoso entre los pilotos por la buena organizaci n o de su torre de control. Corre el rumor de que el sistema de gesti n de pistas fue programado por o un alumno de TP. El problema le fue planteado en los siguientes t rminos: un conjunto de aviones solicitan e permiso para despegar o para aterrizar (para simplicar el problema, supongamos que hay D de los primeros, A de los segundos y que realizan todo el proceso de despegue o aterrizaje dentro de un bucle innito). A continuaci n, esperan permiso de la torre para usar una pista, decidida por o esta, y una vez obtenido, proceden a la maniobra. Cuando naliza la misma, lo comunican a la torre. El aeropuerto dispone de dos pistas que pueden utilizarse indistintamente para despegue o aterrizaje con las siguientes restricciones: si una pista est siendo utilizada para despegue, puede a haber un m ximo de tres aviones realizando simult neamente tal maniobra (forman una la en la a a cabecera de la pista); si se usa para aterrizaje, s lo habr un avi n simult neamente realizando o a o a la maniobra en dicha pista. Adicionalmente, si hay aviones esperando para aterrizar se les dar a prioridad frente a los despegues. En concreto, se congelar n nuevos permisos de despegue en a la pista menos ocupada para que quede libre lo antes posible y se pueda aterrizar en ella. Los permisos para despegue se conceder n por orden estricto de solicitud e igual criterio se seguir a a con los de aterrizaje. Dise e un programa concurrente que satisfaga estas restricciones, sin bloqueos ni inanici n, y n o que sea al menos tan bueno como el que dio fama al aeropuerto de Chinchilla.

277

Programaci n Concurrente o

4.2
4.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para resolver este problema mediante citas, he creado dos tareas Torre, Avin. La torre de o control ser la que se encargar de recibir las peticiones de los aviones y las gestionar de forma a a a adecuada, permitiendo el paso a uno u otros aviones seg n las especicaciones del enunciado. u La tarea torre de control, tiene estos puntos de entrada: solicitoAterrizar(Id:Integer;Pista:out Integer): un avi n solicita atero rizar, se le devolver la pista en la que pued hacerlo, y si no puede hacerlo en ese momento a se devolver un cero y se guardar su petici n para atenderla cuando se pueda. a a o solicitoDespegar(Id:Integer;Pista:out Integer): un avi n solicita deo spegar, y se gestionar de igual forma que en el punto de entrada anterior. a Termino(Pista:Integer): un avi n indica a la torre de control, que ha terminado de o despegar o aterrizar en una determinada pista. La tarea avi n tendr estos puntos de entrada: o a Init (Ii:Integer; quiere:estado): punto de entrada para la inicializaci n de o los aviones. Permiso(Pista:Integer): si a un avi n no se le ha concedido despegar o aterrizar o en el momento en el que lo ha pedido, esperar en este punto hasta que se lo den. a Para que no se den llamadas a tareas (aviones) que ya han terminado su ejecuci n, siempre o que damos permiso a alg n avi n marcamos como atendido su petici n en un vector de variables u o o l gicas, para no volver a llamar a ese avi n m s. o o a

4.2.2

C digo fuente o
C digo fuente 4.1: Aeropuerto por citas en Ada o

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

--Problema asignado: Aeropuerto de Chinchilla --David Antonio Perez Zaba with ada.text_io; with ada.integer_text_io; with Ada.Numerics.Float_Random ; use Ada.Numerics.Float_Random; use ada.integer_text_io; use ada.text_io;

procedure Aeroport is G:Generator;

278

Ejercicio asignado - Aeropuerto


--num. aviones para despegar D:Integer:=3; --num. aviones para aterrizar A:Integer:=6; -------------------------------------------------num. maximo aviones despegando por pista Max_AD:Integer:=3; --num. maximo aviones aterrizando por pista MAx_AA:Integer:=1; type estado is (Aterrizar,Despegar,nada); --prioridad a los aviones estadoue estadouieren aterrizar (en la pista mas despejada) task type avion is entry Init (Ii:Integer; quiere:estado); entry Permiso(Pista:Integer); end avion; task torre is entry solicitoAterrizar(Id:Integer;Pista:out Integer); entry solicitoDespegar(Id:Integer;Pista:out Integer); entry Termino(Pista:Integer); end torre; A_Aterrizar:array (1..A) of Avion; A_Despegar:array (1..D) of Avion; --vectores de aviones antendidos Atend_Aterrizar:array (1..A) of Boolean; Atend_Despegar:array (1..D) of Boolean;

17 18 19 20 21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

task body Avion is quiero:estado; Id:Integer; Pis:Integer; begin accept Init (Ii:Integer;quiere:estado)do Id:=Ii; quiero:=quiere; end Init; if quiero=Aterrizar then --pedir permiso Torre.solicitoAterrizar(Id,Pis); else --pedir permiso Torre.solicitoDespegar(Id,Pis); end if; --si no nos dieron permiso, esperamos a que nos lo den if Pis=0 then accept Permiso(Pista:Integer) do Pis:=Pista;

279

Programaci n Concurrente o
if quiero=Aterrizar then Put_Line("++ Avion ("&IntegerImage(Id)&"A) tiene Permiso p:"&IntegerImage(Pis)); else Put_Line("++ Avion ("&IntegerImage(Id)&"D) tiene Permiso p:"&IntegerImage(Pis)); end if; end Permiso; end if; --tarda un rato delay (2.0); --aterrizamos o despegamos if quiero=Aterrizar then Put_Line("<< Avion ("&IntegerImage(Id)&"A) termina IntegerImage(Pis)); else Put_Line("<< Avion ("&IntegerImage(Id)&"D) termina IntegerImage(Pis)); end if; Torre.Termino(Pis); end Avion;

72 73

74 75

76 77 78 79 80 81 82 83 84 85

p:"&

86 87

p:"&

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

task body Torre is N_1:Integer:=0; N_2:Integer:=0; Estado1:estado:=Nada; Estado2:estado:=Nada; Esp_Aterrizar:Integer:=0; P:Integer; function HayVacia return Boolean is begin if Estado1=Nada then return True; elsif Estado2=Nada then return True; else return False; end if; end HayVacia; function DameVacia return Integer is V:Integer:=0; begin if Estado1=Nada then V:=1; elsif Estado2=Nada then V:=2;

280

Ejercicio asignado - Aeropuerto


end if; return V; end DameVacia; procedure CambiaEstado(Pis:Integer;Est:Estado) is begin if Pis=1 then Estado1:=Est; elsif Pis=2 then Estado2:=Est; end if; end CambiaEstado; function CabeAvion(Pis:Integer) return Boolean is begin if Pis=1 then return N_1<Max_AD; else return N_2<Max_AD; end if; end CabeAvion; procedure AumentaN(Pis:Integer) is begin if Pis=1 then N_1:=N_1+1; elsif Pis=2 then N_2:=N_2+1; end if; end AumentaN; begin loop select accept solicitoAterrizar(Id:Integer;Pista:out Integer) do Put_Line(">> Avion ("&IntegerImage(Id)&"A) solicita Aterrizar"); Pista:=0; if HayVacia then --obtenemos la pista P:=DameVacia; --devolvemos la pista que va a utilizar el avion Pista:=P; --cabemos despegando en la pista p if CabeAvion(P) then --cambiamos el estado de la pista a aterrizar CambiaEstado(P,Aterrizar); --aumentamos el num. aviones en esa pista AumentaN(P); Put_Line("++ Avion ("&IntegerImage(Id)&"A) tiene Permiso p:"&IntegerImage(pista)); --marcamos como ya atendido Atend_Aterrizar(Id):=True; end if;

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

159

160 161 162 163 164 165 166 167 168 169 170 171 172

173 174 175 176

281

Programaci n Concurrente o
else Esp_Aterrizar:=Esp_Aterrizar+1; end if; end SolicitoAterrizar; or --atendemos cuando no haya nadie aterrizando (damos prioridad a aterrizar) when Esp_Aterrizar=0 => accept solicitoDespegar(Id:Integer;Pista:out Integer ) do Put_Line(">> Avion ("&IntegerImage(Id)&"D) solicita Despegar"); Pista:=0; if HayVacia or (Estado1=Despegar and CabeAvion(1)) or (Estado2=Despegar and CabeAvion(2)) then --vemos el motivo por el que hemos entrado al if, para saber que pista asignar if HayVacia then P:=DameVacia; Pista:=P; else if Estado1=Despegar then Pista:=1; else Pista:=2; end if; end if; Put_Line("++ Avion ("&IntegerImage(Id)&"D) tiene Permiso p:"&IntegerImage(Pista)); AumentaN(P); CambiaEstado(P,Despegar); --marcamos avion como atendido Atend_Despegar(Id):=True; end if; end SolicitoDespegar; or accept Termino(Pista:Integer)do --un avion menos en la pista if Pista=1 then N_1:=N_1-1; else N_2:=N_2-1; end if; --si es el ultimo, no hay estado de la pista if N_1=0 then Estado1:=Nada; elsif N_2=0 then Estado2:=Nada; end if; --------------------------------------------revisamos todas las peticiones pendientes --primero los que quieren aterrizar for Ii in 1..A loop if HayVacia and not Atend_Aterrizar(Ii) Then P:=DameVacia; A_Aterrizar(Ii).Permiso(P);

177 178 179 180 181 182

183 184

185

186 187

188

189 190 191 192 193 194 195 196 197

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

282

Ejercicio asignado - Aeropuerto


AumentaN(P); CambiaEstado(P,Aterrizar); Esp_Aterrizar:=Esp_Aterrizar-1; --marcamos como atendido Atend_Aterrizar(Ii):=True; end if; end loop; --recorremos los que quieren DESPEGAR for Ii in 1..D loop --si no hay esperando a aterrizar if Esp_Aterrizar=0 and not Atend_Despegar(Ii) Then --si hay pista libre, y cabe el avion en ella if HayVacia then P:=DameVacia; if HayVacia or (Estado1=Despegar and CabeAvion(1)) or (Estado2=Despegar and CabeAvion(2)) then --vemos el motivo por el que hemos entrado al if, para saber que pista asignar if HayVacia then P:=DameVacia; A_Despegar(Ii).Permiso(P); AumentaN(P); CambiaEstado(P,Despegar); else if Estado1=Despegar then A_Despegar(Ii).Permiso(1); AumentaN(1); Cambiaestado(1,Despegar); else A_Despegar(Ii).Permiso(2); AumentaN(2); Cambiaestado(2,Despegar); end if; end if; --marcamos como atendido Atend_Despegar(Ii):=True; end if; end if; end if; end loop; end Termino; or terminate; end select; end loop; end Torre; begin

227 228 229 230 231 232 233 234 235 236 237 238 239 240

241 242 243 244

245

246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

283

Programaci n Concurrente o

278 279 280 281 282 283 284 285 286 287 288 289 290

for Ii in 1..D loop Atend_Despegar(Ii):=False; A_Despegar(Ii).Init(Ii,despegar); end loop; for Ii in 1..A loop Atend_Aterrizar(Ii):=False; A_Aterrizar(Ii).Init(Ii,Aterrizar); end loop; end Aeroport;

284

Ejercicio asignado - Audi A3

Ejercicio asignado 5

Audi A3
5.1 Enunciado

Audi, ha sacado a las calles de las capitales de provincia un Audi A3 que estar a disposici n de a o todo el mundo con el n de que prueben su vehculo con la posibilidad de ser los ganadores de uno de ellos. Las condiciones que impone la marca son: S lo se podr montar un ciudadano en el coche. o a Los ciudadanos para poder montarse en el coche tendr n que colocar obst culos con el n a a de que el coche se pare. Para conseguir obst culos, los ciudadanos tienen que acudir a los puestos de la ciudad. En a cada uno de los M puestos, habr un empleado que se encargar de facilitar el material (s lo a a o atender a un ciudadano a la vez). a Cuando el material de un puesto se termina, el puesto se cierra, por lo que los ciudadanos tendr n que acudir a los otros puestos para conseguir material. a En el momento en el que todos los puestos se queden sin material ya no podr participar a ning n ciudadano m s. u a El conductor tendr que intentar esquivar ese obst culo. Si lo consigue el ciudadano que a a coloc el obst culo ser eliminado, y el obst culo se retirar . Si no lo consigue esquivar, en o a a a a ese momento se cambia de conductor quedando eliminado el conductor anterior. Cuando el coche para por un obst culo y se cambia de conductor, el obst culo es eliminado a a para siempre. Puesto que los ciudadanos se van eliminando, y junto con ellos sus obst culos, el que cona siga eliminar a todos los ciudadanos, ser el ganador del fant stico Audi A3. a a

285

Programaci n Concurrente o

5.2
5.2.1

Resoluci n por citas en Ada o


Explicaci n o

Para la implementaci n en citas, tendremos tres tareas: Ciudadano, Puesto, Coche o Algunas de las cosas que tenemos que tener en cuenta son: En Puesto, debemos controlar el n mero de objetos que puede dar. u El ultimo ciudadano que est montado en el coche, ser el ganador, y debe salir para terminar a a la ejecuci n del programa. o El ciudadano, debe ir puesto a puesto hasta encontrar un obstaculo, o si no hay ninguno marcharse. Una vez puesto el obstaculo, comprobar a ver si consigue parar el coche o no. Si consigue pararlo, debe sacar al conductor, entrar en el y esperar hasta que le saquen o que el concurso se termine. Una de las dicultades de este ejercicio es, saber c mo hacer que terminen las tareas, ya que o el ultimo ciudadano que se monta en el coche y esquiva todos los obstaculos, o ya no se va a encontrar m s obstaculos, se quedar esperando dentro del coche hasta que alguien lo saque y a a entonces compruebe que ha sido el ganador. Algunas posibilodades son: Controlar en el punto de entrada Espera SalirCoche (tarea coche) que el n mero de u objetos encontrados sea igual que el n mero m ximo de objetos que se va a encontrar. u a Cada ciudadano llama a la tarea coche al terminar, as la tarea coche podr saber cuando han a terminado todos los ciudadanos que participan. Los puntos de entrada que tenemos en este ejercicio son: Ciudadano Inicializar Puesto Inicializar DarObstaculo: el puesto asigna un obstaculo (si tiene) al ciudadano que lo pida. Coche EntrarCoche: un ciudadano entra en el coche. SacarCoche: se saca al conductor coche. Espera SalirCoche: el ciudadano se queda esperando hasta que alguien lo saque del coche. HayObstaculo: avisa al coche de que hay un obstaculo en el camino, e intentar a esquivarlo. 286

Ejercicio asignado - Audi A3

5.2.2

C digo fuente o

C digo fuente 5.1: Audi A3 por citas en Ada o


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

--Exposicion 1: Audi A3 --David Antonio Perez Zaba with with with with use use use use ada.text_io; ada.integer_text_io; Ada.Numerics.Float_Random ; Ada.Exceptions; Ada.Numerics.Float_Random; ada.integer_text_io; ada.text_io; Ada.Exceptions;

procedure A3 is G:Generator; Npuestos:Integer:=3; Nciudadanos:Integer:=15; Max_Obs:integer:=0; --estados de los puestos type Estados is (Abierto,Cerrado); task type Puesto is entry Init(Id:Integer); entry DarObstaculo(dado:out Boolean); end Puesto; task type Ciudadano is entry Init(Id:Integer); end Ciudadano; task Coche is entry EntrarCoche(Id:Integer); entry SacarCoche; entry Espera_SalirCoche(Gana: out Boolean); entry HayObstaculo(Esquivado:out Boolean); end Coche; Mpuestos: array (1..Npuestos) of Puesto; Mciudadanos:array (1..Nciudadanos) of Ciudadano;

task body Puesto is Nobstaculos:Integer:=3; I:Integer; Estado:Estados:=Abierto; begin accept Init(Id:Integer) do I:=Id; end Init;

287

Programaci n Concurrente o
Put_Line("Puesto: "&IntegerImage(i)&" abierto."); loop --exit when Nobstaculos=0; Select accept DarObstaculo(Dado:out Boolean)do if Nobstaculos>0 and Estado=abierto then Max_Obs:=Max_Obs+1; Nobstaculos:=Nobstaculos-1; Dado:=True; else --Put_Line("Puesto: "&IntegerImage(i)&" esta cerrado."); Estado:=Cerrado; Dado:=False; end if; end DarObstaculo; or terminate; end select; end loop; end Puesto; task body Ciudadano is I:Integer; Tengo_Obs:Boolean; Esquivado:Boolean; Ganador:Boolean; begin accept Init(Id:Integer)do I:=Id; end Init; --Recorremos los puestos en busca de algun obstaculo for Ii in 1..Npuestos loop Mpuestos(Ii).DarObstaculo(Tengo_Obs); exit when Tengo_Obs; end loop; delay Duration(2); --si tenemos obstaculo lo pone, y espera al coche if Tengo_Obs then --tarda un rato en poner el obstaculo delay Duration(2); Coche.HayObstaculo(Esquivado); Put_Line("-- Ciudadano "&IntegerImage(I)&" pone obstaculo "); if not Esquivado then Put_Line("-- Ciudadano "&IntegerImage(I)&" ha parado el A3, y se monta en el"); --hemos parado el coche Coche.SacarCoche;

52 53 54 55 56 57 58 59 60 61 62 63 64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

101 102

103 104

288

Ejercicio asignado - Audi A3


Coche.EntrarCoche(I); Coche.Espera_SalirCoche(Ganador); if Ganador then Put_Line("*********** Ciudadano "&IntegerImage(I)&" GANADOR"); else Put_Line("<< Ciudadano "&IntegerImage(I)&" eliminado, adios"); end if; else Put_Line("<< Ciudadano "&IntegerImage(I)&" esquivado, adios"); end if; else Put_Line("<< Ciudadano "&IntegerImage(I)&" no tengo obstaculo, adios"); end if; end Ciudadano;

105 106 107 108

109 110

111 112 113 114

115 116 117 118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

task body Coche is Ocupante:Integer:=0; --estado ocupacion del coche Ocupado:Boolean:=False; --numero de obstaculos encontrados Nobs:Integer:=0; Aleatorio:Float; begin loop Select accept EntrarCoche(Id:Integer) do Ocupante:=Id; Ocupado:=True; Put_Line("++ Conductor"&IntegerImage(Ocupante)); end EntrarCoche; or accept SacarCoche do Ocupado:=False; end SacarCoche; or when not ocupado or Nobs=Max_obs => accept Espera_SalirCoche(Gana: out Boolean) do if Nobs=Max_Obs then Gana:=True; else Gana:=False; end if; end Espera_SalirCoche; or accept HayObstaculo(Esquivado:out Boolean)do --incrementamos el numero de obstaculos pasados Nobs:=Nobs+1; if Ocupado then

289

Programaci n Concurrente o
--de forma aleatoria, decidimos si el obstaculo es esquivado o no Aleatorio:=Random(G); if Aleatorio <0.5 then Esquivado:=True; else Esquivado:=False; end if; else Esquivado:=False; end if; end HayObstaculo; or terminate; end select; end loop; end Coche; TentreC:Integer:=1; begin for Ii in 1..Npuestos loop Mpuestos(Ii).Init(Ii); end loop; for Ii in 1..Nciudadanos loop Mciudadanos(Ii).Init(Ii); delay Duration(TentreC); end loop;

157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

end A3;

290

Parte IV

Anexos

291

Anexo 1 - Valoraci n general de la asignatura o

Anexo 1

Valoraci n general de la asignatura o


Comentaremos, en lineas generales, las impresiones que hemos tenido de la asignatura, as como las mayores dicultades a las que nos hemos enfrentado.

1.1

Sobre la asignatura

Programaci n Concurrente es una de las asignaturas m s interesantes de la carrera, ya no s lo o a o porque la programaci n es uno de los campos que m s atraen al estudiante, sino tambi n porque o a e la interacci n entre tareas y procesos resulta imprescindible hoy en da. o Tal y como est planteada la asignatura, si un estudiante es capaz de seguirla al da, queda a asegurada una asimilaci n de los conceptos y m todos estudiados. Y es un punto a favor, puesto o e que a estas alturas del curso, s lo cabe esperar cierta duda en cuanto al aprendizaje en los alumnos o que no han asistido a clase durante el curso.

1.2

Sobre la carga de trabajo

Como estudiantes que hemos asisitido a clase y llevado todos los ejercicios y pr cticas al da, a podemos asegurar que la carga de trabajo es algo excesiva, ya no s lo desde nuestro punto de o vista, sino que se trata de una opini n compartida por el resto de compa eros de clase. o n Al respecto, quiz se podra suprimir la entrega de los ejercicios asignados, puesto que con las a pr cticas y los ejercicios inventados podra ser m s que suciente. a a

1.3

Conclusiones

Esta asignatura exige mucho, pero eso no tiene por qu ser malo, si llegado el da de las calicae ciones se ve reejado todo el trabajo realizado en los resultados obtenidos. Teniendo en cuenta lo anterior, incluso puede ser positivo haber tenido que realizar tantos ejercicios y pr cticas, puesto que es algo que sirve como m todo de evaluaci n de una forma a e o mucho m s able que un simple examen (o dos), en el que m s que los conocimientos adquiridos a a muchas veces se reejan los nervios y el cansancio acumulado despu s de tanto trabajo. e

293

You might also like