stringtranslate.com

Patrón de unión

Join-patterns proporciona una forma de escribir programas informáticos concurrentes , paralelos y distribuidos mediante el paso de mensajes . En comparación con el uso de subprocesos y bloqueos, este es un modelo de programación de alto nivel que utiliza un modelo de construcción de comunicación para abstraer la complejidad del entorno concurrente y permitir la escalabilidad . Su enfoque está en la ejecución de un acorde entre mensajes consumidos atómicamente desde un grupo de canales.

Esta plantilla se basa en el cálculo de uniones y utiliza la coincidencia de patrones . En concreto, esto se hace permitiendo la definición de uniones de varias funciones y/o canales mediante la coincidencia de patrones de llamadas y mensajes concurrentes. Es un tipo de patrón de concurrencia porque hace más fácil y flexible que estas entidades se comuniquen y gestionen con el paradigma de programación multiproceso.

Descripción

El patrón de unión (o un acorde en Cω ) es como una supertubería con sincronización y emparejamiento. De hecho, este concepto se resume en emparejar y unir un conjunto de mensajes disponibles de diferentes colas de mensajes , y luego manejarlos todos simultáneamente con un controlador. [1] Podría representarse con las palabras clave whenpara especificar la primera comunicación que esperábamos, con el andpara unir/emparejar otros canales y el dopara ejecutar algunas tareas con los diferentes mensajes recopilados. Un patrón de unión construido normalmente toma esta forma:

j.Cuando(a1).Y(a2)....Y(an).Haz(d)

El argumento a1 de When(a1)puede ser un canal sincrónico o asincrónico o una matriz de canales asincrónicos. Cada argumento ai posterior a (for ) debe ser un canal asincrónico. [2]And(ai)i > 1

Más precisamente, cuando un mensaje coincide con una cadena de patrones vinculados, hace que su controlador se ejecute (en un nuevo hilo si está en un contexto asincrónico); de lo contrario, el mensaje se pone en cola hasta que se habilite uno de sus patrones; si hay varias coincidencias, se selecciona un patrón no especificado. [3]

A diferencia de un controlador de eventos, que atiende uno de varios eventos alternativos a la vez, junto con todos los demás controladores de ese evento, un patrón de unión espera una conjunción de canales y compite por la ejecución con cualquier otro patrón habilitado. [4]

Este diagrama de flujo muestra cómo se ejecuta el patrón de unión mediante una coincidencia general con diferentes canales (esperar un acorde) y sincroniza los recursos (libres o bloqueados).

El patrón de unión se define mediante un conjunto de canales de cálculo pi x que admiten dos operaciones diferentes, enviar y recibir. Necesitamos dos nombres de cálculo de unión para implementarlo: un nombre de canal x para enviar (un mensaje) y un nombre de función x para recibir un valor (una solicitud). El significado de la definición de unión es que una llamada a devuelve un valor que se envió en un canal . Cada vez que las funciones se ejecutan simultáneamente, se activa el proceso de retorno y se sincroniza con otras uniones. [5]x()x<>

J ::= //patrones de unión | x < y > //patrón de envío de mensajes | x ( y ) //patrón de llamada de función | J | JBIS //sincronización          

Desde la perspectiva de un cliente, un canal simplemente declara un método con el mismo nombre y firma. El cliente publica un mensaje o emite una solicitud invocando el canal como método. Un método de continuación debe esperar hasta que llegue una única solicitud o mensaje a cada uno de los canales que siguen a la cláusula When de la continuación. Si la continuación se ejecuta, los argumentos de cada invocación de canal se sacan de la cola (y, por lo tanto, se consumen) y se transfieren (atómicamente) a los parámetros de la continuación. [6]

Diagrama de clases del patrón Join

En la mayoría de los casos, el orden de las llamadas sincrónicas no está garantizado por razones de rendimiento. Finalmente, durante la partida, los mensajes disponibles en la cola podrían ser robados por algún hilo interviniente; de ​​hecho, el hilo despertado podría tener que esperar nuevamente. [7]

Historia

Cálculo π – 1992

El cálculo π pertenece a la familia de cálculos de procesos , permite formalismos matemáticos para describir y analizar propiedades de computación concurrente mediante el uso de nombres de canales que se comunican a lo largo de los propios canales, y de esta manera es capaz de describir cálculos concurrentes cuya configuración de red puede cambiar durante el cálculo.

Cálculo de uniones – 1993

Los patrones de unión aparecieron por primera vez en el cálculo de unión fundacional de Fournet y Gonthier, un álgebra de procesos asincrónicos diseñado para una implementación eficiente en un entorno distribuido. [8] El cálculo de unión es un cálculo de procesos tan expresivo como el cálculo π completo . Fue desarrollado para proporcionar una base formal para el diseño de lenguajes de programación distribuida y, por lo tanto, evita intencionalmente las construcciones de comunicaciones que se encuentran en otros cálculos de procesos, como las comunicaciones de encuentro .

Cálculo de uniones distribuidas – 1996

Join-Calculus es a la vez un cálculo de paso de nombres y un lenguaje central para la programación concurrente y distribuida. [9] Es por eso que Distributed Join-Calculus [10] basado en Join-Calculus con la programación distribuida fue creado en 1996. Este trabajo utiliza los agentes móviles donde los agentes no son solo programas sino imágenes centrales de procesos en ejecución con sus capacidades de comunicación.

JoCaml, Funnel y Join Java – 2000

