You are on page 1of 31

PROGRAMACIN CONCURRENTE EN LENGUAJES FUNCIONALES:

CONCURRENT HASKELL

Rafael lvarez Lpez Fernando vila Ferrer

NDICE

1. INTRODUCCIN 1.1 Motivacin y Orgenes 1.2 Concurrencia y lenguajes funcionales 2. CONCURRENT HASKELL
2.1 Procesos 2.2 Sincronizacin y comunicacin 2.3 Semforos 2.4 Otras operaciones concurrentes 2.5 Productor/consumidor 2.6 Canales

3. CONCLUSIONES 4. REFERENCIAS
2

1. INTRODUCCIN

La necesidad de ofrecer concurrencia en el acceso a los recursos computacionales se remonta a los primeros sistemas operativos. Aprovechar al mximo los recursos computacionales fue una necesidad apremiante, sobre todo en la poca en que las computadoras eran caras y escasas; el sistema operativo tena que ofrecer la ejecucin concurrente y segura de programas de varios usuarios, que desde distintas terminales utilizaban un solo procesador, y as surgi la necesidad de introducir algunos conceptos de programacin concurrente para programar los sistemas operativos.
3

1.1 Motivacin y Orgenes


Existen sistemas inherentemente concurrentes: los sistemas reactivos. Aparte de esta motivacin existen otras dos motivaciones principales, que de hecho fueron anteriores en el tiempo a la utilizacin de la programacin concurrente para la construccin de sistemas reactivos: Explotacin de arquitecturas paralelas para obtener ganancia en la velocidad de ejecucin (Programacin Paralela). Mejorar la utilizacin del procesador (Sistemas Operativos).
4

1.2 Concurrencia y lenguajes funcionales

Debido a la propiedad de confluencia (podemos encontrar dos secuencias de evaluacin diferentes que parten del mismo dato de entrada), los lenguajes funcionales pueden utilizar directamente el paralelismo implcito. Otra opcin es aadir al lenguaje ciertas extensiones para especificar la concurrencia, como es el caso que vamos a estudiar.
5

2. CONCURRENT HASKELL

Concurrent Haskell es una extensin 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 ms que una extensin 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 semntica para Haskell claramente diferenciada en una capa determinista y una capa concurrente. Las tcnicas de razonamiento existentes son mantenidas sin modificaciones, por ejemplo, las transformaciones de programas que preservan la correccin en un programa Haskell secuencial tambin la preservarn en un lenguaje Haskell concurrente. Hay pocas operaciones primitivas nuevas, que son expresivas y fciles de implementar.

nuevos ingredientes a haskell:


Procesos, y un mecanismo para gestionarlos. Estados atmicos mutables, para soportar comunicacin y cooperacin entre los procesos.

2.1 Procesos

Concurrent Haskell proporciona la nueva primitiva forkIO que inicia un proceso concurrente: forkIO :: IO () -> IO () forkIO a , es una accin que toma a otra accin , a, como su argumento y crea un proceso concurrente que ejecuta dicha accin. La entrada y salida y otros efectos laterales realizados por a, son interpolados de una manera indefinida con aquellos que siguen el forkIO.

Ejemplo1:
import Control.Concurrent main = forkIO (escribir 'a') >> escribir 'b' where escribir c = putChar c >> escribir c

10

caractersticas de forkIO :

Como la implementacin de haskell usa evaluacin perezosa, forkIO necesitar sincronizacin 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 evaluacin 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 solucin correcta ser proveer mecanismos que permitan la gestin segura de un estado compartido. forkIO es asimtrico. Cuando un proceso ejecuta un forkIO crea un proceso hijo que se ejecuta concurrentemente al padre.
11

2.2 Sincronizacin y comunicacin

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 semforo. Para que un proceso pueda leer una cadena de valores producida por varios procesos es proporcionando una operacin no determinista de ordenacin.
12

Type MVar a

Un valor del tipo MVar t, para algn tipo t, es el nombre de una posicin de memoria que pueda estar vaca 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 posicin sea no vaca. Entonces lee y devuelve el valor dejando la posicin vaca. putMVar :: MVar a -> a -> IO () Escribe un valor en la posicin 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 versin 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 semforo binario, donde los signal y los waits son implementados con putMVar y takeMVar respectivamente.
14

