Programación en Ada/Tareas/Aceptación de citas
Aceptación de citas (accept)
[editar]La forma de aceptar una cita y ejecutar las sentencias que se deseen
es mediante la sentencia accept, dentro del cuerpo de la tarea que
acepta la cita. Cada sentencia entry debe corresponderse con una sentencia accept.
La sintaxis de accept es:
acceptación_cita ::=acceptidentificador [ ( expresión ) ] [ ( especificación_parámetro { ; especificación parámetro } ) ] [dosecuencia_de_sentenciasend[ identificador ] ] ;
Por ejemplo:
acceptEntrada (N: Integer)do-- ... Secuencia de sentencias.endEntrada;
Se deben repetir los parámetros formales declarados en el punto de entrada de la especificación de la tarea.
La diferencias fundamentales entre los puntos de entrada y los procedimientos son:
- El código existente dentro en la sentencia accept es ejecutado por la tarea propietaria y no por la parte invocante, como en los procedimientos.
- Además, hasta que la tarea no llegue a la ejecución de dicha sentencia
accept, no puede ser invocado el punto de entrada. De igual manera, la parte invocante queda suspendida hasta que termine la ejecución de la sentenciaaccept. Éste es el fundamento de la cita.
La forma más simple de sincronizar una tarea que dependa de la terminación de otro código es por ejemplo:
taskSimpleisentryContinuar;endSimple;taskbodySimpleisbegin-- ...acceptContinuar;-- Se queda bloqueado hasta que se cite.-- ...endSimple;
Como otro ejemplo, si se quiere implementar una tarea que realice un control de escritura y lectura sobre un buffer de un único elemento:
taskBuffer1isentryEscribir (Elem: TElemento);entryLeer (Elem:outTElemento);endBuffer1;taskbodyBuffer1isElemLocal: TElemento;beginloopacceptEscribir (Elem: TElemento)doElemLocal:= Elem;-- Guarda el elemento.endEscribir; Ada.Text_IO.Put_Line("Elemento escrito, voy a intentar LEER!");acceptLeer (Elem:outTElemento)doElem := ElemLocal;-- Devuelve el elemento.endLeer; Ada.Text_IO.Put_Line("Elemento leido, vuelvo a intentar ESCRIBIR");endloop;endBuffer1;
Se aceptan llamadas Buffer1.Escribir(…) y Buffer1.Leer(…) de forma
consecutiva, sin posibilidad de escribir o leer dos o más veces
seguidas.
Varias tareas diferentes pueden invocar a los puntos de
entrada y, por tanto, pueden quedar encoladas. Cada punto de entrada
tiene una cola de tareas que esperan llamar a dicho punto de entrada. El
atributo Escribir'Count contiene el número de tareas que se encuentran
encoladas a la espera de que se ejecute el punto de entrada Escribir,
pero sólo se puede utilizar dentro de la tarea que contiene el punto de
entrada. Con la ejecución de la sentencia accept se extraería la
primera tarea de la cola (la primera que llegó).
Por tanto, el ejemplo anterior funciona de la siguiente manera: la tarea Buffer1 llega al accept de Escribir y se queda bloqueada allí hasta que otra tarea realice una llamada Buffer1.Escribir(…). En ese momento, la tarea Buffer1 ejecuta Escribir y llega al accept de Leer, donde se queda bloqueada hasta que otra tarea realice una llamada Buffer1.Leer(…). Se ejecuta Leer y la tarea Buffer1 vuelve al accept de Escribir, y así constantemente. Evidentemente, si hay tareas encoladas en los puntos de entrada de Escribir o de Leer, la tarea Buffer1 no se queda bloqueada, sino que atiende a la primera tarea llamante de la cola.
Se puede introducir código entre dos bloques de accept, tal y como se ve en el ejemplo anterior: cuando se acaba el primer bloque accept (Escribir) se ejecuta dicho código y después se entra en la cola de espera del segundo bloque accept (Leer).
Si hay definidos varios puntos de entrada simultáneamente, se puede
aceptar uno de ellos, por ejemplo, como:
acceptAviso (3) (Elem: Telemento)do-- ...endAviso;