JoCaml [11] [12] y Funnel [13] [14] son ​​lenguajes funcionales que admiten patrones de unión declarativos. Presentan ideas para implementar directamente cálculos de procesos en un entorno funcional.

Otras extensiones de Java (no genéricas), JoinJava, fueron propuestas independientemente por von Itzstein y Kearney. [15]

Do# polifónico – 2002

Cardelli, Benton y Fournet propusieron una versión orientada a objetos de patrones de unión para C# llamada C# polifónico . [16]

Cω-2003

Cω es una adaptación del cálculo de unión a un entorno orientado a objetos. [17] Esta variante de C# polifónico se incluyó en la versión pública de Cω (también conocido como Comega) en 2004.

Scala se incorpora – 2007

Scala Joins es una biblioteca para utilizar Join-Pattern con Scala en el contexto de coincidencia de patrones extensible con el fin de integrar uniones en un marco de concurrencia basado en actores existente. [18]

Jerlang – 2009

Erlang es un lenguaje que soporta de forma nativa el paradigma concurrente, en tiempo real y distribuido. La concurrencia entre procesos era compleja, por eso el proyecto construyó un nuevo lenguaje, JErlang ( J significa Join ) basado en el cálculo de Join.

Patrón de unión en la literatura clásica de programación

"Los patrones de unión se pueden utilizar para codificar fácilmente expresiones de concurrencia relacionadas, como actores y objetos activos". [19]

