En este sistema hay una serie de puntos clave que condicionan la estructura de procesos adoptada:
Estos requisitos obligan a separar en tareas diferentes el encolado de órdenes ---proceso Buffer---, la visualización ---proceso Visual---, y la edición propiamente dicha ---Ejecutor. La estructura de procesos, con un cuarto proceso que lee de teclado y produce las órdenes, se muestra en la figura.
Además, hay una serie de restricciones a la sincronización entre estos procesos:
Finalmente se ha llegado al esquema de canales de la figura, con el código simplificado de la otra página.
El proceso Teclado simplemente forma comandos a partir de la lectura del teclado y los envía a Buffer. Por otra parte, Buffer recibe peticiones de Ejecutor por Peticion y contesta con el primer comando de la cola o bien avisa que no hay comandos. Además, cuando llega el primer comando a la cola vacía, lo envía a Ejecutor sin esperar una petición previa. (Esto es una forma de evitar un bucle de espera activa.) El funcionamiento de Visual es pedir por PetVisu la parte visible del documento a Ejecutor. Para corresponder a ambos, ejecutor queda a la espera de un mensaje por PetVisu o por Trabajo después de quedarse vacío la cola de órdenes. Así se satisface el último requisito.
Naturalmente, no es la única solución posible.
A continuación se especifica el código CC-MODULA de las tareas.
TASK Buffer; VAR Cola: TIPOCOLA; Comando: TIPOCOMANDO; Pet, EsperaOrden: BOOLEAN; BEGIN GetChannel(Comandos); GetChannel(Peticion); <<inicializar buffer>> esperaOrden:=TRUE; (* Empieza una racha de comandos *) LOOP SELECT WHEN esperaOrden, Receive(Comandos,Comando) DO esperaOrden:=FALSE; Send(Trabajo,Comando); WHEN NOT(esperaOrden) AND NOT(Llena(Cola)), Receive(Comandos,Comando) DO Encolar(Comando,Cola); WHEN Vacia(Cola), Receive(Peticion,Pet) DO esperaOrden:=TRUE; Send(Fin,TRUE); WHEN NOT(Vacia(Cola)), Receive(Peticion,Pet) DO Send(Trabajo,Primero(Cola)); QuitaPrimero(Cola) END END END Buffer;
TASK Ejecutor; VAR Documento, Pantalla: TIPODOC; Comando: TIPOCOMANDO; FinComandos: BOOLEAN; BEGIN GetChannel(Trabajo); GetChannel(Fin); GetChannel(PetVisu); <<inicializar Documento, etc>> Receive(Trabajo,Comando); Ejecutar(Comando,Documento); FinComandos:=FALSE; DatosNuevos:=FALSE; LOOP SELECT WHEN Receive(Fin,FinComandos) DO WHEN Receive(Trabajo,Comando) DO Ejecutar(Comando); FinComandos:=FALSE; DatosNuevos:=TRUE; Send(Peticion,TRUE) WHEN FinComandos AND DatosNuevos, Receive(PetVisu,Pet) DO ExtraePant(Documento,Pant); DatosNuevos:=FALSE; Send(Pantalla,Pant) END END END Ejecutor;
TASK Visual; VAR Pant: TIPODOC; BEGIN GetChannel(Pantalla); LOOP Send(PetVisu,TRUE); Receive(Pantalla,Pant); Mostrar(Pant) END END Visual;
TASK Teclado; VAR Pulsaciones: TIPOTECLADO; Comando: TIPOCOMANDO; BEGIN LOOP LeerTeclado(Pulsaciones); Comando:=ConstruirComando(Pulsaciones); Send(Comandos,Comando) END END Teclado;