Programación en Ada/Tareas/Selección de citas
Selección de citas (select)
editarUno de los usos de la sentencia select es permitir a una tarea seleccionar entre varias posibles citas; en este caso, se permite su uso únicamente dentro del cuerpo de una tarea. Su sintaxis es la siguiente:
seleccción_aceptación_cita ::=select
[when
condición => ] ( acceptación_cita | (delay
[until
] expresión ) [ secuencia_de_sentencias ] ) | (terminate
; ) ) {or
[when
condición => ] ( acceptación_cita | (delay
[until
] expresión ) [ secuencia_de_sentencias ] ) | (terminate
; ) ) } [else
sequencia_sentencias ]end
select
;
Esta alternativa de sentencia select
permite una combinación de espera y
selección entre varias aceptaciones de puntos de entrada a la tarea
alternativas. Además, la selección puede depender de condiciones
asociadas a cada alternativa.
La sentencia delay
sirve para indicar que, si en un determinado
intervalo de tiempo no se produce ninguna llamada que corresponda con las
selecciones anteriores, se ejecuten las sentencias posteriores.
La sentencia terminate
se elige en la sentencia select
si la unidad de
la que la tarea depende ha llegado al final y todas las tareas hermanas
y dependientes han terminado. Es una terminación controlada. Esta
alternativa no puede aparecer si hay una alternativa delay
o else
.
Por ejemplo:
task
Servidoris
entry
Trabajar;entry
Cerrar;end
;task
body
Servidoris
begin
loop
select
accept
Trabajardo
-- Se acepta la llamada a trabajar.
Trabajando := True;-- Variable global.
end
; Trabajo_servidor;-- Trabaja.
or
accept
Cerrar;-- Se cierra el servidor.
exit
;or
delay
(60.0);-- ¿Se han olvidado del servidor?
Put ("Estoy esperando trabajar.");-- Otra opción en vez de delay:
-- or
-- --Terminación normal cuando se destruya el objeto tarea.
-- terminate;
end
select
;end
loop
;end
Servidor;
Como otro ejemplo, para garantizar la exclusión mutua a una variable (acceso seguro a memoria compartida), se podría implementar con tareas de la siguiente manera:
task
Variable_protegidais
entry
Leer (Elem:out
TElemento);entry
Escribir (Elem: TElemento);end
;task
body
Variable_protegidais
ElemLocal: TElemento;begin
accept
Escribir (Elem: TElemento)do
ElemLocal := Elem;end
Escribir;loop
select
accept
Escribir (Elem: TElemento)do
ElemLocal := Elem;end
Escribir;or
accept
Leer (Elem:out
TElemento)do
Elem := ElemLocal;end
Leer;end
select
;end
loop
;end
Variable_protegida;
La primera sentencia de la tarea es un accept
de Escribir, con lo que se asegura que la primera llamada le de un
valor a la variable local. En el supuesto de que se realizara una llamada a Leer, ésta quedaría encolada
hasta que se produjera la aceptación de Escribir. Después, la tarea
entra en el bucle infinito que contiene una sentencia select
. Es ahí
donde se acepta tanto llamadas a Escribir como a Leer de la siguiente
manera:
Si no se llama ni a Leer ni a Escribir, entonces la tarea se queda
suspendida hasta que se llame a algún punto de entrada, en ese momento
se ejecutará la sentencia accept
correspondiente.
Si hay una o más llamadas en la cola de Leer, pero no hay llamadas en la de Escribir, se acepta la primera llamada a Leer, y viceversa.
Si hay llamadas tanto en la cola de Leer como en la de Escribir, se hace una elección arbitraria.
Es una tarea que sirve a dos colas de clientes que esperan servicios diferentes. Sin embargo, se impide el acceso múltiple a la variable local.