Programación con memoria compartida Andrés Becerra Sandoval [email protected] 20 de abril de 2007 Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Asignación I V = {NewCell Valor_inicial} Asignación I I V = {NewCell Valor_inicial} V := Nuevo_valor Asignación I I I V = {NewCell Valor_inicial} V := Nuevo_valor @V El valor de la celda Asignación I I I I V = {NewCell Valor_inicial} V := Nuevo_valor @V El valor de la celda {Exchange V Old New} Asignación I I I I V = {NewCell Valor_inicial} V := Nuevo_valor @V El valor de la celda {Exchange V Old New} I Liga Old al valor viejo de la celda Asignación I I I I V = {NewCell Valor_inicial} V := Nuevo_valor @V El valor de la celda {Exchange V Old New} I I Liga Old al valor viejo de la celda Pone el valor New en la celda actualizándola Ejemplo Cola (Declarativa) f u n { NewQueue } X C={ NewCell q ( 0 X X ) } proc { I n s e r t X} N S E1 i n q (N S X | E1)=@C C: = q (N+1 S E1 ) end fun { Delete } N S1 E X i n q (N X | S1 E)=@C C: = q (N−1 S1 E ) X end in queue ( i n s e r t : I n s e r t d e l e t e : D e l e t e ) end Ejemplo Cola (Imperativa) f u n { NewQueue } X C={ NewCell q ( 0 X X ) } proc { I n s e r t X} N S E1 N1 i n { Exchange C q (N S X | E1 ) q ( N1 S E1 ) } N1=N+1 end fun { Delete } N S1 E N1 X i n { Exchange C q (N X | S1 E ) q ( N1 S1 E ) } N1=N−1 X end in queue ( i n s e r t : I n s e r t d e l e t e : D e l e t e ) end Ejemplo Cola (con Locks) f u n { NewQueue } X C={ NewCell q ( 0 X X ) } L ={ NewLock } proc { I n s e r t X} N S E1 i n l o c k L then q (N S X | E1)=@C C: = q (N+1 S E1 ) end end fun { Delete } N S1 E X i n l o c k L then q (N X | S1 E)=@C C: = q (N−1 S1 E ) end X end in queue ( i n s e r t : I n s e r t d e l e t e : D e l e t e ) end Ejemplo Cola (con clase) c l a s s Queue a t t r queue prop l o c k i n g meth i n i t queue : = q ( 0 X X ) end meth i n s e r t ( X ) l o c k N S E1 i n q (N S X | E1)=@queue queue : = q (N+1 S E1 ) end end meth d e l e t e ( X ) l o c k N S1 E i n q (N X | S1 E)=@queue queue : = q (N−1 S1 E ) end end end Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Arreglos I I I I I Un arreglo es un conjunto de celdas indexadas A = {NewArray +LowI +HighI InitX } {Array.put A I X} . Ai := X {Array.get A I } . Ai {Array.exchange A +I OldVal NewVal} . Actualiza Ai Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Diccionarios I I I I Un diccionario es una lista de parejas (llave, valor) D = {NewDictionary} {Dictionary.put D +LI X} En la llave LI coloca el valor X {Dictionary.get +D +LI X} Liga X al valor que tiene la llave LI Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Tuple Spaces I I I Un espacio de tuplas es un conjunto de tuplas etiquetadas write: {TS write T} Escribe la tupla T en el espacio TS read: {TS read(L T)} Espera a que el espacio TS tenga una tupla con etiqueta L, cuando suceda esto liga T a dicha tupla Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Cola (con Tuple Spaces) f u n { NewQueue } X TS={New TupleSpace i n i t } proc { I n s e r t X} N S E1 i n { TS read ( q q (N S X | E1 ) ) } { TS w r i t e ( q (N+1 S E1 ) ) } end fun { Delete } N S1 E X i n { TS read ( q q (N X | S1 E ) ) } { TS w r i t e ( q (N−1 S1 E ) ) } X end in { TS w r i t e ( q ( 0 X X ) ) } queue ( i n s e r t : I n s e r t d e l e t e : D e l e t e ) end Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Implementación de Tuple Spaces c l a s s TupleSpace prop l o c k i n g attr tupledict meth i n i t t u p l e d i c t : = { NewDictionary } end meth EnsurePresent ( L ) i f { Not { D i c t i o n a r y . member @ t u p l e d i c t L } } then @ t u p l e d i c t . L : = { NewQueue } end end meth Cleanup ( L ) i f { @ t u p l e d i c t . L . s i z e }==0 then { D i c t i o n a r y . remove @ t u p l e d i c t L } end end meth w r i t e ( Tuple ) l o c k L ={ Label Tuple } i n { s e l f EnsurePresent ( L ) } { @ t u p l e d i c t . L . i n s e r t Tuple } end end Implementación de Tuple Spaces meth w r i t e ( Tuple ) l o c k L ={ Label Tuple } i n { s e l f EnsurePresent ( L ) } { @ t u p l e d i c t . L . i n s e r t Tuple } end end meth read ( L ? Tuple ) lock { s e l f EnsurePresent ( L ) } { @ t u p l e d i c t . L . d e l e t e Tuple } { s e l f Cleanup ( L ) } end { Wait Tuple } end Implementación de Tuple Spaces meth readnonblock ( L ? Tuple ?B ) lock { s e l f EnsurePresent ( L ) } i f { @ t u p l e d i c t . L . s i z e } >0 then { @ t u p l e d i c t . L . d e l e t e Tuple } B= t r u e e l s e B= f a l s e end { s e l f Cleanup ( L ) } end end Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Locks - Candados I I Los candados permiten proteger varias regiones críticas Podemos implementarlos, aunque Oz tiene una implementación a bajo nivel (C++) más eficiente Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Lock (no reentrante) f u n { SimpleLock } Token ={ NewCell u n i t } proc { Lock P} Old New i n { Exchange Token Old New} { Wait Old } { P} New= u n i t end in ’ l o c k ’ ( ’ l o c k ’ : Lock ) end Lock (no reentrante) Con manejo de excepciones: f u n { CorrectSimpleLock } Token ={ NewCell u n i t } proc { Lock P} Old New i n { Exchange Token Old New} { Wait Old } t r y { P} f i n a l l y New= u n i t end end in ’ l o c k ’ ( ’ l o c k ’ : Lock ) end Lock (reentrante) f u n { NewLock } Token ={ NewCell u n i t } CurThr ={ NewCell u n i t } proc { Lock P} i f { Thread . t h i s }==@CurThr then { P} e l s e Old New i n { Exchange Token Old New} { Wait Old } CurThr : = { Thread . t h i s } t r y { P} f i n a l l y CurThr : = u n i t New= u n i t end end end in ’ l o c k ’ ( ’ l o c k ’ : Lock ) end Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Monitores I I Un monitor es un tipo abstracto de datos que protege varias regiones críticas (al igual que un lock), pero permite un mayor control al programador (son más expresivos), ya que los hilos se pueden notificar eventos entre si Operaciones: I I I I Lock Wait Notify NotifyAll Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Bounded Buffer Un ejemplo familiar: class Buffer attr buf f i r s t l a s t n i meth i n i t (N) b u f : = { NewArray 0 N−1 n u l l } f i r s t :=0 l a s t :=0 n : =N i :=0 end meth p u t ( X ) . . . % w a i t u n t i l i <n % now add an element : @buf . @last : =X l a s t : = ( @last +1) mod @n i : = @i+1 end meth g e t ( X ) . . . % w a i t u n t i l i >0 % now remove an element : X=@buf . @ f i r s t f i r s t : = ( @ f i r s t +1) mod @n Bounded Buffer (con monitor) Un monitor ayuda a modelar: class Buffer a t t r m buf f i r s t l a s t n i meth i n i t (N) m: = { NewMonitor } b u f : = { NewArray 0 N−1 n u l l } n : =N i :=0 f i r s t :=0 l a s t :=0 end meth p u t ( X ) {@m. ’ l o c k ’ proc { $ } i f @i>=@n then {@m. w a i t } { s e l f p u t ( X ) } else @buf . @last : =X l a s t : = ( @last +1) mod @n i : = @i+1 {@m. n o t i f y A l l } end end } end Bounded Buffer (con monitor) meth g e t ( X ) {@m. ’ l o c k ’ proc { $ } i f @i==0 then {@m. w a i t } { s e l f g e t ( X ) } else X=@buf . @ f i r s t f i r s t : = ( @ f i r s t +1) mod @n i : = @i−1 {@m. n o t i f y A l l } end end } end end Contenido Introducción TADs imperativos Arreglos Diccionarios Tuple Spaces Definición Ejemplo con Tuple Spaces Implementación Locks Definición Implementación Monitores Definición Ejemplo Implementación Implementación de Monitor f u n { NewMonitor } Q={NewQueue } L ={NewGRLock } proc { LockM P} { L . g e t } t r y { P} f i n a l l y { L . r e l e a s e } end end proc { WaitM } X in {Q. i n s e r t X} { L . r e l e a s e } { Wait X} { L . g e t } end proc { N o t i f y M } U={Q. deleteNonBlock } i n case U o f [ X ] then X= u n i t e l s e s k i p end end proc { N o t i f y A l l M } L ={Q. d e l e t e A l l } i n f o r X i n L do X= u n i t end end in m o n i t o r ( ’ l o c k ’ : LockM w a i t : WaitM n o t i f y : N o t i f y M Cola extendida f u n { NewQueue } ... f u n { Size } l o c k L then @C. 1 end end fun { D e l e t e A l l } l o c k L then X q ( _ S E)=@C i n C: = q ( 0 X X ) E= n i l S end end f u n { DeleteNonBlock } l o c k L then i f { Size } >0 then [ { D e l e t e } ] e l s e n i l end end end in queue ( i n s e r t : I n s e r t d e l e t e : D e l e t e s i z e : Size d e l e t e A l l : D e l e t e A l l deleteNonBlock : DeleteNonBl Lock(get-release) f u n { NewGRLock } Token1 ={ NewCell u n i t } Token2 ={ NewCell u n i t } CurThr ={ NewCell u n i t } proc { GetLock } i f { Thread . t h i s } \ = @CurThr then Old New i n { Exchange Token1 Old New} { Wait Old } Token2 : =New CurThr : = { Thread . t h i s } end end proc { ReleaseLock } CurThr : = u n i t u n i t =@Token2 end in ’ l o c k ’ ( g e t : GetLock r e l e a s e : ReleaseLock ) end