Universidad Politécnica de Madrid Escuela Universitaria de Informática Departamento de Lenguajes, Proyectos y Sistemas Informáticos Asignatura PROGRAMACIÓN II Plan: 92 / Curso: 98-99 Madrid, a 28 de Junio de 1.999 CUESTIONES DE TEORÍA Junio - 99 Valoración máxima: 3 puntos Respuesta correcta: + 0.2 puntos Respuesta incorrecta o no contestada: - 0.15 puntos I. PROGRAMACIÓN CONCURRENTE 1. ¿Qué es la inanición de procesos? Aquella situación en la que un proceso intenta acceder a un recurso compartido compitiendo con otros procesos y no lo logra nunca, mientras otros lo consiguen repetidamente 2. ¿Cómo se resuelve el acceso exclusivo de un conjunto de procesos a una variable compartida mediante semáforos? ¿Y con monitores? Con semáforos se asocia un semáforo a esa variable, y se inicializa con valor 1. Cuando un proceso debe acceder a la variable, primero ejecuta una operación WAIT sobre el semáforo para obtener el acceso exclusivo sobre ella; después consulta y/o modifica su valor; y finalmente ejecuta una operación SIGNAL sobre el semáforo para liberarla. Con monitores se incluye la variable en el interior de un monitor y, para consultar y/o modificar su valor, los procesos invocan un procedimiento de ese monitor. 3. ¿Qué sucede en PASCAL-FC con la exclusión mutua sobre dos monitores A y B cuando un proceso, desde el monitor A, invoca a un procedimiento del monitor B y ejecuta una operación DELAY en ese procedimiento? Retiene la exclusión mutua sobre el monitor A y libera la de B. Página 1 de 9 Programación II – Solución de examen Junio 99 4. ¿Puede haber interbloqueo en el siguiente programa concurrente si N = 2? ¿Y si N > 2? Razone las respuestas. PROGRAM Programa; CONST N = ... TYPE TAcceso = RECORD Primero : BOOLEAN; Exclusion : SEMAPHORE END; PROCESS TYPE TProceso (VAR Acceso : TAcceso; VAR Exclusion, Sincronizacion : SEMAPHORE); BEGIN REPEAT WAIT(Acceso.Exclusion); IF Acceso.Primero THEN BEGIN Acceso.Primero := FALSE; SIGNAL(Acceso.Exclusion); WAIT(Exclusion); WAIT(Sincronizacion); SIGNAL(Exclusion) END ELSE BEGIN Acceso.Primero := TRUE; SIGNAL(Sincronizacion); SIGNAL(Acceso.Exclusion) END FOREVER END; VAR Acceso : TAcceso; Exclusion, Sincronizacion : SEMAPHORE; aProceso : ARRAY [1..N] OF TProceso; i : INTEGER; BEGIN Acceso.Primero := TRUE; INITIAL(Acceso.Exclusion, 1); INITIAL(Exclusion, 1); INITIAL(Sincronizacion, 0); COBEGIN FOR i := 1 TO N DO aProceso[i](Acceso, Exclusion, Sincronizacion) COEND END. Si N >= 2, no puede haber interbloqueo. Los procesos acceden bajo exclusión mutua y ausencia de interbloqueo a la variable Acceso, y ejecutan alternativamente una rama distinta de la sentencia IF-THEN-ELSE. Los procesos que acceden en posición impar (el primero, el tercero, …) ejecutan la rama THEN, los que lo hacen en posición par, ejecutan la ELSE.. Los procesos que ejecutan la rama THEN acceden bajo exclusión mutua a la región crítica protegida por el semáforo Exclusion, y uno podría bloquearse en su interior al ejecutar WAIT(Sincronizacion), pero sólo hasta que el siguiente proceso que curse la rama ELSE ejecute SIGNAL(Sincronizacion), lo cual ocurrirá eventualmente. Página 2 de 9 Programación II – Solución de examen Junio 99 5. Escriba en PASCAL-FC un monitor llamado SemaforoFIFO, que exporte los procedimientos Initial, Wait y Signal, según la semántica de estas operaciones aplicadas sobre un semáforo con política FIFO. MONITOR SemaforoFIFO; EXPORT Initial, Wait, Signal; VAR Contador : INTEGER; Cola : CONDITION; PROCEDURE Initial (Valor : INTEGER); BEGIN Contador := Valor END; PROCEDURE Wait; BEGIN IF Contador > 0 THEN Contador := Contador - 1 ELSE DELAY(Cola) END; PROCEDURE Signal; BEGIN IF NOT EMPTY(Cola) THEN RESUME(Cola) ELSE Contador := Contador + 1 END; END; II. PROGRAMACIÓN ORIENTADA A OBJETOS 1. ¿Pueden sobrecargarse los constructores? ¿Y los destructores? Razone las respuestas. Los constructores sí, porque al crear los objetos se puede determinar el constructor a emplear especificando distinto número o tipos de parámetros. Los destructores no, porque no se invocan explícitamente y, por tanto, no tienen parámetros. 2. ¿Puede haber ciclos en una jerarquía de herencia entre clases? ¿Y en una jerarquía de uso? Razone las respuestas. En una jerarquía de herencia no puede haber ciclos pues significaría que dos clases, en realidad, son la misma clase. En una jerarquía de uso si puede haber ciclos, pues los objetos de dos clases distintas pueden usarse mutuamente entre sí. Página 3 de 9 Programación II – Solución de examen Junio 99 3. ¿Qué es una clase abstracta? ¿Para qué se usa? Una clase abstracta es aquélla que tiene al menos un método diferido. Se usa para modelar conceptos e ideas que pueden ayudar a construir jerarquías de clasificación. 4. ¿Cuáles son los beneficios del polimorfismo? Aumenta el nivel de abstracción, pues permite tratar uniformemente objetos de diversas clases sin preocuparse de qué clase son. Aumenta el grado de extensibilidad, pues no es necesario modificar ese tratamiento al añadir una nueva posible clase. 5. Considere las siguientes vistas públicas de las clases cA y cB: CLASS INTERFACE cA; PUBLIC METHODS PROCEDURE P; END CLASS INTERFACE cA; CLASS INTERFACE cB; INHERITS FROM cA; PUBLIC METHODS REDEFINED PROCEDURE P; PROCEDURE Q; END CLASS INTERFACE cB; Suponga además la siguiente implantación de un cierto método de otra clase cC: PROCEDURE R; LOCALS pA : ^cA; b : BOOLEAN; BEGIN b := ... (* Irrelevante *) IF b THEN NEW(pA, cA) ELSE NEW(pA, cB); pA^.Q; DISPOSE(pA) END; Indique y razone todos los errores que encuentre, tanto en la declaración de las vistas públicas de cA y cB como en la implantación del método R de la clase cC. El puntero pA debe declarase polimórfico, pues puede albergar direcciones de objetos de las clases cA y cB. No se debe invocar al método Q, pues no está definido en la clase cA. Página 4 de 9 Programación II – Solución de examen Junio 99 III. PROGRAMACIÓN FUNCIONAL 1. ¿Qúe se entiende por polimorfismo en la Programación Funcional? Que una función puede recibir y devolver valores de datos de distintos tipos. 2. ¿Cuáles son las desventajas de la Programación Funcional? La supuesta ineficiencia de su ejecución en las arquitecturas tradicionales, y la mayor dificultad de los algoritmos recursivos. 1. Ponga algún valor de datos que se corresponda con el siguiente tipo de CAML: No especifique listas vacías. float * (bool list * char list) list * 'a list ( 1.7 , [ ( [ true ; false ] , [ `a` ; `b` ] ) ; ( [ true ] , [ `c` ] ) ] , [ 1 ; 2 ] ) 4. ¿Para qué valores de x ocurre un error al evaluar la siguiente expresión en CAML? Razone la respuesta. if x = 0 then true or 1/x > 0 else true & 1/x > 0 Para ninguno. Si x = 0, devuelve true pues el operador or disfruta de evaluación perezosa y no es necesario evaluar 1/x. Si x <> 0, aunque el operador & también tiene evaluación perezosa, sí es necesario evaluar 1/x, pero en este caso no ocurre ningún error. 5. Escriba en la notación CAML el tipo del operador :: ¿Cuál es su asociatividad? Su tipo es ‘a * ‘a list -> ‘a list. Se asocia de derecha a izquierda. Página 5 de 9 Programación II – Solución de examen Junio 99 PROBLEMAS Junio - 99 I. PROGRAMACIÓN ORIENTADA A OBJETOS (2.5 puntos) Se desea automatizar un centro de documentación mediante Programación Orientada a Objetos. Este centro debe gestionar dos clases de documentos: documentos simples y documentos compuestos. Los documentos simples están formados por un máximo de 100 elementos de diversas clases concretas (textos, dibujos, vídeos, ...), todas ellas ya implantadas y derivadas de la clase cElemento, cuya vista pública es la siguiente: CLASS INTERFACE cElemento; PUBLIC METHODS DEFERRED FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; ... END CLASS INTERFACE cElemento; Los documentos compuestos están formados por un máximo de 25 documentos, que pueden ser indistintamente documentos simples, o a su vez documentos compuestos. Se pide: Escribir las vistas pública y privada de la clase cDocumento y de sus clases derivadas para poder seleccionar de cada cada documento, ya sea simple o compuesto, la información relativa a cualquier tema que se solicite. El funcionamiento del proceso de selección debe ser el siguiente: - Si se trata de un documento simple, se busca entre sus elementos aquéllos que son relativos al tema pedido. - Si no se encuentra ninguno se devolverá NIL. - Si se encuentra al menos uno, se crea una copia del documento original, pero que sólo contenga las direcciones de tales elementos, y se devolverá la dirección de esa copia. - Si se trata de un documento compuesto, se busca entre sus documentos aquéllos que son relativos al tema pedido. - Si no se encuentra ninguno se devolverá NIL. - Si se encuentra sólo uno, se devolverá la dirección del documento obtenido al seleccionar su información relativa a ese tema. - Si se encuentra más de uno, se crea una copia del documento original, pero que sólo contenga las direcciones de los documentos obtenidos al seleccionar su información relativa a ese tema, y se devolverá la dirección de esa copia. Página 6 de 9 Programación II – Solución de examen Junio 99 CLASS INTERFACE cDocumento; PUBLIC METHODS DEFERRED FUNCTION pSeleccion (sTema : STRING) : POLYMORPHIC ^cDocumento; DEFERRED FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; END CLASS INTERFACE cDocumento; (* ****************************************************************** *) CLASS INTERFACE cDocumentoSimple; INHERITS FROM cDocumento; PUBLIC METHODS REDEFINED FUNCTION pSeleccion (sTema : STRING) : POLYMORPHIC ^cDocumento; REDEFINED FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; END CLASS INTERFACE cDocumentoSimple; (* ------------------------------------------------------------------ *) CLASS IMPLEMENTATION cDocumentoSimple; ATTRIBUTES mapElemento : ARRAY [1..100] OF POLYMORPHIC ^cElemento; miNumElementos : INTEGER(0); PRIVATE METHODS PROCEDURE AnhadirElemento (pElemento : POLYMORPHIC ^cElemento); METHODS DEFINITION FUNCTION pSeleccion (sTema : STRING) : POLYMORPHIC ^cDocumento; LOCALS i : INTEGER; pDocumentoSimple : ^cDocumentoSimple; BEGIN IF SELF.bEsRelativoAlTema(sTema) THEN BEGIN NEW(pDocumentoSimple, cDocumentoSimple); FOR i := 1 TO miNumElementos DO IF mapElemento[i]^.bEsRelativoAlTema(sTema) THEN pDocumentoSimple^.AnhadirElemento(mapElemento[i]); pSeleccion := pDocumentoSimple END ELSE pSeleccion := NIL END; FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; LOCALS i : INTEGER; BEGIN i := 1; WHILE (i < miNumElementos) AND NOT mapElemento[i]^.bEsRelativoAlTema(sTema) DO i := i + 1; bEsRelativoAlTema := mapElemento[i]^.bEsRelativoAlTema(sTema) END; PROCEDURE AnhadirElemento (pElemento : POLYMORPHIC ^cElemento); BEGIN miNumElementos := miNumElementos + 1; mapElemento[miNumElementos] := pElemento END; END CLASS IMPLEMENTATION cDocumentoSimple; Página 7 de 9 Programación II – Solución de examen Junio 99 CLASS INTERFACE cDocumentoCompuesto; PUBLIC METHODS REDEFINED FUNCTION pSeleccion (sTema : STRING) : POLYMORPHIC ^cDocumento; REDEFINED FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; END CLASS INTERFACE cDocumentoCompuesto; (* ------------------------------------------------------------------- *) CLASS IMPLEMENTATION cDocumentoCompuesto; INHERITS FROM cDocumento; ATTRIBUTES mapDocumento : ARRAY [1..25] OF POLYMORPHIC ^cDocumento; miNumDocumentos : INTEGER(0); PRIVATE METHODS FUNCTION iCuantosRelativos (sTema : STRING) : INTEGER; PROCEDURE AnhadirDocumento (pDocumento : POLYMORPHIC ^cDocumento); METHODS DEFINITION FUNCTION pSeleccion (sTema : STRING) : POLYMORPHIC ^cDocumento; LOCALS i, iCuantos : INTEGER; pDocumentoCompuesto : ^cDocumentoCompuesto; BEGIN iCuantos := SELF.iCuantosRelativos(Tema); IF iCuantos = 0 THEN pSeleccion := NIL ELSE IF iCuantos = 1 THEN BEGIN i := 1; WHILE (i < miNumDocumentos) AND NOT mapDocumento[i]^.bEsRelativoAlTema(sTema) DO i := i + 1; pSeleccion := mapDocumento[i]^.pSeleccion(sTema) END ELSE BEGIN NEW(pDocumentoCompuesto, cDocumentoCompuesto); FOR i := 1 TO miNumDocumentos DO IF mapDocumento[i]^.bEsRelativoAlTema(sTema) THEN pDocumentoCompuesto^.AnhadirDocumento( mapDocumento[i]^.pSeleccion(sTema)); pSeleccion := pDocumentoCompuesto END END; FUNCTION bEsRelativoAlTema (sTema : STRING) : BOOLEAN; LOCALS i : INTEGER; BEGIN i := 1; WHILE (i < miNumDocumentos) AND NOT mapDocumento[i]^.bEsRelativoAlTema(sTema) DO i := i + 1; bEsRelativoAlTema := mapDocumento[i]^.bEsRelativoAlTema(sTema) END; Página 8 de 9 Programación II – Solución de examen Junio 99 FUNCTION iCuantosRelativos (sTema : STRING) : INTEGER; LOCALS i, iCuantos : INTEGER; BEGIN iCuantos := 0; FOR i := 1 TO miNumDocumentos DO IF mapDocumento[i]^.bEsRelativoAlTema(sTema) THEN iCuantos := iCuantos + 1; iCuantosRelativos := iCuantos END; PROCEDURE AnhadirDocumento (pDocumento : POLYMORPHIC ^cDocumento); BEGIN miNumDocumentos := miNumDocumentos + 1; mapDocumento[miNumDocumentos] := pDocumento END; END CLASS IMPLEMENTATION cDocumentoCompuesto; II. PROGRAMACIÓN FUNCIONAL (2.5 puntos) Dada una lista de elementos de cualquier tipo, cuyos valores no están repetidos, se pide escribir en CAML las funciones necesarias para obtener todas las posibles parejas de elementos distintas que se pueden obtener con los elementos de la lista original. Las parejas formadas por los mismos elementos, pero en orden inverso, por ejemplo (A, B) y (B, A), sólo debe aparecer una vez en el resultado, incluyendo a la pareja formada por un elemento consigo mismo. Ejemplos) Parejas -: (int [ (1 (2 (3 (4 [ * , , , , 1 ; 2 ; 3 ; 4 ] ;; int) list = 1) ; (1 , 2) ; (1 , 3) ; (1, 4) ; 2) ; (2 , 3) ; (2, 4) ; 3) ; (3, 4) ; 4) ] Parejas [ [ ] -: (char list [ ([ ] , [ ([ `a` ; ([ `c` ] ; [ `a` ; `b` ] ; [ `c` ] ] ;; * char list) list = ]) ; ([ ] , [ `a` ; `b` ]) ; ([ ] , [ `c` ]) ; `b` ] , [ `a` ; `b` ]) ; ([ `a` ; `b` ] , [ `c` ]) ; , [ `c` ]) ] let rec Concatenar = function [ ] , L -> L | cab :: cola , L -> cab :: Concatenar(cola, L);; let rec PrimeroConResto = function x , [ ] -> [ ] | x , cab :: cola -> (x, cab) :: PrimeroConResto(x, cola);; let rec Parejas = function [ ] -> [ ] | cab :: cola -> Concatenar((cab, cab) :: PrimeroConResto(cab, cola), Parejas(cola));; Página 9 de 9