clase SymmetricBarrier { público de solo lectura Sincrónico . Canal Llegar ;      public SymmetricBarrier ( int n ) { // Crea j y canales de inicialización (eliminados) var pat = j . When ( Llegar ); for ( int i = 1 ; i < n ; i ++ ) pat = pat . And ( Llegar ); pat . Do (() => { }); } }                         
var j = Join . Create (); Sincrónico . Channel [] hambriento ; Asincrónico . Channel [] palillo ; j . Init ( fuera hambriento , n ); j ​​. Init ( fuera palillo , n );         para ( int i = 0 ; i < n ; i ++ ) { var izquierda = palillo [ i ]; var derecha = palillo [ ( i + 1 ) % n ]; j . Cuando ( hambriento [ i ]). Y ( izquierda ). Y ( derecha ). Hacer (() => { comer (); izquierda (); derecha (); // reemplazar palillos }); }                          
clase Lock { público readonly Synchronous . Channel Acquire ; público readonly Asynchronous . Channel Release ;          public Lock () { // Crea j y canales de inicialización (eliminados) j . When ( Acquire ). And ( Release ). Do (() => { }); Release (); // inicialmente libre } }          
clase Buffer < T > { público de solo lectura Asíncrono . Canal < T > Put ; público de solo lectura Síncrono < T > . Canal Get ;          public Buffer () { Join j = Join . Create (); // asignar un objeto Join j . Init ( out Put ); // enlazar sus canales j . Init ( out Get ); j ​​. When ( Get ). And ( Put ). Do // registrar chord ( t => { return t ; }); } }                     
clase ReaderWriterLock { privado de solo lectura Asíncrono . Canal inactivo ; privado de solo lectura Asíncrono . Canal < int > compartido ; público de solo lectura Síncrono . Canal AcqR , AcqW , RelR , RelW ;                 public ReaderWriterLock () { // Crea j y canales de inicialización (eliminados) j . When ( AcqR ). And ( idle ). Do (() => shared ( 1 )); j . When ( AcqR ). And ( shared ). Do ( n => shared ( n + 1 )); j . When ( RelR ). And ( shared ). Do ( n => { if ( n == 1 ) { idle (); } else { shared ( n - 1 ); } }); j . When ( AcqW ). And ( idle ). Do (() => { }); j . When ( RelW ). Do (() => idle ()); idle (); // inicialmente libre } }                                  
clase Semáforo { público readonly Sincrónico . Canal Adquirir ; público readonly Asíncrono . Canal Liberar ;          public Semaphore ( int n ) { // Crea j y canales de inicialización (eliminados) j . When ( Adquirir ). And ( Liberar ). Hacer (() => { }); for (; n > 0 ; n -- ) Liberar (); // inicialmente n libre } }                 

Características y conceptos fundamentales

Dominio de aplicación

Agente móvil

Un agente móvil es un agente de software autónomo con cierta capacidad social y, lo más importante, movilidad. Está compuesto por software y datos informáticos que pueden moverse entre diferentes ordenadores de forma automática mientras continúan sus ejecuciones.

Los agentes móviles pueden utilizarse para hacer coincidir la concurrencia y la distribución si se utiliza el cálculo de unión. Por eso se creó un nuevo concepto llamado "cálculo de unión distribuido", que es una extensión del cálculo de unión con ubicaciones y primitivas para describir la movilidad. Esta innovación utiliza a los agentes como procesos en ejecución con sus capacidades de comunicación para permitir una idea de la ubicación, que es un sitio físico que expresa la posición real del agente. Gracias al cálculo de unión, una ubicación se puede mover atómicamente a otro sitio. [24]

Los procesos de un agente se especifican como un conjunto que define su funcionalidad, incluida la emisión asincrónica de un mensaje y la migración a otra ubicación. En consecuencia, las ubicaciones se organizan en un árbol para representar más fácilmente el movimiento del agente. Con esta representación, un beneficio de esta solución es la posibilidad de crear un modelo simple de falla. Por lo general, una falla de un sitio físico causa la falla permanente de todas sus ubicaciones. Pero con el cálculo de unión, se puede detectar un problema con una ubicación en cualquier otra ubicación en ejecución, lo que permite la recuperación de errores. [24]

Por lo tanto, el cálculo de unión es el núcleo de un lenguaje de programación distribuido. En particular, la semántica operacional es fácilmente implementable en un entorno distribuido con fallas. Por lo tanto, el cálculo de unión distribuido trata los nombres de los canales y los nombres de las ubicaciones como valores de primera clase con alcances léxicos. Una ubicación controla sus propios movimientos y solo puede moverse hacia una ubicación cuyo nombre ha recibido. Esto proporciona una base sólida para el análisis estático y para la movilidad segura. Esto es completo para expresar configuraciones distribuidas. Sin embargo, en ausencia de fallas, la ejecución de procesos es independiente de la distribución. Esta transparencia de ubicación es esencial para el diseño de agentes móviles y muy útil para verificar sus propiedades. [24]

En 2007, se ha presentado una extensión del cálculo de uniones básico con métodos que hacen que los agentes sean proactivos. Los agentes pueden observar un entorno compartido entre ellos. Con este entorno, es posible definir variables compartidas con todos los agentes (por ejemplo, un servicio de nombres para descubrir agentes entre ellos). [25]

Compilación

Los lenguajes join se construyen sobre el cálculo join, que se toma como lenguaje central. De modo que todo el cálculo se analiza con procesos asincrónicos y el patrón join proporciona un modelo para sincronizar el resultado. [9]
Para ello, existen dos compiladores:

Estos dos compiladores trabajan con el mismo sistema, un autómata.

sea ​​A(n) | B() = P(n)y A(n) | C() = Q(n);;

Representa el consumo de un mensaje que llega a un modelo de unión completado. Cada estado es un posible paso para la ejecución del código y cada transición es la recepción de un mensaje para cambiar entre dos pasos. Y así, cuando se obtienen todos los mensajes, el compilador ejecuta el código de unión del cuerpo correspondiente a la unión del modelo completada.

En el cálculo de unión, los valores básicos son los nombres, como en el ejemplo A, B o C. Por lo tanto, los dos compiladores representan estos valores de dos maneras.
El compilador de unión usa un vector con dos ranuras, la primera para el nombre en sí y la segunda para una cola de mensajes pendientes.
Jocaml usa el nombre como un puntero a las definiciones. Estas definiciones almacenan los otros punteros de los otros nombres con un campo de estado y una estructura de fecha coincidente por mensaje.
La diferencia fundamental es cuando se ejecuta el proceso de protección, para el primero, se verifica si todos los nombres son los mensajes pendientes listos, mientras que el segundo usa solo una variable y accede a las otras para saber si el modelo está completo. [9]

Investigaciones recientes describen el esquema de compilación como la combinación de dos pasos básicos: envío y reenvío. El diseño y la corrección del despachador se derivan esencialmente de la teoría de coincidencia de patrones, mientras que la inserción de un paso de reenvío interno en las comunicaciones es una idea natural, que intuitivamente no cambia el comportamiento del proceso. Hicieron la observación de que lo que vale la pena observar es que una implementación directa de la coincidencia de patrones de unión extendida en el nivel de tiempo de ejecución complicaría significativamente la gestión de las colas de mensajes, que luego necesitarían ser escaneadas en busca de mensajes coincidentes antes de consumirlos. [26]

Implementaciones y bibliotecas

Existen muchos usos de los patrones de unión en diferentes lenguajes. Algunos lenguajes utilizan patrones de unión como base de sus implementaciones, por ejemplo, Polyphonic C# o MC#, pero otros lenguajes integran patrones de unión mediante una biblioteca como Scala Joins [27] para Scala o la biblioteca Joins para VB. [28] Además, el patrón de unión se utiliza a través de algunos lenguajes como Scheme para actualizar el patrón de unión. [29]

Únase a Java

Join Java [30] es un lenguaje basado en el lenguaje de programación Java que permite el uso del cálculo de uniones. Introduce tres nuevas construcciones de lenguaje:

Ejemplo:

clase  JoinExample { int fragment1 () & fragment2 ( int x ) { // Devolverá el valor de x al llamador de fragment1 return x ; } }           

Ejemplo:

clase  ThreadExample { señal thread ( SomeObject x ) { // Este código se ejecutará en un nuevo hilo } }       

Los fragmentos de unión se pueden repetir en múltiples patrones de unión, por lo que puede haber un caso en el que se completen múltiples patrones de unión cuando se llama a un fragmento. Tal caso podría ocurrir en el ejemplo siguiente si se llaman B(), C() y D() y luego A(). El fragmento A() final completa tres de los patrones, por lo que hay tres métodos posibles que se pueden llamar. El modificador de clase ordenado se utiliza aquí para determinar qué método de unión se llamará. El valor predeterminado y cuando se usa el modificador de clase desordenado es elegir uno de los métodos al azar. Con el modificador ordenado, los métodos se priorizan según el orden en que se declaran.

Ejemplo:

clase  ordenada SimpleJoinPattern { void A () & B () { } void A () & C () { } void A () & D () { } señal D () & E () { } }                          

El lenguaje más cercano relacionado es el polifónico C# .

Jerlang

En la codificación Erlang, la sincronización entre múltiples procesos no es sencilla. Por eso se creó JErlang, [31] una extensión de Erlang , The J is for Join. De hecho, para superar esta limitación se implementó JErlang, una extensión de Erlang inspirada en el cálculo de uniones . Las características de este lenguaje son:

operación () -> recibir { ok , suma } y { val , X } y { val , Y } -> { suma , X + Y }; { ok , mult } y { val , X } y { val , Y } -> { mult , X * Y }; { ok , sub } y { val , X } y { val , Y } -> { sub , X - Y }; fin fin                                          
recibir { Transacción , M } y { límite , Inferior , Superior } cuando ( Inferior <= M y M <= Superior ) -> commit_transaction ( M , Transacción ) fin                  
recibir { obtener , X } y { establecer , X } -> { encontrado , 2 , X } fin ... recibir { Pin , id } y { auth , Pin } y { commit , Id } -> perform_transaction ( Pin , Id ) fin                    
recibir prop ({ sesión , Id }) y { acto , Acción , Id } -> realizar_acción ( Acción , Id ); { sesión , Id } y { cierre de sesión , Id } -> cierre de sesión_usuario ( Id ) fin ... recibir { Pin , id } y { auth , Pin } y { commit , Id } -> realizar_transacción ( Pin , Id ) fin                           
recibir { aceptar , Pid1 } y { asíncrono , Valor } y { aceptar , Pid2 } -> Pid1 ! { ok , Valor }, Pid2 ! { ok , Valor } fin                 

C++

Yigong Liu ha escrito algunas clases para el patrón de unión que incluye todas las herramientas útiles como canales asincrónicos y sincrónicos, acordes , etc. Está integrado en el proyecto Boost c++.

plantilla < typename V > clase buffer : public joint { public : async < V > put ; synch < V , void > get ; buffer () { acorde ( get , put , & buffer :: chord_body ); } V cuerpo_acorde ( void_t g , V p ) { return p ; } };                         

Este ejemplo nos muestra un buffer seguro para subprocesos y una cola de mensajes con las operaciones básicas put y get. [32]

DO#

Do# polifónico

Polyphonic C# es una extensión del lenguaje de programación C#. Introduce un nuevo modelo de concurrencia con métodos sincrónicos y asincrónicos (que devuelven el control al autor de la llamada) y acordes (también conocidos como "patrones de sincronización" o "patrones de unión").

clase pública Buffer { pública String get () y pública async put ( String s ) { return s ; } }              

Este es un ejemplo de buffer simple. [33]

MC#

El lenguaje MC# es una adaptación del lenguaje polifónico C# para el caso de cálculos distribuidos concurrentes.

manejador público Get2 long () y canal c1 ( long x ) y canal c2 ( long y ) { return ( x + y ); }                 

Este ejemplo demuestra el uso de acordes como herramienta de sincronización.

C# paralelo

Parallel C# se basa en C# polifónico y agrega algunos conceptos nuevos como métodos móviles y funciones de orden superior.

usando Sistema ; clase Test13 { int Recibir () y async Enviar ( int x ) { devolver x * x ; }              public static void Main ( string [ ] args ) { Test13 t = new Test13 ( ); t.Send ( 2 ) ; Console.WriteLine ( t.Receive ( ) ) ; } }             

Este ejemplo demuestra cómo utilizar uniones. [34]

Cω agrega nuevas características del lenguaje para soportar la programación concurrente (basada en el anterior Polyphonic C# ). La biblioteca de concurrencia de uniones para C# y otros lenguajes .NET se deriva de este proyecto. [35] [36]

Patrones de unión escalables

Es una biblioteca de patrones de unión declarativa y escalable fácil de usar. A diferencia de la biblioteca Russo, [28] no tiene bloqueo global. De hecho, funciona con un sistema de mensajes Atomic y CAS de comparación e intercambio . La biblioteca [37] utiliza tres mejoras para el patrón de unión:

JoCaml

JoCaml es el primer lenguaje en el que se implementó el patrón join. De hecho, al principio todas las diferentes implementaciones se compilaron con el compilador JoCaml. El lenguaje JoCaml es una extensión del lenguaje OCaml . Amplía OCaml con soporte para concurrencia y sincronización, la ejecución distribuida de programas y la reubicación dinámica de fragmentos de programas activos durante la ejecución. [38]

tipo  monedas  =  Nickel  |  Dime y  bebidas  =  Café  |  y  botones  =  BCoffee  |  BTea  |  BCancelar ;;(* def define una cláusula de conjunto de patrón Join * "&" en el lado izquierdo de = significa join (sincronismo de canal) * "&" en el lado derecho significa: proceso paralelo * synchronous_reply :== "reply" [x] "to" channel_name * los canales sincrónicos tienen tipos similares a funciones (`a -> `b) * los canales asincrónicos tienen tipos (`a Join.chan) * solo la última declaración en una expresión rhs de patrón puede ser un mensaje asincrónico * 0 en una posición de mensaje asincrónico significa STOP ("no se envió mensaje" en la terminología de CSP).  *)def  put ( s )  =  print_endline  s  ;  0  (* DETENER *)  ;;  (* put: cadena Join.chan *)def  serve ( beber )  =  match  drink  with  Coffee  ->  put ( "Café" )  |  Tea  ->  put ( "Té" )  ;;  (* serve: bebidas Join.chan *)def  reembolso ( v )  =  let  s  =  Printf.sprintf " Reembolso %d" v en put ( s ) ;; (* reembolso: int Join.chan * )      deje que  new_vending  sirva  reembolso  =  deje que  vend  ( costo : int )  ( crédito : int )  =  si  crédito  >=  costo  entonces  ( verdadero ,  crédito  -  costo )  de lo contrario  ( falso ,  crédito )  en  def  moneda ( Níquel )  y  valor ( v )  =  valor ( v + 5 )  y  respuesta  ()  a  moneda  o  moneda ( Dime )  y  valor ( v )  =  valor ( v + 10 )  y  respuesta  ()  a  moneda o  botón ( BCoffee )  &  valor ( v )  =  let  should_serve ,  resto  =  vend  10  v  en  ( si  should_serve  entonces  serve ( Coffee )  de lo contrario  0  (* STOP *) )  &  valor ( resto )  &  responder  ()  al  botón o  botón ( BTea )  y  valor ( v )  =  let  should_serve ,  resto  =  vend  5  v  en  ( si  should_serve  entonces  serve ( Tea )  de lo contrario  0  (*STOP *) )  y  valor ( resto )  y  responder  ()  al  botón o  botón ( BCancelar )  y  valor ( v )  =  reembolso (  v )  y  valor ( 0 )  y  responder  ()  al  botón  en  el valor de generación  ( 0 ) ; moneda , botón (* moneda, botón: int -> unidad *) ;; (* new_vending: bebida Join.chan -> int Join.chan -> (int->unidad)*(int->unidad) *)      deje que  ccoin ,  cbutton  =  new_vending  sirva  el reembolso  en  ccoin ( Nickel );  ccoin ( Nickel );  ccoin ( Dime );  Unix.sleep ( 1 ); cbutton ( BCoffee ); Unix.sleep ( 1 ) ; cbutton ( BTea ); Unix.sleep ( 1 ) ; cbutton ( BCancel ); Unix.sleep ( 1 ) ( * deje que se muestre el último mensaje * ) ;;        

da

CaféReembolso 5

Hume

Hume [39] es un lenguaje funcional estricto y fuertemente tipado para plataformas de recursos limitados, con concurrencia basada en paso de mensajes asincrónico, programación de flujo de datos y una sintaxis similar a Haskell .

Hume no proporciona mensajería sincrónica.

Envuelve un conjunto de patrones de unión con un canal en común como una caja , enumerando todos los canales en una tupla de entrada y especificando todas las salidas posibles en una tupla de salida .

Cada patrón de unión en el conjunto debe cumplir con el tipo de tupla de entrada del cuadro , especificando un '*' para los canales no requeridos, dando una expresión cuyo tipo se ajuste a la tupla de salida, marcando '*' las salidas no alimentadas.

Una cláusula de cable especifica

  1. una tupla de orígenes o fuentes de entrada correspondientes y, opcionalmente, valores iniciales
  2. una tupla de destinos de salida, que son canales o sumideros (stdout, ..).

Un cuadro puede especificar controladores de excepciones con expresiones que se ajusten a la tupla de salida.

datos Monedas = Nickel | Dime ; datos Bebidas = Café | ; datos Botones = BCoffee | BTea | BCancelar ;                 tipo Int = int 32 ; tipo String = string ; mostrar u = u como string ;               caja de café en ( moneda :: Monedas , botón :: Botones , valor :: Int ) - canales de entrada salida ( bebida_salida :: String , valor ' :: Int , reembolso_salida :: String ) - salidas con nombre                        match -- * comodines para salidas no completadas y entradas no consumidas ( Nickel , * , v ) -> ( * , v + 5 , * ) | ( Dime , * , v ) -> ( * , v + 10 , * ) | ( * , BCoffee , v ) -> vend Coffee 10 v | ( * , BTea , v ) -> vend Tea 5 v | ( * , BCancel , v ) -> let refund u = "Refund " ++ show u ++ " \n " in ( * , 0 , refund v ) ;                                                             vender bebida costo crédito = si crédito >= costo entonces ( servir bebida , crédito - costo , * ) de lo contrario ( * , crédito , * );                     servir bebida = caso bebida de Café -> "Café \n " -> "Té \n " ;           control de caja en ( c :: char ) salida ( moneda :: Monedas , botón :: Botones ) coincidencia 'n' -> ( Níquel , * ) | 'd' -> ( Diez centavos , * ) | 'c' -> ( * , BCoffee ) | 't' -> ( * , BTea ) | 'x' -> ( * , BCancelar ) | _ -> ( * , * ) ;                                      transmitir console_outp a "std_out" ; transmitir console_inp desde "std_in" ;        -- cableado de flujo de datoscable café -- entradas (canal orígenes) ( control . moneda , control . botón , café . valor ' inicialmente 0 ) -- salidas destinos ( console_outp , café . valor , console_outp ) ;           control de cable ( console_inp ) ( café . moneda , café . botón ) ;    

Visual Basic

Básico concurrente – CB

Una extensión de Visual Basic 9.0 con construcciones de concurrencia asincrónica, llamada Concurrent Basic (CB para abreviar), ofrece los patrones de unión. CB (se basa en trabajos anteriores sobre Polyphonic C#, Cω y la biblioteca de uniones) adopta una sintaxis simple similar a un evento familiar para los programadores de VB, permite declarar abstracciones de concurrencia genéricas y proporciona un soporte más natural para la herencia, lo que permite que una subclase aumente el conjunto de patrones. La clase CB puede declarar un método para ejecutar cuando se ha producido una comunicación en un conjunto particular de canales locales asincrónicos y sincrónicos, formando un patrón de unión. [28]

Módulo de búfer  Put público asíncrono ( ByVal s como cadena ) Take público síncrono () como cadena           Función privada CaseTakeAndPut ( ByVal s As String ) Como String _ Cuando Take , Put Devuelve s Fin de la función               Módulo final 

Este ejemplo muestra todas las palabras clave nuevas utilizadas por Concurrent Basic: Asynchronous, Synchronous y When. [40]

Biblioteca de uniones (C# y VB)

Esta biblioteca es una abstracción de alto nivel del patrón Join que utiliza objetos y genéricos. Los canales son valores delegados especiales de algún objeto Join común (en lugar de métodos). [41]

clase Buffer { público de solo lectura Asíncrono . Canal < cadena > Put ; público de solo lectura Síncrono < cadena > . Canal Get ;          public Buffer () { Unir join = Join . Create (); join . Initialize ( salida Poner ); join . Initialize ( salida Obtener ); join . When ( Obtener ). And ( Poner ). Do ( delegado ( cadena s ) { devolver s ; }); } }                 

Este ejemplo muestra cómo utilizar los métodos del objeto Join. [42]

Escala

La biblioteca Scala Joins utiliza el patrón Join. Las funciones de comparación de patrones de este lenguaje se han generalizado para permitir la independencia de representación de los objetos utilizados en la comparación de patrones. Por lo tanto, ahora es posible utilizar un nuevo tipo de abstracción en las bibliotecas. [ Aclaración necesaria ] La ventaja de los patrones de combinación es que permiten una especificación declarativa de la sincronización entre diferentes subprocesos. A menudo, los patrones de combinación se corresponden estrechamente con una máquina de estados finitos que especifica los estados válidos del objeto.

En Scala, es posible resolver muchos problemas con la coincidencia de patrones y Scala Joins, por ejemplo el Lector-Escritor. [27]

clase ReaderWriterLock extiende Joins {     privado val Sharing = new AsyncEvent [ Int ] val Exclusive , ReleaseExclusive = new NullarySyncEvent val Shared , ReleaseShared = new NullarySyncEvent join { caso Exclusive () y Sharing ( 0 ) => Respuesta exclusiva caso ReleaseExclusive () => { Sharing ( 0 ); Respuesta ReleaseExclusive } caso Shared () y Sharing ( n ) => { Sharing ( n + 1 ); Respuesta compartida } caso ReleaseShared () y Sharing ( 1 ) => { Sharing ( 0 ); Respuesta ReleaseShared } caso ReleaseShared () y Sharing ( n ) => { Sharing ( n - 1 ); Respuesta ReleaseShared } } Sharing ( 0 ) }                                                                   

Con una clase declaramos eventos en campos regulares. Por lo tanto, es posible utilizar la construcción Join para habilitar una coincidencia de patrones a través de una lista de declaraciones de casos. Esa lista se representa mediante => con una parte de la declaración en cada lado. El lado izquierdo es un modelo del patrón de unión para mostrar la combinación de eventos asincrónicos y sincrónicos y el lado derecho es el cuerpo de la unión que se ejecuta cuando se completa el modelo de unión.

En Scala, también es posible utilizar la biblioteca de actores de Scala [43] con el patrón de unión. Por ejemplo, un búfer sin límites: [27]

val Put = new Join1 [ Int ] val Get = new Join clase Buffer extiende JoinActor { def act () { recibir { caso Get () y Put ( x ) => Obtener respuesta x } } }                            

Scala Join y Chymyst son implementaciones más nuevas del patrón Join, que mejoran los Scala Joins del Dr. Philipp Haller.

Haskell

Join Language es una implementación del patrón Join en Haskell.

Esquema

Los patrones de unión permiten un nuevo tipo de programación, especialmente para las arquitecturas multinúcleo disponibles en muchas situaciones de programación con altos niveles de abstracción. Esto se basa en los patrones de protección y propagación. Por lo tanto, un ejemplo de esta innovación se ha implementado en Scheme. [29]

Los protectores son esenciales para garantizar que solo se actualicen o recuperen los datos con una clave coincidente. La propagación puede cancelar un elemento, leer su contenido y volver a colocar un elemento en un almacén. Por supuesto, el elemento también está en el almacén durante la lectura. Los protectores se expresan con variables compartidas. Y, por lo tanto, la novedad es que el patrón de unión ahora puede contener partes propagadas y simplificadas. Por lo tanto, en Scheme, la parte anterior a / se propaga y la parte posterior a / se elimina. El uso de Goal-Based es dividir el trabajo en muchas tareas y unir todos los resultados al final con el patrón de unión. Se ha implementado un sistema llamado "MiniJoin" para usar el resultado intermedio para resolver las otras tareas si es posible. Si no es posible, espera la solución de las otras tareas para resolverse a sí mismo.
Por lo tanto, la aplicación del patrón de unión concurrente ejecutada en paralelo en una arquitectura de múltiples núcleos no garantiza que la ejecución paralela genere conflictos. Para garantizar esto y un alto grado de paralelismo, se utiliza una memoria transaccional de software (STM) dentro de una estructura de datos concurrentes altamente ajustada basada en comparación e intercambio atómico (CAS). Esto permite ejecutar muchas operaciones concurrentes en paralelo en una arquitectura multinúcleo. Además, se utiliza una ejecución atómica para evitar el "falso conflicto" entre CAS y STM. [29]

Otros patrones de diseño similares

Join Pattern no es el único patrón para realizar multitareas pero es el único que permite la comunicación entre recursos, la sincronización y la unión de diferentes procesos.

Véase también

Referencias

Notas

  1. ^ Taral Dragon (25 de octubre de 2009). "Únete al cálculo".
  2. ^ Russo, Claudio V. (23 de octubre de 2008). "Join Patterns for Visual Basic". ACM SIGPLAN Notices . 43 (10): 10. doi :10.1145/1449955.1449770.
  3. ^ "C# paralelo".
  4. ^ Russo, Claudio V. (27 de octubre de 2008). "Join patterns for visual basic". ACM SIGPLAN Notices . 43 (10): 2. doi :10.1145/1449955.1449770.
  5. ^ Fournet, Cédric; Gonthier, Georges (2002). "El cálculo de unión: un lenguaje para la programación distribuida móvil". Applied Semantics . Apuntes de clase en informática. Vol. 2395. Springer. págs. 268–332. CiteSeerX 10.1.1.4.4788 . doi :10.1007/3-540-45699-6_6. ISBN  978-3-540-44044-4.
  6. ^ abcdef Russo, Claudio V. (27 de octubre de 2008). "Join patterns for visual basic". ACM SIGPLAN Notices . 43 (10): 53–72. doi :10.1145/1449955.1449770.
  7. ^ Russo, Claudio V. (23 de octubre de 2008). "Join Patterns for Visual Basic". Avisos SIGPLAN de ACM . 43 (10): 5. doi :10.1145/1449955.1449770.
  8. ^ Russo, Claudio V. (23 de octubre de 2008). "Join Patterns for Visual Basic". ACM SIGPLAN Notices . 43 (10): 18. doi :10.1145/1449955.1449770.
  9. ^ abc Maranget, Luc; Le Fessant, Fabrice (25 de septiembre de 2007). "Compilación de patrones de unión". Le Chesnay Francia.
  10. ^ Fournet, Cédric; Gonthier, Georges; Levy, Jean-Jacques; Maranget, Luc (1996). "Un cálculo de agentes móviles". CONCUR '96: Teoría de la concurrencia . Apuntes de conferencias sobre informática. vol. 1119. Le Chesnay: teoría de la concurrencia. págs. 406–421. doi :10.1007/3-540-61604-7_67. ISBN 978-3-540-61604-7.
  11. ^ Fournet, Cedric; Le Fessant, Fabrice; Maranget, Luc; Schmitt, A. (2003). "JoCaml: un lenguaje para programación distribuida y móvil concurrente". Programación funcional avanzada . Apuntes de clase en informática. Vol. 2638. págs. 129–158. doi :10.1007/978-3-540-44833-4_5. ISBN 978-3-540-40132-2.
  12. ^ Conchon, S.; Le Fessant, F. (1999). "Jocaml: Agentes móviles para Objective-Caml". Actas. Primer y tercer simposio internacional sobre aplicaciones de sistemas de agentes y agentes móviles . págs. 22–29. doi :10.1109/ASAMA.1999.805390. ISBN 0-7695-0342-X. Número de identificación  S2C14355301.
  13. ^ Odersky, Martin (septiembre de 2000). "Una visión general de las redes funcionales". Escuela de verano, Caminha, Portugal, septiembre de 2000. 2395 .
  14. ^ Odersky, Martin (2000). "Redes funcionales". Lenguajes y sistemas de programación . Apuntes de clase en informática. Vol. 1782. págs. 1–25. doi : 10.1007/3-540-46425-5_1 . ISBN. 978-3-540-67262-3.
  15. ^ Itzstein, GS; Kearney, D. (2001). "Join Java: una semántica de concurrencia alternativa para Java". Informe técnico ACRC-01-001, Universidad de Australia del Sur .
  16. ^ Benton, N.; Fournet, C. (junio de 2002). "Abstracciones de concurrencia modernas para C#". En Actas de la 16.ª Conferencia Europea sobre Programación Orientada a Objetos (ECOOP 2002), número 2374 en LNCS .
  17. ^ Benton, N.; Cardelli, L. (2004). Abstracciones de concurrencia modernas para C#. Transacciones ACM en lenguajes y sistemas de programación . Vol. 26.
  18. ^ Van Ham, Jurgen M.; Salvaneschi, Guido; Mezini, Mira; Noyé, Jacques (22 de abril de 2014). "JEScala: coordinación modular con eventos declarativos y uniones". Actas de la 13.ª conferencia internacional sobre modularidad . MODULARITY '14. Nueva York, NY, EE. UU.: Association for Computing Machinery. págs. 205–216. doi :10.1145/2577080.2577082. ISBN 978-1-4503-2772-5.
  19. ^ Singh, Satnam (6 de enero de 2007). "Combinadores de orden superior para patrones de unión utilizando STM". pág. 1.
  20. ^ ab Aaron, Turon; Russo, Claudio V. (27 de octubre de 2011). Patrones de unión escalables (PDF) . Nueva York: Association for Computing Machinery. p. 4. ISBN 978-1-4503-0940-0.
  21. ^ Aaron, Turon; Russo, Claudio V. (27 de octubre de 2011). Patrones de unión escalables (PDF) . Nueva York: Association for Computing Machinery. p. 1. ISBN 978-1-4503-0940-0.
  22. ^ ab Aaron, Turon; Russo, Claudio V. (27 de octubre de 2011). Patrones de unión escalables (PDF) . Nueva York: Association for Computing Machinery. p. 3. ISBN 978-1-4503-0940-0.
  23. ^ Aaron, Turon; Russo, Claudio V. (27 de octubre de 2011). Patrones de unión escalables (PDF) . Nueva York: Association for Computing Machinery. p. 2. ISBN 978-1-4503-0940-0.
  24. ^ abc Fournet, Cédric; Gonthier, Georges; Levy, Jean-Jacques; Maranget, Luc; Rémy, Didier (1996). "Un cálculo de agentes móviles". CONCUR '96: Teoría de la concurrencia . Apuntes de conferencias sobre informática. vol. 1119. Le Chesnay: teoría de la concurrencia. págs. 406–421. doi :10.1007/3-540-61604-7_67. ISBN 978-3-540-61604-7.
  25. ^ Maludzinski, Slawomir; Dobrowolski, Grzegorz (2007). "Ambiente del agente y conocimiento en cálculo de uniones distribuidas". Sistemas y aplicaciones multiagente V. Apuntes de clase en informática. Vol. 4696. págs. 298-300. doi :10.1007/978-3-540-75254-7_30. ISBN 978-3-540-75253-0.
  26. ^ Ma, Qin; Maranget, Luc (5 de abril de 2004). "Compiling Pattern Matching in Join-Patterns". CONCUR 2004 - Teoría de la concurrencia . Apuntes de clase en informática. Vol. 3170. INRIA. págs. 417–431. CiteSeerX 10.1.1.499.8443 . doi :10.1007/978-3-540-28644-8_27. ISBN .  978-3-540-22940-7.S2CID 9956643  .
  27. ^ abc Haller, Phillip; Van Cutsem, Tom (2008). "Implementación de uniones mediante coincidencia de patrones extensible". Modelos y lenguajes de coordinación . Apuntes de clase en informática. Vol. 5052. Lausana: Modelos y lenguajes de coordinación. págs. 135–152. CiteSeerX 10.1.1.210.1242 . doi :10.1007/978-3-540-68265-3_9. ISBN  978-3-540-68264-6.
  28. ^ abc Russo, Claudio V. (23 de octubre de 2008). "Join Patterns for Visual Basic". Avisos SIGPLAN de ACM . 43 (10): 53–72. doi :10.1145/1449955.1449770.
  29. ^ abc Sulzmann, Martin; SL Lam, Edmund. "Patrones de unión paralela con protecciones y propagación". Dinamarca.
  30. ^ Hopf, J.; von Itzstein, G.; Stewart, al. (2002). Hardware Join Java: Un lenguaje de alto nivel para el desarrollo de hardware reconfigurable. Hong Kong: IEEE. Archivado desde el original el 19 de febrero de 2013.
  31. ^ Plociniczak, Hubert; Eisenbach, Susan (2010). "JErlang: Erlang con uniones". Modelos y lenguajes de coordinación . Apuntes de clase en informática. Vol. 6116. Springer. págs. 61–75. Bibcode :2010LNCS.6116...61P. doi : 10.1007/978-3-642-13414-2_5 . ISBN 978-3-642-13413-5.
  32. ^ Liu, Yigong (2007–2009). "Join: biblioteca de coordinación y concurrencia de mensajes asincrónicos".
  33. ^ "Introducción a la polifonía C#".
  34. ^ "C# paralelo". Archivado desde el original el 26 de noviembre de 2013.
  35. ^ Hanus, Michael (enero de 2007). The Joins Concurrency Library. Vol. 4354. ISBN 978-3-540-69608-7.
  36. ^ "Comega".
  37. ^ Aaron, Turon; Russo, Claudio V. (27 de octubre de 2011). Patrones de unión escalables (PDF) . Nueva York: Association for Computing Machinery. ISBN 978-1-4503-0940-0.
  38. ^ Fournet, Cedric; Le Fessant, Fabrice; Maranget, Luc; Schmitt, Alan (2003). "JoCaml: un lenguaje para programación distribuida y móvil concurrente" (PDF) . Programación funcional avanzada . Apuntes de clase en informática. Springer-Verlag. págs. 129–158.
  39. ^ Hammond/Michaelson/Sun – Programación de sistemas reactivos en Hume
  40. ^ "Básico concurrente". Archivado desde el original el 25 de abril de 2015.
  41. ^ Russio, Claudio (2006). "La biblioteca de concurrencia de uniones". Aspectos prácticos de los lenguajes declarativos . Apuntes de clase en informática. Vol. 4354. Cambridge: Aspectos prácticos de los lenguajes declarativos. págs. 260–274. CiteSeerX 10.1.1.187.8792 . doi :10.1007/978-3-540-69611-7_17. ISBN .  978-3-540-69608-7.
  42. ^ "La biblioteca de concurrencia de uniones".
  43. ^ Haller, Phillip; Odersky, Martin (junio de 2007). "Actores que unifican hilos y eventos". Modelos y lenguajes de coordinación . Apuntes de clase en informática. Vol. 4467. Springer. págs. 171–190. doi :10.1007/978-3-540-72794-1_10. ISBN. 978-3-540-72793-4.
  44. ^ MONSIEUR, Geert (2010), Coordinación basada en patrones en composiciones de servicios basadas en procesos, Lovaina Bélgica: Katholiek Universiteit Leuven, p. 68
  45. ^ MONSIEUR, Geert (2010), Coordinación basada en patrones en composiciones de servicios basadas en procesos, Lovaina Bélgica: Katholiek Universiteit Leuven, p. 70

Enlaces externos