Programacion_Concurrente - Memoria 09-10

download Programacion_Concurrente - Memoria 09-10

of 293

Transcript of Programacion_Concurrente - Memoria 09-10

Programaci n Concurrente o Curso 2009-2010

Documentaci n completa o de Pr cticas y Ejercicios aSergio 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

2

Indice generalI1

Pr cticas aEl 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

911 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3

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

4

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

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

5

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

6

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

II1

Ejercicios inventadosJulimocho 1.1 1.2

211213

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

2

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

3

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

4

Party 4.1

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

6

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

5

Florentino P rez e 5.1

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

6

I.O. 6.1

III1

Ejercicios asignadosTurismo de Almorox 1.1 1.2

251253

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

2

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

3

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

4

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

IV1

AnexosValoraci n general de la asignatura o 1.1 1.2 1.3

291293

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

8

Parte I

Pr cticas a

9

Pr ctica 1 - El puente de Puente Duero a

Pr ctica 1 a

El puente de Puente Duero1.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.21.2.1

Resoluci n por monitores en Ada oExplicaci 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 oC 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 aprocedure 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 oprocedure 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 aput_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 oMonitor.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.31.3.1

Resoluci n por monitores en Java oExplicaci 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 oC 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 oocupacion = 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 aturno = 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 otry { 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 aSystem.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.41.4.1

Resoluci n por sem foros en Ada o aExplicaci 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 oC 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(" 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 aT_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.61.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 oC 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 aocupacion: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 aespera = 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.71.7.1

AnexoTiempo 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 karts2.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.22.2.1

Resoluci n por citas en Ada oSin 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) o1 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 oif 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 aEsperando: 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(" >"); 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 awhen (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 o1 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 aPuedo: 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 oPuedo := 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(" >"); 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 aSeguidos := 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 o1 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 aCircuito.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(" >"); 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 aPut_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 obegin 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.32.3.1

Resoluci n por Monitores en Java oSin 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 o1 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 oprivate 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 apublic synchronized void competir_adulto(int id){ try{ while(turno == NINIOS || capacidad_pista >= CAPACIDAD_CIRCUITO || carreras_seguidas_adulto >= MAX_SEGUIDAS ) { System.out.println("Adulto