2.3 Semforos
Aunque se puede implementar con un MVar usando las operaciones putMVar y takeMVar, los semforos tambien estn implementados en Concurrent Haskell. Semforo binario: data QSem newQSem :: Int -> IO QSem waitQSem :: QSem -> IO () signalQSem :: QSem -> IO ()
15

2.3 Semforos
Semforos de cantidad general: data QSemN newQSemN :: Int -> IO QSemN waitQSemN :: QSemN -> Int -> IO () signalQSemN :: QSemN -> Int -> IO ()

16

2.4 Otras operaciones concurrentes


forkIO :: IO a -> IO --Crea proceso hijo threadDelay :: Int -> IO () Dormir durante n microsegundos newEmptyMVar :: IO (MVar a) Crear Mvar vaco newMVar :: a -> IO (MVar a) Inicializar MVAr takeMVar :: MVar a -> IO a take bloqueante putMVar :: MVar a -> a -> IO () put bloqueante tryTakeMVar :: MVar a -> IO (Maybe a) take no bloqueante tryPutMVar :: MVar a -> a -> IO Bool put no bloqueante isEmptyMVar :: MVar a -> IO Bool -- Test de Mvar vaco swapMVar :: MVar a -> a -> IO a --- Intercambia el valor de Mvar
17

2.5 Productor/consumidor

MVar puede ser usado para implementar una conexin entre productor y consumidor. El productor guarda elementos en el MVar y el consumidor los saca. El problema es que no hay nada que impida que el productor escriba un segundo valor antes de que el consumidor haya sacado el primero. Este problema se soluciona con un segundo MVar para manejar confirmaciones entre consumidor y productor. Llamaremos a la abstraccin resultante CVar (variable de canal).
18

Productor consumidor
type CVar a = (MVar a, MVar ()) -- Productor-> consumidor -- Consumidor -> productor

newCVar :: IO (CVar a) newCVar = newMVar >>= \ data_var -> newMVar >>= \ ack_var -> putMVar ack_var () >> return (data_var, ack_var)
putCVar :: CVar a -> a -> IO () putCVar (data_var,ack_var) val= takeMVar ack_var >> putMVar data_var val

getCVar :: CVar a -> IO a getCVar (data_var,ack_var) = takeMVar data_var putMVar ack_var () >> return val

>>= \ val ->


19

2.6 Canales

El proceso creado por el forkIO y su padre pueden realizar entrada y salida independientemente. Podemos pensar en el estado del sistema como un objeto conmutable compartido. Por ejemplo, si dos procesos escriben en el mismo fichero pueden aparecer situaciones indeseadas. Pero como ya sabemos, es comn que dos o ms procesos quieran acceder al mismo fichero.
20

Canales
Usando MVars podemos definir un nuevo tipo que llamaremos canal que permitir que mltiples procesos escriban y lean de l de forma segura. type Channel a = (MVar (Stream a), -- ltimo ledo MVar (Stream a)) -- ltimo escrito newChan :: IO (Channel a) putChan :: Channel a -> a -> IO getChan :: Channel a -> IO a

21

Canales

22

El canal est implementado por un par de MVars que apuntan al ltimo elemento ledo (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 vaco (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 vaco. 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 :: Channel a -> IO (Channel a)


dupChan (read,write) = do { new_read <- newEmptyMVar ; hole <- readMVar write ; putMVar new_read hole ; return (new_read, write) }
28

Implementacin 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 vaco 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. Aadiendo 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 estn siendo empleados de manera comercial como herramienta de programacin para servidores, aportando una nueva manera de programar potente y elegante.
30

4. REFERENCIAS

http://www.haskell.org Ruz, B.C.; Gutirrez, F.; Guerrero, P.; Gallardo, J.E.: Razonando con Haskell. Una introduccin a la Programacin Funcional. Servicio reprogr. (OC) E.T.S.I.I., Universidad de Mlaga. 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 Programacin Declarativa Avanzada.
Blas Carlos Ruiz Jimnez
31