Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Epicor 10 Adaptive ERP WP ENS
Epicor 10 Adaptive ERP WP ENS
CONCURRENTE EN LENGUAJES
FUNCIONALES:
CONCURRENT HASKELL
4
1.2 Concurrencia y lenguajes
funcionales
Debido a la propiedad de confluencia
(podemos encontrar dos secuencias de
evaluación diferentes que parten del mismo
dato de entrada), los lenguajes funcionales
pueden utilizar directamente el paralelismo
implícito. Otra opción es añadir al lenguaje
ciertas extensiones para especificar la
concurrencia, como es el caso que vamos a
estudiar.
5
2. CONCURRENT HASKELL
Concurrent Haskell es una extensión del
lenguaje funcional perezoso Haskell para
ofrecer la posibilidad de realizar programas
concurrentes. Concurrent Haskell representa
un nuevo paso que apunta a construir un
puente entre el mundo de los lenguajes
funcionales puros y los lenguajes intensivos
de entrada y salida.
6
Algo más que una extensión
de haskell :
Consigue integrar la concurrencia en un lenguaje perezoso. Por
ejemplo los procesos pueden comunicarse como estructuras de
datos sin evaluar unos a otros.
Presenta una semántica para Haskell claramente diferenciada
en una capa determinista y una capa concurrente. Las técnicas
de razonamiento existentes son mantenidas sin modificaciones,
por ejemplo, las transformaciones de programas que preservan
la corrección en un programa Haskell secuencial también la
preservarán en un lenguaje Haskell concurrente.
Hay pocas operaciones primitivas nuevas, que son expresivas y
fáciles de implementar.
7
nuevos ingredientes a haskell:
Procesos, y un mecanismo para gestionarlos.
Estados atómicos mutables, para soportar
comunicación y cooperación entre los
procesos.
8
2.1 Procesos
Concurrent Haskell proporciona la nueva primitiva
forkIO que inicia un proceso concurrente:
forkIO :: IO () -> IO ()
forkIO a , es una acción que toma a otra acción , a,
como su argumento y crea un proceso concurrente
que ejecuta dicha acción. La entrada y salida y
otros efectos laterales realizados por a, son
interpolados de una manera indefinida con aquellos
que siguen el forkIO.
9
Ejemplo1:
import Control.Concurrent
main = forkIO (escribir 'a') >> escribir 'b'
where escribir c = putChar c >> escribir c
10
características de forkIO :
Como la implementación de haskell usa evaluación perezosa,
forkIO necesitará sincronización entre procesos, ya que un
proceso puede intentar evaluar un razonamiento que ya está
siendo evaluado por otro proceso, en cuyo caso el primero debe
ser bloqueado hasta que el último complete la evaluación y
sobrescriba el razonamiento con su valor.
Como tanto el proceso padre como el hijo, pueden cambiar el
mismo estado compartido forkIO introduce inmediatamente el no
determinismo. El problema es que casi todas las aplicaciones
concurrentes interesantes implican el uso del mismo estado
compartido por varios procesos. Por tanto, la solución correcta
será proveer mecanismos que permitan la gestión segura de un
estado compartido.
forkIO es asimétrico. Cuando un proceso ejecuta un forkIO crea
un proceso hijo que se ejecuta concurrentemente al padre.
11
2.2 Sincronización y
comunicación
Los procesos pueden necesitar acceso
exclusivo a algunos objetos como por
ejemplo ficheros. La manera de implementar
este acceso exclusivo requiere una variable
compartida mutable o un semáforo.
Para que un proceso pueda leer una cadena
de valores producida por varios procesos es
proporcionando una operación no
determinista de ordenación.
12
Type MVar a
Un valor del tipo MVar t, para algún tipo t, es el nombre de una
posición de memoria que pueda estar vacía o contener un valor
de tipo t. A su vez sobre MVar se pueden realizar las siguientes
operaciones:
newMVar :: IO (MVar a) Crea una nueva MVar
takeMVar :: MVar a -> IO a Bloquea hasta que la posición sea
no vacía. Entonces lee y devuelve el valor dejando la posición
vacía.
putMVar :: MVar a -> a -> IO () Escribe un valor en la posición
especificada. Si existen uno o mas procesos bloqueados en
takeMVar sobre dicha variable, se selecciona uno para que lo
procese. Puede producir error utilizarlo sobre una variable que
ya contenga un valor.
13
MVar
El tipo MVar puede ser usado de tres maneras
diferentes:
Puede ser usado como una versión sncronizada del
tipo MutVar.
Puede ser empleado como un tipo de canal, donde
takeMVar y PutMVar funcionan como recibir y
enviar.
El MVar puede ser usado como un semáforo
binario, donde los signal y los waits son
implementados con putMVar y takeMVar
respectivamente.
14
2.3 Semáforos
Aunque se puede implementar con un MVar usando
las operaciones putMVar y takeMVar, los semáforos
tambien están implementados en Concurrent
Haskell.
Semáforo binario:
data QSem
newQSem :: Int -> IO QSem
waitQSem :: QSem -> IO ()
signalQSem :: QSem -> IO ()
15
2.3 Semáforos
Semáforos de cantidad general:
data QSemN
newQSemN :: Int -> IO QSemN
waitQSemN :: QSemN -> Int -> IO ()
signalQSemN :: QSemN -> Int -> IO ()
16
2.4 Otras operaciones
concurrentes
18
Productor consumidor
type CVar a = (MVar a, -- Productor-> consumidor
MVar ()) -- Consumidor -> productor
newCVar :: IO (CVar a)
newCVar = newMVar >>= \ data_var ->
newMVar >>= \ ack_var ->
putMVar ack_var () >> return (data_var, ack_var)
21
Canales
22
El canal está implementado por un par de MVar’s
que apuntan al último elemento leído (read end) y al
último elemento escrito (write end) del canal
respectivamente.
Las Mvar del canal proporcionan un mecanismo
mediante el cual las operaciones de put y get
pueden modificar el read end y el write end del
canal.
Los datos en el buffer son almacenados en un
Stream que es un MVar que puede estar vacío (en
cuyo caso no hay datos en el stream) o almacena
un Item.
23
type Stream a = MVar (Item a)
Un Item es simplemente un par de elementos, uno
con el dato y otro apundanto al resto del stream.
data Item a = MkItem a (Stream a)
Un Stream puede ser considerado como una lista
que consiste en alternar Items y Mvars que termina
con un “agujero” que consiste en un MVar vacío. El
Write end del canal apunta a dicho “agujero”(Hole).
24
newChan = do { read <- newEmptyMVar ;
write <- newEmptyMVar ;
hole <- newEmptyMVar ;
putMVar read hole ;
putMVar write hole ;
return (read,write) }
25
putChan (read,write) val
= do { new_hole <- newEmptyMVar ;
old_hole <- takeMVar write ;
putMVar write new_hole ;
putMVar old_hole (MkItem val new_hole) }
26
getChan (read,write)
= do { head_var <- takeMVar read ;
MkItem val new_head <- takeMVar head_var ;
putMVar read new_head ;
return val }
27
canal multicast
dupChan (read,write)
= do { new_read <- newEmptyMVar ;
hole <- readMVar write ;
putMVar new_read hole ;
return (new_read, write) }
28
Implementación de canales en
Concurrent Haskell
data Chan a
newChan :: IO (Chan a) -- Nuevo canal
writeChan :: Chan a -> a -> IO () --Escribe dato en canal
readChan :: Chan a -> IO a --Lee un dato del canal
dupChan :: Chan a -> IO (Chan a) --Duplica el canal
unGetChan :: Chan a -> a -> IO () --Devuelve un dato al canal
isEmptyChan :: Chan a -> IO Bool --Comprueba si está vacío
getChanContents :: Chan a -> IO [a] -- lee todo el contenido
writeList2Chan :: Chan a -> [a] -> IO () -- Escribe el contenido
de una lista en el canal
29
3. CONCLUSIONES
Hemos comprobado como Concurrent Haskell
aporta nueva funcionalidad a Haskell.
Añadiendo forkIO y MVars a Haskell damos un salto
cualitativo en cuanto a la cantidad de aplicaciones
que podemos escribir. Las extensiones son sencillas
y simples de describir.
En la actualidad Haskell y sus versiones
concurrentes están siendo empleados de manera
comercial como herramienta de programación para
servidores, aportando una nueva manera de
programar potente y elegante.
30
4. REFERENCIAS
http://www.haskell.org
Ruíz, B.C.; Gutiérrez, F.; Guerrero, P.; Gallardo, J.E.: Razonando con
Haskell. Una introducción a la Programación Funcional. Servicio
reprogr. (OCÉ) E.T.S.I.I., Universidad de Málaga. 2000
http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control.Concu
rrent.html
Tackling the Awkward Squad: monadic input/output, concurrency,
exceptions, and foreign-language calls in Haskell
Simon PEYTON JONES Microsoft Research, Cambridge
simonpj@microsoft.com
http://research.microsoft.com/users/simonpj
Concurrent Haskell
Simon Peyton Jones (University of Glasgow)
Andrew Gordon (University of Cambridge)
Sigbjorn Finne (University of Glasgow)
Notas para la asignatura Programación Declarativa Avanzada.
Blas Carlos Ruiz Jiménez
31