Concurrent Pascal es un lenguaje de programación diseñado por Per Brinch Hansen para escribir programas de computación concurrente como sistemas operativos y sistemas de monitoreo de computación en tiempo real en computadoras con memoria compartida . [1]
Se utiliza un lenguaje independiente, Sequential Pascal , como lenguaje para los programas de aplicaciones ejecutados por los sistemas operativos escritos en Concurrent Pascal. Ambos lenguajes son extensiones de Pascal de Niklaus Wirth y comparten un intérprete de código enhebrado común . [2] A continuación se describe en qué se diferencia Concurrent Pascal de Wirth.
Descripción del idioma
Se eliminaron varias construcciones en Pascal de Concurrent Pascal por simplicidad y seguridad: [2]
- Registros de variantes
- Declaración Goto y etiquetas
- Procedimientos como parámetros
- Matrices empaquetadas
- Tipos de punteros
- Tipos de archivos y procedimientos de entrada/salida estándar asociados
Estas omisiones permiten garantizar, mediante una combinación de comprobaciones en tiempo de compilación y una comprobación mínima en tiempo de ejecución en el intérprete de código enhebrado, que un programa no pueda dañarse a sí mismo ni a otro programa al direccionarse fuera de su espacio asignado.
Pascal concurrente incluye tipos de datos de clase, monitor y proceso. Las instancias de estos tipos se declaran como variables y se inicializan en una initinstrucción.
Las clases y los monitores son similares: ambos incluyen variables y procedimientos privados con procedimientos públicos (llamados entradas de procedimiento). Una instancia de clase puede ser utilizada solo por un proceso, mientras que una instancia de monitor puede ser compartida por varios procesos. Los monitores proporcionan el único mecanismo para la comunicación entre procesos en un programa Pascal concurrente.
Solo se puede ejecutar un proceso a la vez dentro de una instancia de monitor dada. La cola, un tipo de datos integrado, junto con las operaciones delayy continue, se utilizan para la programación dentro de los monitores. Cada variable de tipo cola puede contener un proceso. Si se deben retrasar muchos procesos en un monitor, se deben proporcionar múltiples variables de cola, generalmente organizadas como una matriz. La variable de cola de proceso único le da a un monitor control total sobre la programación a mediano plazo, pero el programador es responsable de desbloquear el proceso correcto.
Un proceso, como una clase o un monitor, tiene variables locales, procedimientos y una sentencia inicial, pero no tiene entradas de procedimiento. La sentencia inicial normalmente se ejecuta indefinidamente, llamando a procedimientos locales, procedimientos de clase y procedimientos de monitor. Los procesos se comunican a través de procedimientos de monitor. Las reglas del lenguaje evitan los bloqueos imponiendo una jerarquía a los monitores. Pero nada puede evitar que un monitor olvide por error desbloquear un proceso retrasado (al no llamar a continue) de modo que el sistema pueda seguir colgándose de forma efectiva debido a errores de programación.
La configuración de los procesos, monitores y clases en un programa Pascal concurrente se establece normalmente al inicio de la ejecución y no se modifica posteriormente. Las rutas de comunicación entre estos componentes se establecen mediante variables que se pasan en las initinstrucciones, ya que las variables de instancia de clase y monitor no se pueden utilizar como parámetros de procedimiento.
Ejemplo
El siguiente ejemplo muestra la declaración de un monitor simple y su uso por dos procesos que se comunican.
tipo
"Monitor de buffer delimitado"
buffer = Monitor
var
guardado : entero ; "el elemento guardado es un entero"
fullq , emptyq : cola ; "usado solo por dos procesos"
completo : booleano ; "verdadero si se guarda un elemento:"
"Pone el elemento en el búfer"
procedimiento entrada put ( elemento : Integer );
begin
si está lleno entonces
delay ( fullq ); "bloquear si está lleno"
save : = elemento ; "guardar el elemento"
full : = true ; "marcar como lleno"
continue ( emptyq ) "desbloquear consumidor"
end ;
"Obtiene el elemento del buffer"
procedimiento entrada get ( var item : Integer );
begin
si no está lleno entonces
delay ( emptyq ); "bloquea si está vacío"
item : = guardado ; "obtiene el elemento"
full : = false ; "marca como no lleno"
continue ( fullq ) "desbloquea al productor"
end ;
"Inicializar el monitor"
begin
full : = false
end ;
"El productor usa un buffer"
productor = proceso ( pass : Buffer );
var item : Integer ;
begin
ciclo "ejecutar en un bucle para siempre"
"producir un elemento"
pass . put ( item ) "pasar un elemento al monitor"
end
end ;
"El consumidor usa un buffer"
consumidor = proceso ( pasar : Buffer );
var elemento : Entero ;
comenzar
ciclo
pasar . obtener ( elemento ); "obtener un elemento del monitor"
"consumir el elemento"
fin
fin ;
"declarar instancias del monitor, productor y consumidor"
"dar al productor y consumidor acceso al monitor"
var
pass : Buffer ;
prod : Productor ;
cons : Consumidor ;
begin
init pass , "iniciar el monitor"
prod ( pass ), "iniciar el proceso del productor"
cons ( pass ) "iniciar el proceso del consumidor"
end .
