Sammanfogningsmönster
Paradigm | concurrent computing , distribuerad programmering |
---|---|
Utvecklare | INRIA Inria |
Hemsida | Inria Gå med |
Stora implementeringar | |
Gå med i Java , Polyphonic C #, Unified Parallel C , Cω , Joins library , Boost . | |
Influerad | |
Gå med i Calculus |
Join-patterns ger ett sätt att skriva samtidiga , parallella och distribuerade datorprogram genom att skicka meddelanden . Jämfört med användningen av trådar och lås, är detta en högnivåprogrammeringsmodell som använder kommunikationskonstruktionsmodell för att abstrahera komplexiteten i samtidig miljö och för att möjliggöra skalbarhet . Dess fokus ligger på utförandet av ett ackord mellan meddelanden som atomärt konsumeras från en grupp av kanaler.
Den här mallen är baserad på join-calculus och använder mönstermatchning . Konkret görs detta genom att tillåta kopplingsdefinitionen av flera funktioner och/eller kanaler genom att matcha samtidiga samtals- och meddelandemönster. Det är en typ av samtidighetsmönster eftersom det gör det enklare och mer flexibelt för dessa enheter att kommunicera och hantera det flertrådiga programmeringsparadigmet.
Beskrivning
Sammanfogningsmönstret (eller ett ackord i Cω ) är som en superpipeline med synkronisering och matchning. Faktum är att det här konceptet sammanfattas efter matchning och ansluter till en uppsättning meddelanden som är tillgängliga från olika meddelandeköer , och hanterar sedan dem alla samtidigt med en hanterare. Det kan representeras av nyckelorden när
man ska specificera den första kommunikationen som vi förväntade oss, med och
att gå med/para ihop andra kanaler och göra för
att köra vissa uppgifter med de olika insamlade meddelandena. Ett konstruerat sammanfogningsmönster tar vanligtvis denna form:
j . När ( a1 ). Och ( a2 ). ... . Och ( an ). Gör ( d )
Argument al av When(al)
kan vara en synkron eller asynkron kanal eller en grupp av asynkrona kanaler. Varje efterföljande argument ai till And(ai)
(för i > 1
) måste vara en asynkron kanal.
Närmare bestämt, när ett meddelande matchar en kedja av länkade mönster får dess hanterare att köras (i en ny tråd om det är i asynkront sammanhang) annars köas meddelandet tills ett av dess mönster är aktiverat; om det finns flera matchningar väljs ett ospecificerat mönster. Till skillnad från en händelsehanterare, som servar en av flera alternativa händelser åt gången, tillsammans med alla andra hanterare för den händelsen, väntar ett joinmönster på en konjunktion av kanaler och tävlar om exekvering med vilket annat aktiverat mönster som helst.
Join-pattern definieras av en uppsättning pi-calculus-kanaler x som stöder två olika operationer, sändning och mottagning, vi behöver två join-kalkylnamn för att implementera det: ett kanalnamn x för att skicka (ett meddelande) och ett funktionsnamn x för att ta emot ett värde (en begäran). Meningen med joindefinitionen är att ett anrop till x()
returnerar ett värde som skickades på en kanal x<>
. Varje gång funktioner är samtidigt, utlöser returprocessen och synkroniseras med andra kopplingar.
J ::= //anslutningsmönster | x < y > //meddelande skicka mönster | x ( y ) //funktionsanropsmönster | J | JBIS //synkronisering
Ur en klients perspektiv deklarerar en kanal bara en metod med samma namn och signatur. Klienten postar ett meddelande eller utfärdar en begäran genom att anropa kanalen som en metod. En fortsättningsmetod måste vänta tills/om inte en enda begäran eller meddelande har kommit till var och en av kanalerna efter fortsättningens When-klausul. Om fortsättningen kommer att köras, urköas (förbrukas) argumenten för varje kanalanrop och överförs (atomiskt) till fortsättningens parametrar.
I de flesta fall är ordningen på synkrona samtal inte garanterad av prestandaskäl. Slutligen, under matchen kunde meddelanden som finns i kön stjälas av någon mellanliggande tråd; faktiskt, den väckta tråden kan behöva vänta igen.
Historia
π-kalkyl – 1992
π-kalkylen tillhör familjen processkalkyler , tillåter matematiska formalismer för att beskriva och analysera egenskaper hos samtidig beräkning genom att använda kanalnamn som kommuniceras längs kanalerna själva, och på detta sätt kan den beskriva samtidiga beräkningar vars nätverkskonfiguration kan ändras under beräkningen.
Join-Calculus – 1993
Sammanfogningsmönster dök först upp i Fournet och Gonthiers grundläggande join-kalkyl, en asynkron processalgebra designad för effektiv implementering i en distribuerad miljö. Den sammanfogade kalkylen är en processkalkyl som är lika uttrycksfull som den fullständiga π-kalkylen . Det utvecklades för att ge en formell grund för utformningen av distribuerade programmeringsspråk och undviker därför avsiktligt kommunikationskonstruktioner som finns i andra processkalkyler, såsom möteskommunikation .
Distribuerad Join-Calculus – 1996
Join-Calculus är både en namnberäkning och ett kärnspråk för samtidig och distribuerad programmering. Det är därför Distributed Join-Calculus baserad på Join-Calculus med distribuerad programmering skapades 1996. Detta arbete använder de mobila agenterna där agenter inte bara är program utan kärnbilder av pågående processer med sina kommunikationsmöjligheter.
JoCaml, Funnel och Join Java – 2000
JoCaml och Funnel är funktionella språk som stöder deklarativa sammanfogningsmönster. De presenterar idéerna för att direkt implementera en processkalkyl i en funktionell miljö.
En annan tillägg till (icke-generisk) Java, JoinJava , föreslogs oberoende av von Itzstein och Kearney.
Polyfonisk C# – 2002
Cardelli, Benton och Fournet föreslog en objektorienterad version av sammanfogningsmönster för C# som kallas Polyphonic C# .
Cω – 2003
Cω är anpassning av join-calculus till en objektorienterad inställning. Denna variant av Polyphonic C# inkluderades i den offentliga utgåvan av Cω (aka Comega) 2004.
Scala går med – 2007
Scala Joins är ett bibliotek för att använda Join-Pattern med Scala i samband med utvidgbar mönstermatchning för att integrera sammanfogningar i ett befintligt aktörsbaserat ramverk för samtidighet.
JErlang – 2009
Erlang är ett språk som naturligt stöder det samtidiga, realtids- och distribuerade paradigmet. Samtidighet mellan processer var komplex, det är därför som projektet bygger ett nytt språk, JErlang ( J står för Join ) med hjälp av Join-kalkylen.
Join-mönster i klassisk programmeringslitteratur
"Join-mönster kan användas för att enkelt koda relaterade samtidighetsidiom som skådespelare och aktiva objekt."
klass SymmetricBarrier { offentlig skrivskyddad Synchronous . Channel Arrive ; public SymmetricBarrier ( int n ) { // Skapa j och init-kanaler (elided) var pat = j . När ( anländer ); för ( int i = 1 ; i < n ; i ++) pat = pat . Och ( Anländer ); klappa . Gör (() => { }); } }
0
var j = Gå med . Skapa (); Synkron . Kanal [] hungrig ; Asynkron . Kanal [] ätpinne ; j . Init ( ut hungrig , n ); j . Init ( ut ätpinne , n ); for ( int i = ; i < n ; i ++) { var left = ätpinne [ i ]; var höger = ätpinne [( i + 1 ) % n ]; j . När ( hungrig [ i ]). Och ( vänster ). Och ( höger ). Gör (() => { äta (); vänster (); höger (); // byt ut ätpinnar }); }
class Lock { public readonly Synchronous . Channel Acquire ; publik skrivskyddad Asynkron . Kanalsläpp ; _ public Lock () { // Skapa j och init-kanaler (elided) j . När ( Förvärva ). Och ( Släpp ). Gör (() => { }); Släpp (); // initialt gratis } }
class Buffer < T > { public readonly Asynchronous . Kanal < T > Put ; offentlig skrivskyddad Synkron < T >. Channel Get ; public Buffer () { Join j = Join . Skapa (); // allokera ett Join-objekt j . Init ( ut Put ); // binda dess kanaler j . Init ( ut Get ); j . När ( Hämta ). Och ( Sätt ). Gör // registrera ackord ( t => { return t ; }); } }
class ReaderWriterLock { privat skrivskyddad Asynkron . Kanal inaktiv ; privat skrivskyddad Asynkron . Kanal < int > delad ; offentlig skrivskyddad Synkron . Kanal AcqR , AcqW , RelR , RelW ; public ReaderWriterLock () { // Skapa j och init-kanaler (elided) j . När ( AcqR ). Och ( tomgång ). Gör (() => delad ( 1 )); j . När ( AcqR ). Och ( delad ). Gör ( n => delad ( n + 1 )); j . När ( RelR ). Och ( delad ). Gör ( n => { if ( n == 1 ) { tomgång (); } else { shared ( n - 1 ); } }); j . När ( AcqW ). Och ( tomgång ). Gör (() => { }); j . När ( RelW ). Gör (() => tomgång ()); tomgång (); // initialt gratis } }
0
class Semaphore { public readonly Synchronous . Channel Acquire ; publik skrivskyddad Asynkron . Kanalsläpp ; _ public Semaphore ( int n ) { // Skapa j och init-kanaler (elided) j . När ( Förvärva ). Och ( Släpp ). Gör (() => { }); för (; n > ; n --) Släpp (); // initialt n gratis } }
Grundläggande egenskaper och begrepp
- Join-calculus : Den första uppenbarelsen av Join-mönstret kommer ut med denna processkalkyl.
- Meddelandeöverföring : Join-pattern fungerar med ett meddelandeöverföringssystem av parallella skäl.
- Kanal : Kanaler används för att synkronisera och skicka meddelanden mellan trådar som körs samtidigt. I allmänhet kan en kanal vara involverad i mer än ett kopplingsmönster, varje mönster definierar en annan fortsättning som kan köras när kanalen anropas.
- Synkron : Sammanfogningsmönstret kan använda en synkron kanal som returnerar ett resultat. Fortsättningen av ett synkront mönster löper i den synkrona avsändarens tråd.
- Asynkron : Den kan också använda en asynkron kanal som inte returnerar något resultat utan tar argument. Fortsättningen av ett asynkront mönster löper i en nyligen skapad tråd. Ett kopplingsmönster kan vara rent asynkront, förutsatt att dess fortsättning är en subrutin och dess When-sats endast listar asynkrona kanaler.
- Kombinera synkron och asynkron: Att slå samman deklarationerna av synkron och asynkron buffert skulle ge en modul som stöder de två kommunikationstyperna av konsumenter.
- Schemaläggare : Det finns en schemaläggning mellan sammanfogningsmönster (t.ex. en schemaläggare av runda, schemaläggare för första matchen).
- Designmönster : Sammanfogningsmönstret är först och främst ett beteendemönster och ett samtidighetsmönster.
- Samtidig programmering : Det körs samtidigt.
- Mönstermatchning : Sammanfogningsmönstret fungerar med matchningsuppgifter.
- Parallell programmering : Den utför uppgifter parallellt.
- Distribuerad programmering : Jobb kan spridas på olika agenter och miljöer med detta mönster.
- Mjukvarutransaktionsminne : Mjukvarutransaktionsminne (STM) är en av de möjliga implementeringarna för kommunikation mellan gemensamma.
- Överlappande : Mönstret kan tillåta mönster som deklareras på överlappande uppsättningar av kanaler.
Applikationsdomän
Mobilagent
En mobil agent är en autonom mjukvaruagent med en viss social förmåga och viktigast av allt, mobilitet. Den består av datorprogram och data som kan flyttas mellan olika datorer automatiskt medan de fortsätter att köra dem.
De mobila agenterna kan användas för att matcha samtidighet och distribution om man använder Join-kalkylen. Det är därför ett nytt koncept som heter "distributed Join-calculus" skapades; det är en förlängning av Join-calculus med platser och primitiver för att beskriva rörligheten. Denna innovation använder agenter som löpande processer med sina kommunikationsmöjligheter för att möjliggöra en idé om plats, vilket är en fysisk plats som uttrycker agentens faktiska position. Tack vare Join-calculus kan en plats flyttas atomärt till en annan plats.
En agents processer specificeras som en uppsättning som definierar dess funktionalitet inklusive asynkron emission av ett meddelande, migrering till annan plats. Följaktligen är platser organiserade i ett träd för att representera agentens rörelse lättare. Med denna representation är en fördel med denna lösning möjligheten att skapa en enkel modell av misslyckande. Vanligtvis orsakar en krasch av en fysisk plats ett permanent fel på alla dess platser. Men med join-kalkylen kan ett problem med en plats upptäckas på vilken annan plats som helst, vilket möjliggör felåterställning.
Så Join-kalkylen är kärnan i ett distribuerat programmeringsspråk. I synnerhet är den operativa semantiken lätt implementerbar i en distribuerad miljö med misslyckanden. Så den distribuerade join-kalkylen behandlar kanalnamn och platsnamn som förstaklassvärden med lexikal omfattning. En plats styr sina egna rörelser och kan bara flytta mot en plats vars namn den har fått. Detta ger en god grund för statisk analys och säker mobilitet. Detta är komplett för att uttrycka distribuerade konfigurationer. I frånvaro av misslyckanden är exekveringen av processer dock oberoende av distribution. Denna platstransparens är avgörande för utformningen av mobilagenter och till stor hjälp för att kontrollera deras egenskaper.
Under 2007 har en utökning av den grundläggande sammanfogningskalkylen med metoder som gör agenter proaktiva kommit ut. Agenterna kan observera en miljö som delas mellan dem. Med denna miljö är det möjligt att definiera delade variabler med alla agenter (t.ex. en namntjänst för att upptäcka agenter sinsemellan).
Kompilering
Join-språk är byggda ovanpå Join-calculus som är ett kärnspråk. Så alla kalkyler analyseras med asynkrona processer och sammanfogningsmönstret ger en modell för att synkronisera resultatet. För att göra detta finns det två kompilatorer:
- Join Compiler: En kompilator av ett språk som heter "join langage". Det här språket har endast skapats för sammanfogningskalkylen
- Jocaml Compiler : En kompilator av en förlängning av Objectif Caml skapad för att använda join-kalkylen.
Denna två kompilator fungerar med samma system, en automat.
låt A(n) | B() = P(n) och A(n) | C() = Q(n);;
Det representerar konsumtionen av meddelanden som kommer fram till en färdig kopplingsmodell. Varje tillstånd är ett möjligen steg för kodexekveringen och varje övergång är mottagningen av ett meddelande att växla mellan två steg. Och så när alla meddelanden är tagna, exekverar kompilatorn body join-koden som motsvarar den färdiga modellkopplingen.
Så i join-kalkylen är de grundläggande värdena namnen som i exemplet är A,B eller C. Så de två kompilatorerna representerar dessa värden på två sätt. Gå med i kompilatorn använd en vektor med två platser, den första till namnet och den andra till en kö av väntande meddelanden. Jocaml använder namn som en pekare på definitioner. Denna definition lagrar de andras pekare för de andras namn med ett statusfält och en matchande datumstruktur per meddelande. Den grundläggande skillnaden är när bevakningsprocessen exekveras, för den första kontrollerades om alla namn är de väntande meddelandena klara medan den andra endast använder en variabel och åtkomst till de andra för att veta om modellen är färdig.
Ny forskning beskriver sammanställningsschemat som en kombination av två grundläggande steg: sändning och vidarebefordran. Utformningen och korrektheten hos avsändaren härrör i huvudsak från mönstermatchningsteori, medan det är en naturlig idé att infoga ett internt vidarebefordransteg i kommunikationen, som intuitivt inte ändrar processbeteende. De gjorde observationen att det värt att observera är en direkt implementering av utökad kopplingsmönstermatchning på körtidsnivå skulle avsevärt komplicera hanteringen av meddelandeköer, som sedan skulle behöva skannas för att söka efter matchande meddelanden innan de konsumeras.
Implementeringar och bibliotek
Det finns många användningsområden för Join-mönster med olika språk. Vissa språk använder join-mönster som bas för sina implementeringar, till exempel Polyphonic C# eller MC# , men andra språk integrerar join-mönster av ett bibliotek som Scala Joins för Scala eller Joins-biblioteket för VB. Dessutom används join-mönstret genom vissa språk som Scheme för att uppgradera join-mönstret.
JErlang | CB | Går med i biblioteket | Polyfonisk C# | Parallell C# | Cω | Scala ansluter | F# | Schema | Gå med i Java | Hume | JoCaml | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Mönster som matchar | Ja | Ja | Ja | Ja | Ja | Ja | Ja | Ja | Ja | Ja | Ja | Ja |
Schemaläggare mellan sammanfogningsmönster | Ja: första matchen | Ja : first/round robin | Ja | Ja | Ja | Ja | Ja | Ja | Nej | Ja: slumpmässigt | Ja : first/round robin | Ja: slumpmässigt |
Generika | Ja | — | Ja | Nej | — | Nej | Ja | Ja | Nej | Nej | Nej | Nej |
Åsidosättande | Nej | Ja | — | — | — | Ja | Ja | Ja | Nej | Ja | Nej | Nej |
Gå med i Java
Join Java är ett språk baserat på Java-programmeringsspråket som tillåter användning av join-kalkylen. Den introducerar tre nya språkkonstruktioner:
- Join-metoder definieras av två eller flera Join-fragment. En Join-metod kommer att köras när alla fragment av Join-mönstret har anropats. Om returtypen är en standard Java-typ kommer det inledande fragmentet att blockera anroparen tills Join-mönstret är komplett och metoden har exekveras. Om returtypen är av typen signal kommer det inledande fragmentet att återvända omedelbart. Alla efterföljande fragment är asynkrona så blockerar inte den som ringer.
Exempel:
class JoinExample { int fragment1 () & fragment2 ( int x ) { // Returnerar värdet på x till anroparen av fragment1 returnerar x ; } }
- Asynkrona metoder definieras genom att använda signalreturtypen. Detta har samma egenskaper som void-typen förutom att metoden kommer tillbaka omedelbart. När en asynkron metod anropas skapas en ny tråd för att utföra metoden.
Exempel:
class ThreadExample { signal thread ( SomeObject x ) { // Denna kod kommer att köras i en ny tråd } }
- Beställa modifierare
Join-fragment kan upprepas i flera Join-mönster, så det kan finnas ett fall när flera Join-mönster fullbordas när ett fragment anropas. Ett sådant fall kan inträffa i exemplet nedan om B(), C() och D() sedan A() anropas. Det sista A()-fragmentet fullbordar tre av mönstren så det finns tre möjliga metoder som kan anropas. Den ordnade klassmodifieraren används här för att bestämma vilken Join-metod som ska anropas. Standardinställningen och när du använder den oordnade klassmodifieraren är att välja en av metoderna slumpmässigt. Med den beställda modifieraren prioriteras metoderna enligt den ordning de deklareras.
Exempel:
class ordered SimpleJoinPattern { void A () & B () { } void A () & C () { } void A () & D () { } signal D () & E () { } }
Det närmast besläktade språket är Polyphonic C# .
JErlang
I Erlang är kodning inte enkel att synkronisera mellan flera processer. Det är därför JErlang, en förlängning av Erlang skapades, The J is for Join. För att övervinna denna begränsning implementerades JErlang, en Join-Calculus- inspirerad tillägg till Erlang . Funktionerna i detta språk är:
- Joins tillåter första Match-semantik och möjligheten att ha flera mönster med en bevarande av meddelandenas ordning.
operation () -> ta emot { ok , summa } och { val , X } och { val , Y } -> { summa , X + Y }; { ok , mult } och { val , X } och { val , Y } -> { mult , X * Y }; { ok , sub } och { val , X } och { val , Y } -> { sub , X - Y }; slutet slut
- Guards tillhandahåller ytterligare filtrering som inte uttrycks i form av mönster. Begränsat antal uttryck utan biverkningar
ta emot { Transaction , M } och { limit , Lower , Upper } när ( Lower <= M och M <= Upper ) -> commit_transaction ( M , Transaction ) slut
- Med icke-linjära mönster kan meddelanden matcha flera kopplingar
motta { get , X } och { set , X } -> { found , 2 , X } end ... ta emot { Pin , id } och { auth , Pin } och { commit , Id } -> perform_transaction ( Pin , Id } ) slut
- spridning gör det möjligt att kopiera korrekta meddelanden istället för att ta bort dem.
ta emot prop ({ session , Id }) och { act , Action , Id } -> perform_action ( Action , Id ); { session , Id } and { logout , Id } -> logout_user ( Id ) end ... motta { Pin , id } och { auth , Pin } och { commit , Id } -> perform_transaction ( Pin , Id ) end
- Synkrona samtal
motta { acceptera , Pid1 } och { asynkront , Värde } och { acceptera , Pid2 } -> Pid1 ! { ok , värde } , Pid2 ! { ok , värde } slut
C++
Yigong Liu har skrivit några klasser för sammanfogningsmönstret inklusive alla användbara verktyg som asynkrona och synkrona kanaler, ackord , etc. Det är integrerat i projektet Boost c++ .
mall < typnamn V > class buffer : public joint { public : async < V > put ; synch < V , void > get ; buffer () { ackord ( get , put , & buffer :: chord_body ); } V chord_body ( void_t g , V p ) { return p ; } };
Det här exemplet visar oss en trådsäker buffert och meddelandekö med de grundläggande operationerna put and get.
C#
Polyfonisk C#
Polyphonic C# är en förlängning av programmeringsspråket C#. Den introducerar en ny samtidighetsmodell med synkrona och asynkrona (som återför kontroll till den som ringer) metoder och ackord (även kända som 'synkroniseringsmönster' eller 'join-mönster').
public class Buffer { public String get () & public async put ( String s ) { return s ; } }
Detta är ett enkelt buffertexempel.
MC#
MC# -språket är en anpassning av det polyfoniska C#-språket för fallet med samtidiga distribuerade beräkningar.
offentlig hanterare Get2 long () & channel c1 ( long x ) & channel c2 ( long y ) { return ( x + y ); }
Det här exemplet visar användningen av ackord som ett synkroniseringsverktyg.
Parallell C#
Parallel C# är baserat på Polyphonic C# och de lägger till några nya begrepp som lösöremetoder, högordningsfunktioner.
använder System ; class Test13 { int Receive () & async Send ( int x ) { return x * x ; } public static void Main ( sträng [] args ) { Test13 t = new Test13 (); t . Skicka ( 2 ); Konsol . WriteLine ( t . Receive ()); } }
Det här exemplet visar hur man använder joins.
Cω
Cω lägger till nya språkfunktioner för att stödja samtidig programmering (baserat på det tidigare Polyphonic C# ) . Joins Concurrency Library för C# och andra .NET-språk härrör från detta projekt.
Skalbara kopplingsmönster
Det är ett lättanvänt deklarativt och skalbart kopplingsmönsterbibliotek. I motsats till Russo-biblioteket har det inget globalt lås. Faktum är att det fungerar med ett jämför-och-byt CAS och Atomic meddelandesystem. Biblioteket använder tre förbättringar för sammanfogningsmönstret:
- Stjäla meddelande för oanvända resurser (tillåter pråm);
- Lazy queue sparar både på allokering och potentiellt på interprocessorkommunikation genom att undvika allokering eller kö med en optimistisk snabbväg;
- En status "WOKEN" : säkerställer att en blockerad synkron uppringare väcks endast en gång.
JoCaml
JoCaml är det första språket där join-mönstret implementerades. Faktum är att i början kompilerades alla olika implementeringar med JoCaml-kompilatorn. JoCaml-språket är en förlängning av OCaml -språket. Den utökar OCaml med stöd för samtidighet och synkronisering, distribuerad körning av program och dynamisk omlokalisering av aktiva programfragment under körning.
0
0
0
0
0
typmynt = Nickel | _ Dime och dryck = Kaffe | Te och knappar = BCaffe | BTea | BCavbryt ;; (* def definierar en Join-pattern set-sats * "&" på vänster sida av = betyder join (kanalsynkronism) * "&" på höger sida betyder: parallell process * synchronous_reply :== "reply" [x] "till" kanalnamn * synkrona kanaler har funktionsliknande typer (`a -> `b) * asynkrona kanaler har typer (`a Join.chan) * endast det sista uttrycket i ett mönster-rhs-uttryck kan vara ett asynkront meddelande * 0 i en asynkron meddelandeposition betyder STOPP ("inget skickat meddelande" i CSP-terminologi) *) def put ( s ) = print_endline s ; (* STOPP *) ;; (* put: string Join.chan *) def serve ( drink ) = matcha drink med Coffee -> put ( "Cofee" ) | Tea -> put ( "Te" ) ;; (* servera: drinks Join.chan *) def återbetalning ( v ) = låt s = Printf . sprintf " Återbetalning %d" v input ( s ) ;; (* återbetalning: int Join.chan *) let new_vending serve refund = let vend ( cost : int ) ( credit : int ) = if credit >= cost then ( true , credit - cost ) else ( false , credit ) in def coin ( Nickel ) & värde ( v ) = värde ( v + 5 ) & svar ( ) på mynt eller mynt ( Dime ) & värde ( v ) = värde ( v + 10 ) & svar ( ) på mynt eller knapp ( BCoffe ) & värde ( v ) = låt bör_serva , resterande = sälj 10 v in ( om borde_servera , servera ( kaffe ) annat ( * STOPP * ) ) & värde ( resterande ) & svara ( ) på knapp eller knapp ( BTea ) & värde ( v ) = låt bör_serva , rest = sälj 5 v in ( om should_serve then serve ( Tea ) else (* STOP *) ) & value ( restant ) & svara ( ) till knapp eller knapp ( BCancel ) & värde ( v ) = återbetalning ( v ) ) & värde ( ) & svara () på knappen i spawn värde ( ) ; mynt , knapp (* mynt, knapp: int -> enhet *) ;; (* new_vending: drink Join.chan -> int Join.chan -> (int->unit)*(int->unit) *) låt ccoin , cbutton = new_vending servera återbetalning i ccoin ( Nickel ); mynt ( nickel ); mynt ( Dime ); Unix . sömn ( 1 ); cknapp ( BCoffe ); Unix . sömn ( 1 ); cknapp ( BTea ); Unix . sömn ( 1 ); cknapp ( BCavbryt ); Unix . sleep ( 1 ) (* låt det sista meddelandet dyka upp *) ;;
ger
Kaffe Te Återbetalning 5
Hume
Hume är ett strikt , starkt typat funktionsspråk för plattformar med begränsade resurser, med samtidighet baserad på asynkron meddelandeöverföring, dataflödesprogrammering och en Haskell -liknande syntax.
Hume tillhandahåller inte synkrona meddelanden.
Den omsluter ett sammanfogningsmönster med en gemensam kanal som en låda , listar alla kanaler i en in- tupel och specificerar alla möjliga utgångar i en ut- tuppel.
Varje kopplingsmönster i uppsättningen måste överensstämma med boxingångstypen som specificerar ett '*' för icke obligatoriska kanaler, vilket ger ett uttryck vars typ överensstämmer med utmatningstuppeln, markerar "*" de icke matade utgångarna.
En trådklausul anger
- en tupel av motsvarande ingångsursprung eller källor och valfritt startvärden
- en tupel av utgångsdestinationer, som är kanaler eller sänkor (stdout, ..).
En ruta kan ange undantagshanterare med uttryck som överensstämmer med utdatatupeln.
0
0
data Mynt = Nickel | Dime ; data Drycker = Kaffe | Te ; dataknappar = BCaffe | _ BTea | BCavbryt ; typ Int = int 32 ; typ String = sträng ; visa u = u som sträng ; box kaffe in ( mynt :: Mynt , knapp :: Knappar , värde :: Int ) -- ingångskanaler ut ( drink_outp :: String , value ' :: Int , refund_outp :: String ) -- namngivna utgångar matchar -- * jokertecken för ofyllda utgångar och oförbrukade ingångar ( Nickel , * , v ) -> ( * , v + 5 , * ) | ( Dime , * , v ) -> ( * , v + 10 , * ) | ( * , BCoffe , v ) -> vend Kaffe 10 v | ( * , BTea , v ) -> vend Tea 5 v | ( * , BCancel , v ) -> let refund u = "Återbetalning " ++ visa u ++ " \n " i ( * , , återbetalning v ) ; vend drink cost credit = if credit >= cost then ( servera drink , credit - cost , * ) else ( * , credit , * ); servera drink = kaffedryck -> "Kaffe \ n " Te -> " Te \ n " ; boxkontroll in ( c :: char ) ut ( mynt :: Mynt , knapp :: Knappar ) matcha 'n' - > ( Nickel , * ) | 'd' -> ( Dime , * ) | 'c' -> ( * , BCoffe ) | 't' -> ( * , BTea ) | 'x' -> ( * , BCancel ) | _ -> ( * , * ) ; streama console_outp till "std_out" ; streama console_inp från "std_in" ; -- dataflödesledningar kafé -- ingångar ( kanalursprung ) ( kontroll . mynt , kontroll . knapp , kaffe . värde ' initialt ) -- utdata destinationer ( console_outp , coffee . value , console_outp ) ; trådkontroll ( console_inp ) ( kaffe . mynt , kaffe . knapp ) ; _
Visual Basic
Concurrent Basic – CB
En förlängning av Visual Basic 9.0 med asynkrona samtidighetskonstruktioner, kallad Concurrent Basic (för kort CB), erbjuder sammanfogningsmönstren. CB (bygger på tidigare arbete på Polyphonic C#, Cω och Joins Library) antar en enkel händelseliknande syntax som är bekant för VB-programmerare, låter en deklarera generiska samtidighetsabstraktioner och ger mer naturligt stöd för arv, vilket gör det möjligt för en underklass att utöka uppsättningen av mönster. CB-klassen kan deklarera metod för att exekvera när kommunikation har skett på en viss uppsättning lokala kanaler asynkrona och synkrona, vilket bildar ett sammanfogningsmönster.
Modul Buffer Public Asynchronous Put ( ByVal s As String ) Public Synchronous Take () As String Private Function CaseTakeAndPut ( ByVal s As String ) As String _ When Take , Put Return s End Function End Module
Det här exemplet visar alla nya nyckelord som används av Concurrent Basic: Asynkron, Synkron och När.
Går med i biblioteket (C# och VB)
Det här biblioteket är en abstraktion på hög nivå av Join-mönstret med hjälp av objekt och generika. Kanaler är speciella delegatvärden från något vanligt Join-objekt (istället för metoder).
class Buffer { offentlig skrivskyddad Asynkron . Kanal < sträng > Put ; offentlig skrivskyddad Synkron < sträng >. Channel Get ; public Buffer () { Join join = Join . Skapa (); gå med . Initiera ( ut Putta ); gå med . Initiera ( ut Get ); gå med . När ( Hämta ). Och ( Sätt ). Gör ( delegera ( sträng s ) { return s ; }); } }
Det här exemplet visar hur man använder metoder för Join-objektet.
Scala
Det finns ett bibliotek i Scala som heter "Scala Joins" Scala Joins för att använda Join-Pattern, det föreslår att man använder mönstermatchning Pattern Matching som ett verktyg för att skapa modeller av sammanfogningar. Du kan hitta exempel på användningen av sammanfogningsmönstret i scala här: Förbindningsdefinitioner i Scala .
Mönstermatchningsfaciliteterna för detta språk har generaliserats för att möjliggöra representationsoberoende för objekt som används i mönstermatchning. Så nu är det möjligt att använda en ny typ av abstraktion i bibliotek. Fördelen med sammanfogningsmönster är att de tillåter en deklarativ specifikation av synkroniseringen mellan olika trådar. Ofta motsvarar kopplingsmönstren nära en finita tillståndsmaskin som specificerar objektets giltiga tillstånd.
I Scala är det möjligt att lösa många problem med mönstermatchning och Scala Joins, till exempel Reader-Writer.
0
0
0
0 class ReaderWriterLock förlänger Joins { private val Sharing = new AsyncEvent [ Int ] val Exclusive , ReleaseExclusive = new NullarySyncEvent val Shared , ReleaseShared = new NullarySyncEvent join { case Exclusive () & Sharing ( ) => Exklusivt svarsfall ReleaseExclusive ( ) => { Sharing ( ); ReleaseExklusivt svar } fall Delad () & Delning ( n ) => { Delning ( n + 1 ); Delat svar } fall ReleaseShared () & Sharing ( 1 ) => { Sharing ( ) ; ReleaseShared svar } fall ReleaseShared () & Sharing ( n ) => { Sharing ( n - 1 ); Släpp delat svar } } Delning ( ) }
Med en klass deklarerar vi händelser i vanliga fält. Så det är möjligt att använda Join-konstruktionen för att möjliggöra en mönstermatchning via en lista med falldeklarationer. Den listan representerar av => med på varje sida en del av deklarationen. Den vänstra sidan är en modell av sammanfogningsmönster för att visa kombinationen av händelser asynkrona och synkrona och den högra sidan är kroppen av sammanfogningen som exekveras med att sammanfogningsmodellen är klar.
I Scala är det också möjligt att använda Scalas skådespelarbibliotek med sammanfogningsmönstret. Till exempel, en ogränsad buffert:
val Put = new Join1 [ Int ] val Get = new Join class Buffert extends JoinActor { def act () { receive { case Get () & Put ( x ) => Få svar x } } }
Aktörsbaserad concurrency stöds av ett bibliotek och vi tillhandahåller join-mönster som en biblioteksförlängning också, så det finns möjlighet att kombinera join-mönster med den händelsedrivna concurrency-modellen som erbjuds av aktörer. Som du ser i exemplet är det samma sätt att använda kopplingsmönster med aktörer, det är bara att göra det en lista över falldeklarationer i metoden som får för att visa när modellen är färdig.
Praktiskt taget samma verktyg finns tillgängliga i F# för att använda sammanfogningsmönster
Scala Join och Chymyst är nyare implementeringar av Join Pattern, som förbättrar Dr. Philipp Hallers Scala Joins .
Haskell
Join Language är en implementering av Join Pattern i Haskell.
Schema
Join Patterns tillåter en ny programmeringstyp speciellt för flerkärniga arkitekturer som är tillgängliga i många programmeringssituationer med en hög abstraktionsnivå. Detta är baserat på Guards and Propagation. Så ett exempel på denna innovation har implementerats i Scheme.
Guards är viktigt för att garantera att endast data med en matchande nyckel uppdateras/hämtas. Förökning kan avbryta en vara, läser dess innehåll och sätter tillbaka en vara i en butik. Självklart finns varan även i butiken under läsningen. Vakterna uttrycks med delade variabler. Och så nyheten är att fogmönsterburken innehåller nu förökade och förenklade delar. Så i Schema förökas delen före / och delen efter / tas bort. Användningen av den målbaserade är att dela upp arbetet i många uppgifter och sammanfogar alla resultat i slutet med sammanfogningsmönstret. Ett system som heter "MiniJoin" har implementerat för att använda mellanresultatet för att lösa de andra uppgifterna om det är möjligt. Om det inte är möjligt väntar den på att andras uppgifter löser sig själv. Så den samtidiga kopplingsmönsterapplikationen som körs parallellt på en flerkärnig arkitektur garanterar inte att parallell exekvering leder till konflikter. För att garantera detta och en hög grad av parallellitet, används ett Software Transactional Memory (STM) inom en högt avstämd samtidig datastruktur baserad på atomic compare-and-swap (CAS). Detta gör det möjligt att köra många samtidiga operationer parallellt på flerkärnig arkitektur. Dessutom används en atomavrättning för att förhindra den "falska konflikten" mellan CAS och STM.
Andra liknande designmönster
Join Pattern är inte det enda mönstret för att utföra multitasks men det är det enda som tillåter kommunikation mellan resurser, synkronisering och sammanfogning av olika processer.
- Sekvensmönster : består av att vänta på att en uppgift har slutförts för att byta till en annan (den klassiska implementeringen).
- Dela mönster ( parallelldelning ): utför flera uppgifter parallellt samtidigt (t.ex. Map reduce ).
Se även
- Gå med i Java – Gå med i Java är ett programmeringsspråk som utökar det vanliga programmeringsspråket för Java
- Joins (samtidighetsbibliotek) – Joins är ett asynkront samtidig beräknings-API från Microsoft Research för .NET Framework.
- Join-calculus – Join-calculus utvecklades för att ge en formell grund för utformningen av distribuerade programmeringsspråk.
- Cédric, Fournet; Luc, Maranget (2006-08-15). "Språket Join-Calculus" . Institut National de Recherche en Informatique et Automatique . Hämtad 2012-10-09 .
- "Gå med i Calculus" . Cunningham & Cunningham, Inc. 25 oktober 2009 . Hämtad 2012-10-09 .
- Fournet, Cédric; Gonthier, Georges; Levy, Jean-Jacques; Maranget, Luc (1996). CONCUR '96: Concurrency Theory . Föreläsningsanteckningar i datavetenskap. Vol. 1119. Le Chesnay: Concurrency Theory. s. 406–421. doi : 10.1007/3-540-61604-7_67 . ISBN 978-3-540-61604-7 .
- Maludzinski, Slawomir; Dobrowolski, Grzegorz (2007). Agentmiljö och kunskap i Distributed Join Calculus . Föreläsningsanteckningar i datavetenskap . Vol. 4696. s. 298–300. doi : 10.1007/978-3-540-75254-7_30 . ISBN 978-3-540-75253-0 .
- Russio, Claudio (2007). "The Joins Concurrency Library". Praktiska aspekter av deklarativa språk . Föreläsningsanteckningar i datavetenskap. Vol. 4354. Cambridge: Praktiska aspekter av deklarativa språk. s. 260–274. CiteSeerX 10.1.1.187.8792 . doi : 10.1007/978-3-540-69611-7_17 . ISBN 978-3-540-69608-7 .
-
Maranget, Luc; Le Fessant, Fabrice (25 september 2007). "Kompilera sammanfogningsmönster" . Le Chesnay Frankrike.
{{ citera journal }}
: Citera journal kräver|journal=
( hjälp ) - Haller, Philip; Van Cutsem, Tom (2008). Samordningsmodeller och språk . Föreläsningsanteckningar i datavetenskap. Vol. 5052. Lausanne: Samordningsmodeller och språk. s. 1–15. CiteSeerX 10.1.1.210.1242 . doi : 10.1007/978-3-540-68265-3_9 . ISBN 978-3-540-68264-6 .
-
Sulzmann, Martin; SL Lam, Edmund. "Parallella sammanfogningsmönster med skydd och förökning" . Danmark.
{{ citera journal }}
: Citera journal kräver|journal=
( hjälp ) - Fournet, Cédric; Gonthier, Georges (2002). Tillämpad semantik . Föreläsningsanteckningar i datavetenskap. Vol. 2395. Caminha. s. 1–66. CiteSeerX 10.1.1.4.4788 . doi : 10.1007/3-540-45699-6_6 . ISBN 978-3-540-44044-4 .
- Ma, Qin; Maranget, Luc (5 april 2004). CONCUR 2004 – Concurrency Theory . Föreläsningsanteckningar i datavetenskap. Vol. 3170. INRIA. s. 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 .
-
Singh, Satnam (6 januari 2007). "Högre ordningskombinatorer för sammanfogningsmönster med STM" .
{{ citera journal }}
: Citera journal kräver|journal=
( hjälp ) - MONSIEUR, Geert (2010), Mönsterbaserad koordinering i processbaserade tjänstekompositioner , Leuven Belgien: Katholiek Universiteit Leuven
- Russo, Claudio V. (23 oktober 2008). "Gå med i mönster för Visual Basic". ACM SIGPLAN-meddelanden . 43 (10): 53–72. doi : 10.1145/1449955.1449770 .
- Aaron, Turon; Russo, Claudio V. (27 oktober 2011). Skalbara sammanfogningsmönster (PDF) . Portland, Oregon, USA. ISBN 978-1-4503-0940-0 .
-
Guzev, Vadim B. (april 2008). "Parallell C#: Användningen av ackord och högre ordningsfunktioner i utformningen av parallella programmeringsspråk" ( PDF) . Moskva, Ryssland.
{{ citera journal }}
: Citera journal kräver|journal=
( hjälp )