Join minta

A join minta egy konkurrens (párhuzamos, elosztott) programtervezési minta, aminek lényege, hogy a szálak üzenetátadással kommunikálnak. A zárolással szemben magas szintű programozási modell, ami kommunikációs szerkezetmodellt használ, hogy elvonatkoztasson a környezet bonyolultságától, és lehetővé tegye a skálázást. Az üzenetek elfogyasztását atominak tekinti, még akkor is, ha több csatornán érkeztek az üzenetek.

Ez a minta a join-kalkuluson alapul, és mintaillesztést használ. Konkrétan ezt azzal valósítja meg, hogy lehetővé teszi függvények join definícióját, és/vagy csatornákat, amelyek konkurens hívásra illeszkednek, továbbá üzenetminták is definiálhatók. Konkurens programtervezési minták mintája (metaminta), mivel egyszerűbbé és hatékonyabbá teszi ezeknek az entitásoknak a kommunikációt és a többszálú programozási paradigma használatát.

Leírása

A join-minta egy magasabb csővezeték, szinkronizációval és mintaillesztéssel. Angolul chordnak is nevezik. Valójában a fogalom összegezhető illesztéssel és csatlakozással néhány üzenetre, amelyek különböző üzenetsorokból származnak, majd egyetlen kezelővel egyszerre kezeli őket.[1] Az első elvárt kommunikációs lépés jelezhető a when kulcsszóval, a felcsatlakozás és párosítás and kulcsszóval, és a különféle feladatok futtatása a do kulcsszóval. A join minta tipikus formája:

j.When(a1).And(a2). ... .And(an).Do(d)

A When(a1) első argumentuma lehet szinkron vagy aszinkron csatorna, de lehet csatornák tömbje is. Minden további argumentumnak aszinkron csatornának kell lennie.[2]

Pontosabban, ha egy üzenet illeszkedik minták egy összekapcsolt sorozatára, akkor elindul a kezelője egy új szálban, ha aszinkron kontextusban van, különben az üzenetnek várnia kell addig, amíg nem illeszkedik egy minta az ő valamelyik mintájára. Ha több illeszkedés van, akkor nem specifikált, hogy melyik minta választódik ki.[3] Egy eseménykezelővel szemben, ami egy időben egyszerre több alternatív esemény egyikét szolgálja ki, a join minta csatornák konjunkciójára vár, és verseng a végrehajtásért minden más megengedett mintával.[4]

Folyamatdiagram a join minta végrehajtásáról; általános illesztés több üzenetre (wait a chord) és az erőforrások szinkronizálása (szabad vagy zárolva)

A join mintát pi-kalkulusbeli csatornák halmaza definiálja, ami két műveletet definiál, a küldést és a fogadást; emiatt két join kalkulusbeli névre van szükség, egy x csatornanévre és egy x függvénynévre, az érték megszerzéséhez (egy kérés). A join definíció jelentése x() egy hívása, ami visszaadja azt az értéket, ami egy x<> csatornán érkezett. Továbbá ha több függvény fut párhuzamosan, kiváltódik a return folyamat, és együtt szinkronizálódik a többi folyamattal.[5]

J ::= //join patterns
| x<y> //message send pattern
| x(y) //function call pattern
| J | JBIS //synchronization

A kliens perspektívájából a csatorna csak deklarál egy metódust, ugyanazzal a névvel és szignatúrával. A kliens üzenetet küld vagy kérést vált ki a metódus hívásával. A folytató metódusnak várnia kell, amíg kérés vagy üzenet érkezett minden csatornán a folytatás When mondatát követően. Ha a folytatás futni kezd, akkor a csatornahívások argumentumai kikerülnek a sorból (elfogyasztódnak), és atomian átadódnak a folytatás paramétereinek. [6]

A join minta osztálydiagramja

A legtöbb esetben a szinkron hívások sorrendje nem garantált a jobb teljesítmény érdekében. Az üzeneteket egy másik szál is elfogyaszthatja, így a szálnak lehet, hogy tovább kell várnia egy újabb üzenetre.[7]

Története

π-kalkulus – 1992

A π-kalkulus a folyamatkalkulusok családjába tartozik, aminek segítségével matematikai képletekkel írja le és elemzi a konkurens számítások sorozatát elnevezett csatornák bevezetésével, így a folyamatok kommunikálhatnak csatornákon keresztül, így leírhatók olyan konkurens számítások is, amelyek hálózatkonfigurációja dinamikusan, futásidőben változik.

Join kalkulus – 1993

A join minták először Fournet és Gonthier alapvető join kalkulusával jelentek meg, mint aszinkron folyamatalgebra, amit elosztott környezetben hatékony implementációhoz terveztek.[8] A join kalkulus kifejezőképessége megegyezik a π-kalkuluséval. Arra fejlesztették ki, hogy formális megalapozást adjon az elosztott programozási nyelvekhez, így elkerüli a más folyamatkalkulusokban használt kommunikációs szerkezeteket, például a randevúkat.

Elosztott join kalkulus – 1996

A join kalkulus névátadó kalkulus, és egyben magnyelv a konkurens és elosztott programozáshoz.[9] Az elosztott join kalkulus a join kalkuluson alapul, de az elosztott számításokhoz kibővítve.[10] Mobil ágenseket használ, ahol az ágensek nem egyszerűen programok, hanem futó folyamatok, a saját kommunikációs képességeikkel.

JoCaml, Funnel és Join Java – 2000

A JoCaml[11][12] és a Funnel[13][14] funkcionális programozási nyelvek, amelyek támogatják a join minták deklarálását. Közvetlenül valósítják meg a join kalkulust funkcionális programozási nyelvekben.

Egy másik kiterjesztés egy nem szabványos kiterjesztés, a Java, JoinJava, amit Itzstein és Kearney javasolt.[15]

Polyphonic C# – 2002

Cardelli, Benton és Fournet javasolta a C# bővítését join mintával 2002-ben, ez a Polyphonic C#.

Cω – 2003

A Cω a join kalkulus objektumorientált adaptációja. Tartalmazta a Polyphonic C#-ot a Cω (Comega) 2004-es kiadásában.[16]

Scala Joins – 2007

A Scala Joins egy programkönyvtár, ami lehetővé teszi a join minta alkalmazását a Scala nyelvben a kiterjeszthető mintaillesztés kontextusában, hogy a join mintát a létező aktor alapú keretrendszerbe integrálja.

JErlang – 2009

Az Erlang natívan támogatja a konkurens, valós idejű és elosztott paradigmát. A folyamatok közötti konkurenciát bonyolult volt megoldani, ezért egy új nyelvet alkottak, a JErlangot, ami a join kalkuluson alapul.

A klasszikus programozási irodalomban

Join mintával egyszerűen kódolhatók egymással kapcsolatban álló konkurens problémák, mint aktorok és aktív objektumok.[17]

class SymmetricBarrier {
public readonly Synchronous.Channel Arrive;
public SymmetricBarrier(int n) {
    // create j and init channels (elided)
    var pat = j.When(Arrive);
    for (int i = 1; i < n; i++) pat = pat.And(Arrive);
    pat.Do(() => { });
}
}
var j = Join.Create();
Synchronous.Channel[] hungry;
Asynchronous.Channel[] chopstick;
j.Init(out hungry, n); j.Init(out chopstick, n);
for (int i = 0; i < n; i++) {
    var left = chopstick[i];
    var right = chopstick[(i+1) % n];
    j.When(hungry[i]).And(left).And(right).Do(() => {
    eat(); left(); right(); // replace chopsticks
    });
}
class Lock {
public readonly Synchronous.Channel Acquire;
public readonly Asynchronous.Channel Release;
    public Lock() {
        // create j and init channels (elided)
        j.When(Acquire).And(Release).Do(() => { });
        Release(); // initially free
    }
}
class Buffer<T> {
public readonly Asynchronous.Channel<T> Put;
public readonly Synchronous<T>.Channel Get;
    public Buffer() {
        Join j = Join.Create(); // allocate a Join object
        j.Init(out Put);
        // bind its channels
        j.Init(out Get);
        j.When(Get).And(Put).Do // register chord
        (t => { return t; });
    }
}
class ReaderWriterLock {
private readonly Asynchronous.Channel idle;
private readonly Asynchronous.Channel<int> shared;
public readonly Synchronous.Channel AcqR, AcqW,
RelR, RelW;
public ReaderWriterLock() {
    // create j and init channels (elided)
    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(); // initially free
}
}
class Semaphore {
public readonly Synchronous.Channel Acquire;
public readonly Asynchronous.Channel Release;
    public Semaphore(int n) {
        // create j and init channels (elided)
        j.When(Acquire).And(Release).Do(() => { });
        for (; n > 0; n--) Release(); // initially n free
    }
}

Alapfogalmak

  • Join kalkulus: A join minta első megvalósításai ezen alapulnak.
  • Üzenetátadás: A join minta párhuzamossági okok miatt üzenetátadással működik.
  • Csatorna: Csatornák szinkronizálják és adnak át üzeneteket a konkurensen végrehajtott szálak között. Általában egy csatorna több join mintában is benne van, minden minta egy lehetséges folytatást definiál, ami lefuthat, ha a csatorna meghívódik.[6]
  • Szinkron: A join minta használhat szinkron csatornákat, amelyek eredményt adnak vissza. A szinkron minta folytatása a szinkron hívó szálában fut.[6]
  • Aszinkron: Az aszinkron csatornának nincs visszatérési értéke, de argumentumai lehetnek. Folytatása egy új szálban fut. A join minta teljesen aszinkron lehet, folytatását szubrutinban nyújtja, és When mondata csak aszinkron csatornákat tartalmaz.[6]
  • Szinkron és aszinkron: A szinkron és aszinkron bufferek kombinációja egy olyan modult eredményez, ami kétféle fogyasztót támogat.[6]
  • Ütemező: a join mintákat ütemezni kell, kell egy ütemező, ami ezt megoldja.[6]
  • Programtervezési minták: a join minta konkurens viselkedési programtervezési minta.
  • Konkurens programozás: Konkurensen hajtódik végre.
  • Mintaillesztés: a join minta illeszkedő feladatokkal működik.
  • Párhuzamos programozás: párhuzamosan hajtódnak végre a feladatok.
  • Elosztott programozás: a join mintával felosztott feladatokat különböző ágensek hajthatják végre különböző környezetekben.
  • Tranzakcionális memória: alkalmas a join minta kommunikációjának megvalósítására.
  • Átfedés: a join minta számára nem probléma a különböző join minták közötti átfedés, egy csatornára több join minta is hivatkozhat.

Alkalmazások

Mobil ágenesek

A mobil ágensek autonóm programágensek társas készségekkel, kommunikációs lehetőségekkel és mozgási lehetőségekkel. A program és adatai mozoghatnak különféle gépek között futás közben.

A mobil ágensek használhatók arra, hogy összekapcsolják a konkurens és az elosztott programozást join kalkulussal. Ezért megalkották az elosztott join kalkulus fogalmát, ami helyekkel és primitívekkel bővíti a join kalkulust a mobilitás leírására. Így az ágenseknek van fogalmuk a lokációról, ami az ágens fizikai helyét jelenti. Az ágens atomi jelleggel mozoghat a különböző helyek között.[22]

Egy ágens folyamata funkcionalitásainak halmazaként definiálható, amibe beletartozik az aszinkron üzenetátadás, és a vándorlás. A mozgás könnyebb reprezentációja érdekében a helyeket fába szervezik. Ezzel a hibázás is egyszerűbben modellezhető. Ha egy helyen összeomlik a program, akkor minden alatta levő helyen is összeomlik. Egy meghatározott helyű hiba bármely futási helyről megtalálható, ez segít kijavítani a hibát.[22]

Így a join kalkulus egy elosztott nyelv magja. Operációs szemantikája egyszerűen implementálható egy elosztott rendszerben, ami a hiba lehetőségét is tartalmazza. Így a join kalkulus elsőrangú objektumokként kezeli a csatornákat és a helyeket. Egy hely ismeri más helyek nevét, ezért onnan oda lehet lépni. Ez biztos alapot teremt a statikus elemzésnek és a biztonságos mozgásnak. Teljes az elosztott helyek kifejezésében. Ha nincs hiba, akkor a végrehajtás független a helyektől. Ez az átláthatóság fontos a mobil ágensek tervezésében, és nagyon hasznos tulajdonságaik ellenőrzéséhez.[22]

2007-ben kiadták az alap join kalkulus egy proaktív ágenseket kezelő kiegészítését. Az ágensek megfigyelhetik közös környezetüket. Ehhez a közös környezethez változók adhatók az ágensekkel, például egy névszolgáltató, ami segít megtalálni más ágenseket.[23]

Szerkesztés, fordítás

A join nyelvek join kalkulusra, mint magnyelvre épülnek. Ezért a kalkulust aszinkron folyamatokkal elemzik, és a join minták modellt adnak az eredmény szinkronizálására.[9]
Ehhez két fordító szükséges:

  • Join fordító: a join nyelv számára készített fordító. Ezt csak a join kalkulus számára hozták létre.
  • Jocaml fordító: Az Objectif Caml egy kiterjesztésének fordítója, ami a join kalkulust használja.[24]

Ez a két fordító ugyanazon a rendszeren, egy automatán működik.

let A(n) | B() = P(n)
and A(n) | C() = Q(n)
;;

Ez egy üzenet fogyasztását reprezentálja, ami a kiegészített join modellbe érkezik. Minden állapot egy lehetőség a kód végrehajtására, és minden átmenet üzenet fogadása két állapot között. Ha minden üzenet meg van ragadva, akkor a fordító végrehajtja a join kód törzsét, a teljes join modellnek megfelelően.

Így a join kalkulusban az alapértékek nevek, mint például A, B vagy C. Így a két fordító kétféleképpen reprezentálja az eredményeket. A join fordító egy kétdimenziós vektort használ, az első a név, a második pedig a fogadott üzenetek listája. A Jocaml a neveket pointerként használja, ami a definícióra mutat. Ezek további nevek pointerét tartalmazzák állapot mezővel, és illeszkedő adatszerkezetet üzenetekkel. Az alapvető különbség az, hogy ha az őrző folyamat végrehajtódik, akkor először az üzenetben szereplő összes nevet ellenőrzi, hogy készen állnak-e a futásra, míg a második csak egy változót és hozzáférést a többihez ahhoz, hogy tudja, a modell teljes.[9]

Jelenlegi kutatások szerint a fordítási séma kétlépéses: irányításból és továbbításból áll. Az irányító tervezése és korrektsége lénygében a mintaillesztés elméletén múlik, míg egy belső irányítási lépés beszúrása a kommunikációba természetes ötlet, ami intuitívan nem változtatja meg a folyamat működését. Megfigyelték, hogy nem érdemes ennek ellenőrzése érdekében felügyelő objektumokat futás idejű szinten beiktatni, mivel ez jelentősen bonyolultabbá teszi az üzenetsorok kezelését, mivel végig kellene őket szkennelni a mintaillesztés és az üzenet elfogyasztása előtt.[25]

Implementációk és könyvtárak

A join mintákat több nyelvben is megtalálhatjuk. Egyes nyelvek implementációja is a join mintákon alapul, ilyen például a Polyphonic C# és az MC#.[26] Más nyelvek könyvtárként tartalmazzák a join mintákat. Ilyen a Scala Joins a Scala számára,[27] vagy a VB Joins könyvtára.[28] Továbbá egyes nyelvekben a join mintával fejlesztik a join mintákat, ilyen például a Scheme.[29]

JErlang CB Joins Library Polyphonic C# Parallel C# Scala Joins F# Scheme Join Java Hume JoCaml
Mintaillesztés Igen Igen Igen Igen Igen Igen Igen Igen Igen Igen Igen Igen
Ütemező a join minták között Igen : első illesztés Igen : első/round robin Igen Igen Igen Igen Igen Igen Nem Igen : véletlen Igen : első/round robin Igen : véletlen
Generikusok Igen N/A Igen Nem N/A Nem Igen Igen Nem Nem Nem Nem
Felüldefiniálás Nem Igen N/A N/A N/A Igen Igen Igen Igen Igen Nem Nem

Join Java

A Join Java egy programozási nyelv, ami a Javán alapul, és amiben használhatók join minták.[30] Ezt három új nyelvi szerkezet bevezetésével éri el:

A join metódusokat két vagy több join töredékkel lehet definiálni. A join metódus ezeket próbálja meg végrehajtani. Ha a visszatérési típus szabvány Java típus, akkor a vezető töredék blokkolja a hívót, amíg a join minta nem végez, és a metódus is be nem fejeződik. Ha a visszatérési érték jel, akkor a vezető töredék azonnal visszatér. A több töredék aszinkron, nem blokkolja a hívót.

Példa:

 class JoinExample {
    int fragment1() & fragment2(int x) {
       //will return value of x
       //to caller of fragment1
       return x;
    }
 }

Az aszinkron metódusokat jel visszatérési típusúak. Ugyanazok a jellemzői, mint a void visszatérési típus, kivéve hogy azonnal visszaér, és törzsét egy új szál hajtja végre.

Példa:

 class ThreadExample {
    signal thread(SomeObject x) {
       //this code will execute in a new thread
    }
 }

Rendezési módosítók: a join töredékek különböző join mintákban szerepelnek, így lehet, hogy egy minta hívásával több join minta is illeszkedik. Az alábbi példában, ha B(), C() és D() meghívódik, akkor A() is meghívódik. Az A() töredék a minták közül háromra illeszkedik, így három metódus is meghívható. A rendezési osztálymódosító meghatározza, hogy ekkor melyik hívódjon meg; alapértelmezetten véletlenül választódik ki. A rendezési módosító prioritást állíthat fel, hogy melyik legyen előnyben.

Példa:

 class ordered SimpleJoinPattern {
    void A() & B() {
    }
    void A() & C() {
    }
    void A() & D() {
    }
    signal D() & E() {
    }
 }

A legközelebbi rokon nyelv a Polyphonic C#.

JErlang

Erlangban nem egyszerű megoldani a párhuzamos folyamatok szinkronizációját. Ezért hozták létre a JErlang nyelvet, ami az Erlang kiterjesztése.[31] A J betű a Join rövidítése. A bővítés elemei:

A joinok lehetővé teszik az első illesztés szemantikáját; lehetőséget ad több minta definiálására, és az üzenetek sorrendjének megőrzésére.

operation() ->
    receive
        {ok, sum} and {val, X} and {val, Y} ->
            {sum, X + Y};
        {ok, mult} and {val, X} and {val, Y} ->
            {mult, X * Y};
        {ok, sub} and {val, X} and {val, Y} ->
            {sub, X - Y};
    end
end

Az őrök további szűrést tesznek lehetővé minták nélkül. Korlátozott számú kifejezés mellékhatás nélkül.

receive
    {Transaction, M} and {limit, Lower, Upper}
        when (Lower <= M and M <= Upper ) ->
    commit_transaction(M, Transaction)
end

Nemlineáris mintákkal az üzenet több joinra illeszthető.

receive
    {get, X} and {set, X} ->
        {found, 2, X}
end
...
receive
    {Pin, id} and {auth, Pin} and {commit, Id} ->
        perform_transaction(Pin, Id)
end

A terjesztés lehetővé teszi, hogy az üzenetek törlés helyett másolódjanak.

receive
    prop({session, Id}) and {act, Action, Id} ->
        perform_action(Action, Id);
    {session, Id} and {logout, Id} ->
        logout_user(Id)
end
...
receive
    {Pin, id} and {auth, Pin} and {commit, Id} ->
        perform_transaction(Pin, Id)
end

Szinkron hívások

receive
    {accept, Pid1} and {asynchronous, Value}
                   and {accept, Pid2} ->
        Pid1 ! {ok, Value},
        Pid2 ! {ok, Value}
end

C++

Yigong Liu írt néhány osztályt a C++-hoz a join minta számára,[32] köztük hasznos eszközöket, mint a szinkron és aszinkron csatornák, chordok, és hasonlók. Beépült a Boost projektbe.[33]

template <typename V>
class buffer: public joint {
public:
  async<V> put;
  synch<V,void> get;
  buffer() {
    chord(get, put, &buffer::chord_body);
  }
  V chord_body(void_t g, V p) {
    return p;
  }
};

Ebben a példában egy szálbiztos buffer és egy üzenetsor látható a put és get alapműveletekkel.[34]

C#

Polyphonic C#

A Polyphonic C# a C# programozási nyelv kiterjesztése. Új konkurencia modellt vezet be szinkron és aszinkron metódusokkal és chordokkal.

public class Buffer {
   public String get() & public async put(String s) {
      return s;
   }
}

A példa egy egyszerű buffert mutat.[35]

MC#

Az MC#[36] nyelv a Polyphonic C# adaptációja konkurens elosztott programozáshoz.

public handler Get2 long () & channel c1 ( long x )
& channel c2 ( long y )
{
return ( x + y );
}

A példa a chordot, mint szinkronizációs eszközt mutatja.

Parallel C#

A Parallel C#[37] a Polyphonic C# bővítése új fogalmakkal, mint mozgatható metódusok és magasabb rendű függvények.

using System;
 
class Test13 {
 int Receive() & async Send( int x ) {
  return x * x;
 }
 
 public static void Main( string[] args ) {
  Test13 t = new Test13();
  t.Send( 2 );
  Console.WriteLine( t.Receive() );
 }
}

A példa a joinok használatát mutatja.[38]

A új nyelvi eszközöket ad a konkurrens programozáshoz a Polyphonic C# egy korábbi verziójához képest. A Joins Concurrency Library C# könyvtár és a többi .NET nyelv ebből a projektből indult ki.[39][40]

Scalable Join Patterns

A Scalable Join Patterns egy programkönyvtár, amit arra terveztek, hogy könnyen használható legyen. A Russo könyvtárral szemben,[28] nem tartalmaz globális zárat. Az atomi üzenetrendszeren és az összehasonlít-cserél rendszeren alapul. A könyvtár [41] a join minta következő kiegészítéseit tartalmazza:

  • Nem használt erőforrásoknak érkezett üzenetek ellopása
  • Lusta sormentés, ami allokációkor és potenciálisan a processzorközi kommunikációban az allokáció vagy a sorba tétel elkerülésével egy optimista gyors-úttal;
  • Egy "WOKEN" állapot, ami biztosítja, hogy egy blokkolt szinkron hívó csak egyszer hívódik meg.

JoCaml

A JoCaml az első nyelv, amiben a join mintát implemtálták. Eleinte a többi implementációt is a JoCaml fordítóval fordították.[42] A JoCaml nyelv az OCaml kiterjesztése. A kiterjesztés támogatja a konkurenciát és a szinkronizációt, a programok elosztott végrehajtását, és a dinamikus költözést az aktívan futó programtöredékek számára[43]

type coins = Nickel | Dime
and drinks = Coffee | Tea
and buttons = BCoffee | BTea | BCancel;;

(* def defines a Join-pattern set clause
 * "&" in the left side of = means join (channel synchronism)
 * "&" in the right hand side means: parallel process
 * synchronous_reply :== "reply" [x] "to" channel_name
 * synchronous channels have function-like types (`a -> `b)
 * asynchronous channels have types (`a Join.chan)
 * only the last statement in a pattern rhs expression can be an asynchronous message
 * 0 in an asynchronous message position means STOP ("no sent message" in CSP terminology).
   *)

def put(s) = print_endline s ; 0 (* STOP *)
  ;; (* put: string Join.chan *)

def serve(drink) = match drink with
                 Coffee -> put("Cofee")
                 | Tea -> put("Tea")
              ;; (* serve: drinks Join.chan *)

def refund(v) = let s = Printf.sprintf "Refund %d" v in put(s)
    ;; (* refund: 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) & value(v) = value(v+5) & reply () to coin
  or coin(Dime) & value(v) = value(v+10) & reply () to coin

  or button(BCoffee) & value(v) =
     let should_serve, remainder = vend 10 v in
     (if should_serve then serve(Coffee) else 0 (* STOP *))
             & value(remainder) & reply () to button

  or button(BTea) & value(v) =
     let should_serve, remainder = vend 5 v in
     (if should_serve then serve(Tea) else 0 (* STOP *))
             & value(remainder) & reply () to button

  or button(BCancel) & value(v) = refund( v) & value(0) & reply () to button
  in spawn value(0) ;
  coin, button (* coin, button: int -> unit *)
  ;; (* new_vending: drink Join.chan -> int Join.chan -> (int->unit)*(int->unit) *)

let ccoin, cbutton = new_vending serve refund in
  ccoin(Nickel); ccoin(Nickel); ccoin(Dime);
  Unix.sleep(1); cbutton(BCoffee);
  Unix.sleep(1); cbutton(BTea);
  Unix.sleep(1); cbutton(BCancel);
  Unix.sleep(1) (* let the last message show up *)
  ;;

gives

Coffee
Tea
Refund 5

Hume

A Hume[44] egy szigorú, erősen típusozott funkcionális nyelv korlátozott erőforrásokkal rendelkező platformok számára, aminek konkurenciája aszinkron üzenetátadáson alapul, tartalmaz adatfolyam programozást. Szintaxisa hasonlít a Haskellhez.

A Hume nem tartalmaz szinkron üzenetátadást.

A join minta készletek közös csatornákat tartalmaznak, mint box (doboz), amely egy in tuple összes csatornáján hallgat, és minden lehetséges kimenetet egy out tupléban definiál.

Egy join mintának meg kell felelnie a box input tuple típusnak, amit '*' jelöl a nem igényelt csatornákra, kifejezéstípusa pedig megfelel az output tuple típusnak, amit '*' jelöl a nem táplált kimenetekre.

Egy wire mondat meghatározza a következőket:

  1. tuple a megfelelő input eredetekhez vagy forrásokhoz és opcionálisan kezdőértékek
  2. tuple az output célokhoz, amelyek csatornák vagy sinkek (stdout, ..).

Egy box specifikálhatnak kivételkezelőket az output tuplénak megfelelő kifejezésekkel.

data Coins = Nickel | Dime;
data Drinks = Coffee | Tea;
data Buttons = BCoffee | BTea | BCancel;

type Int = int 32 ;
type String = string ;
show u = u as string ;

box coffee
in ( coin :: Coins, button :: Buttons, value :: Int ) -- input channels
out ( drink_outp :: String, value :: Int, refund_outp :: String) -- named outputs

match
-- * wildcards for unfilled outputs, and unconsumed inputs
  ( 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)
;

vend drink cost credit = if credit >= cost
                      then ( serve drink, credit - cost, *)
                      else ( *, credit, *);

serve drink = case drink of
               Coffee -> "Cofee\n"
               Tea -> "Tea\n"
;

box control
in (c :: char)
out (coin :: Coins, button:: Buttons)
match
 'n' -> (Nickel, *)
 | 'd' -> (Dime, *)
 | 'c' -> (*, BCoffee)
 | 't' -> (*, BTea)
 | 'x' -> (*, BCancel)
 | _ -> (*, *)
;

stream console_outp to "std_out" ;
stream console_inp from "std_in" ;

-- dataflow wiring

wire cofee
    -- inputs (channel origins)
    (control.coin, control.button, coffee.value initially 0)
    -- outputs destinations
    (console_outp, coffee.value, console_outp)
;

wire control
    (console_inp)
    (coffee.coin, coffee.button)
;

Visual Basic

Concurrent Basic – CB

A Concurrent Basic a Visual Basic 9.0 kiterjesztése aszinkron konkurenciaszerkezetekkel a join minták kifejezésére. A CB a korábbi Polyphonic C#, Cω és Joins Library tapasztalatain alapulva adoptál egy egyszerű eseményszerű szintaxist, ami ismerős a VB programozók számára, és lehetővé teszi generikus konkurencia absztrakciók definiálását, továbbá természetesebb támogatást nyújt az öröklődésnek, megengedve az alosztálynak a minták bővítését. Egy CB osztály deklarálhat metódust, ami meghívódik ha kommunikációs esemény történt csatornák egy join mintát meghatározó halmazán.[28]

Module 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

A példa bemutatja a Concurrent Basicbe bevezetett új kulcsszavakat: Asynchronous, Synchronous és When.[45]

Joins könyvtár (C# és VB)

Ez a könyvtár a join minta magas szintű absztrakciója, ami objektumokat és generikusokat használ. A csatornák speciális delegált értékek valamely közös Join objektum (metódusok helyett).[46]

 class Buffer {
   public readonly Asynchronous.Channel<string> Put;
   public readonly Synchronous<string>.Channel Get;
   public Buffer() {
     Join join = Join.Create();
     join.Initialize(out Put);
     join.Initialize(out Get);
     join.When(Get).And(Put).Do(delegate(string s) {
       return s;
     });
   }
 }

A példa azt mutatja, hogyan lehet egy Join objektum metódusait használni.[47]

Scala

A Scala Joins[48] egy Scala könyvtár a join minta használatához. A mintaillesztés egy eszköz join modellek készítéséhez. Példák itt: Join definitions in Scala

A nyelv mintaillesztési lehetőségei általánosíthatók, hogy lehetővé tegye a mintaillesztésben használt objektumok független reprezentációját. Most a könyvtárakban használható egy új típusú absztrakció. A join mintának az az előnye, hogy megengedi a különböző szálak szinkronizációjának deklaratív specifikációját. A join minta megfeleltethető egy véges állapotgépnek, ami specifikálja az objektum érvényes állapotait.

class ReaderWriterLock extends Joins {

private val Sharing = new AsyncEvent[Int]
val Exclusive, ReleaseExclusive = new NullarySyncEvent
val Shared, ReleaseShared = new NullarySyncEvent
join {
case Exclusive() & Sharing(0) => Exclusive reply
case ReleaseExclusive() => { Sharing(0); ReleaseExclusive reply }
case Shared() & Sharing(n) => { Sharing(n+1); Shared reply }
case ReleaseShared() & Sharing(1) => { Sharing(0); ReleaseShared reply }
case ReleaseShared() & Sharing(n) => { Sharing(n-1); ReleaseShared reply }
}
Sharing(0) }

Egy osztályban eseményeket definiálunk adattagként. Így lehet a join szerkezetet, hogy lehetővé tegye a mintaillesztést eset deklarációkkal. A lista => jellel kapcsolja össze a deklaráció részeit. A bal oldal join minta egy modellje, ami események szinkron vagy aszinkron kombinációját jelzi, a jobb oldal pedig végrehajtódik, ha a join minta teljesül.

Scalaban lehet az actor könyvtárat is használni.[49] a join mintával.Például egy nem korlátos buffer:[27]

val Put = new Join1[Int]
val Get = new Join
class Buffer extends JoinActor {
def act() {
receive { case Get() & Put(x) => Get reply x }
} }

A könyvtár támogatja az aktor alapú konkurenciát, és a join minta ennek kiterjesztése, így lehetséges kombinálni a join mintákat és az eseményvezérelt konkurenciamodellt, amit az aktorok nyújtanak. Ahogy a példában látható, ez ugyanaz, mint aktorokkal használni a join mintákat, csak eseteket kell deklarálni a fogadó metódusban, hogy megtudjuk, hogy a modell teljes.

Ugyanezek az eszközök elérhetők az F# számára is.

A Scala Join[50] és a Chymyst[51] a join minta újabb megvalósításai, amelyek Dr. Philipp Haller Scala Joinsán[52] alapulnak.

Haskell

A Join Language[53] a join minta implementációja a Haskell számára.

Scheme

A join minta lehetővé tesz egy új programozási stílust speciálisan a többmagos architektúrák számára, ami sok programozási helyzetben elérhető, és magas szintű absztrakciót nyújt. Ez a Guardokon (őrök) és Propagationön (továbbításon) alapul. A következőkben ennek egy megvalósítását ismertetjük a Scheme nyelvben.[29]

Az őrök ahhoz fontosak, hogy csak az illeszkedő kulcsú adatok frissüljenek vagy lehessenek találatok. PA továbbítás töröl egy itemet, elolvassa a tartalmát és visszahelyez egy itemet a készletbe. Olvasás alatt az item megtalálható a készletben. Az őrök osztott változókkal fejezhetők ki. Az újdonság az, hogy a join minta tartalmazhatja a most továbbított és egyesített részeket. Így a Scheme-ben a továbbítás előtti vagy alatti részeket és az eltávolítás előtti és utáni részeket. A Goal-Based (cél alapú) használata ia munkát sok feladatra osztja és joinolja az összes végeredményt az összes join mintával. Egy "MiniJoin" nevű rendszert arra alkottak, hogy a köztes eredményt felhasználja más feladatok megoldásához, ha ez lehetséges. Ha ez nem lehetséges, akkor megvárja a többi feladatot, hogy felhasználhassa a végeredményüket.

Így a konkurens join minta alkalmazása párhuzamosan hajtódik végre egy többmagos rendszeren, ami viszont nem garantálja, hogy nem lesznek ütközések. Ezt a szoftvertranzakciós memória (STM) intézi egy erősen hangolt konkurens adatszerkezetben, ami atomi összehasonlításon és cserén (CAS) alapul. Ez megengedi, hogy sok konkurens művelet fusson párhuzamosan egy többmagos architektúrán. Továbbá atomi végrehajtást használ a CAS és STM közötti hamis konfliktus elkerülésére.[29]

Hasonló minták

A join minta nem az egyetlen, ami alkalmas egyszerre több szál futtatására, de az egyetlen, ami lehetővé teszi a kommunikációt az erőforrások, a szinkronizáció és a különböző folyamatok joinja között.

  • Szekvencia minta: az egyik feladatnak meg kell várnia, amíg az előző végez (klasszikus implementáció).
  • Split minta: párhuzamosan végrehajt néhány feladatot.

Jegyzetek

  1. Taral Dragon: Join Calculus, 2009. október 25. (Hozzáférés: 2012)
  2. (2008. október 23.) „Join Patterns for Visual Basic”, Nashville, Tennessee, USA, 10. o. 
  3. Parallel C#. (Hozzáférés: 2012)
  4. „Join Patterns for Visual Basic”, 2. o. 
  5. (2002) „The Join Calculus: a Language for Distributed Mobile Programming”, Caminha, 8. o. [halott link]
  6. a b c d e f Join Patterns for Visual Basic Claudio V. Russo.
  7. (2008. október 23.) „Join Patterns for Visual Basic”, Nashville, Tennessee, USA, 5. o. 
  8. (2008. október 23.) „Join Patterns for Visual Basic”, Nashville, Tennessee, USA, 18. o. 
  9. a b c (2007. szeptember 25.) „Compiling Join-Patterns”, Le Chesnay France. 
  10. (1996) „A Calculus of Mobile Agents”, Le Chesnay, 406–421. o, Kiadó: Concurrency Theory. [halott link]
  11. (2000. szeptember 1.) „JoCaml: a language for concurrent distributed and mobile programming.”. In Advanced Functional Programming, 4th International SchoolOxford, August 2002 2638. 
  12. (1999) „JoCaml: Mobile agents for Objective-Caml”. In First International Symposium on AgentSystems and Applications. (ASA'99)/Third International Symposium onMobile Agents (MA'99). 
  13. (2000. szeptember 1.) „An overview of functional nets.”. Summer School, Caminha, Portugal, September 2000 2395. 
  14. (2000) „Functional nets.”. In Proceedings of the European Symposium on Programming. Lecture Notes in Computer Science 1782. 
  15. (2001) „Join Java: An alternative concurrency semantics for Java”. Echnical Report ACRC-01-001, University of South Australia. 
  16. (2002. június 1.) „Modern concurrency abstractions for C#.”. In Proceedings of the 16th European Conference on Object-Oriented Programming (ECOOP 2002), number 2374 in LNCS. 
  17. Singh, Satnam (2007. január 6.). „Higher Order Combinators for Join Patterns using STM”, 1. o. 
  18. a b (2011. október 27.) „Scalable Join Patterns”, Portland, Oregon, USA, 4. o. 
  19. (2011. október 27.) „Scalable Join Patterns”, Portland, Oregon, USA, 1. o. 
  20. a b (2011. október 27.) „Scalable Join Patterns”, Portland, Oregon, USA, 3. o. 
  21. (2011. október 27.) „Scalable Join Patterns”, Portland, Oregon, USA, 2. o. 
  22. a b c (1996) „A Calculus of Mobile Agents”, Le Chesnay, Kiadó: Concurrency Theory. [halott link]
  23. (2007) „Multi-Agent Systems and Applications V”. Lecture Notes in Computer Science 4696, 298–300. o. DOI:10.1007/978-3-540-75254-7_30. 
  24. http://pauillac.inria.fr/jocaml/ Archiválva 2005. október 1-i dátummal a Wayback Machine-ben Jocaml Compiler
  25. (2004. április 5.) „Compiling Pattern Matching in Join-Patterns”, 417–431. o, Kiadó: INRIA. [halott link]
  26. http://www.mcsharp.net/
  27. a b (2008) „Implementing Joins using Extensible Pattern Matching”, Lausanne, 1–15. o, Kiadó: Coordination Models and Languages. [halott link]
  28. a b c (2008. október 23.) „Join Patterns for Visual Basic”, Nashville, Tennessee, USA, 53–72. o. 
  29. a b c Parallel Join Patterns with Guards and Propagation”, Denmark. 
  30. (2002) „Hardware Join Java: A High Level Language For Reconfigurable Hardware Development”, Hong Kong. [2013. február 19-i dátummal az eredetiből archiválva]. (Hozzáférés: 2017. július 6.) 
  31. (2009) „JErlang: Erlang with Joins”, London. [2017. október 10-i dátummal az eredetiből archiválva]. (Hozzáférés: 2017. július 7.) 
  32. osztályok a join mintákhoz
  33. Boost c++.
  34. Join - Asynchronous Message Coordination and Concurrency Library, 2007. január 9. (Hozzáférés: 2012)
  35. Introduction to Polyphonic C#. (Hozzáférés: 2012)
  36. MC#
  37. Parallel C#
  38. Parallel C#. [2013. november 26-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012)
  39. The Joins Concurrency Library. (Hozzáférés: 2012)
  40. Comega. (Hozzáférés: 2012)
  41. (2011. október 27.) „Scalable Join Patterns”, Portland, Oregon, USA. 
  42. JoCaml nyelv
  43. JoCaml: a Language for Concurrent Distributed and Mobile Programming, Advanced Functional Programming, Lecture Notes in Computer Science. Springer-Verlag, 129-158. o. (2003) 
  44. Hammond/Michaelson/Sun - Programming reactive systems in Hume
  45. Concurrent Basic. [2015. április 25-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012)
  46. (2007) „The Joins Concurrency Library”, Cambridge, 260–274. o, Kiadó: Practical Aspects of Declarative Languages. [halott link]
  47. The Joins Concurrency Library. (Hozzáférés: 2012)
  48. Scala Joins
  49. (2007. június 1.) „Actors that unify threads and events”, Kiadó: In Proc. COORDINATION, LNCS. 
  50. Scala Join
  51. Chymyst
  52. Scala Joins. [2016. március 3-i dátummal az eredetiből archiválva]. (Hozzáférés: 2017. július 7.)
  53. Join Language

Források

Fordítás

Ez a szócikk részben vagy egészben a Join-pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.

Read other articles:

David Villa David Villa con la nazionale spagnola nel 2013 Nazionalità  Spagna Altezza 175[1] cm Peso 78[1] kg Calcio Ruolo Attaccante Termine carriera 1º febbraio 2020 Carriera Giovanili 1991-1999 Langreo Squadre di club1 1999-2001 Sporting Gijón B66 (26)2001-2003 Sporting Gijón80 (38)2003-2005 Real Saragozza73 (32)2005-2010 Valencia166 (108)2010-2013 Barcellona77 (33)2013-2014 Atlético Madrid36 (13)2014→  Melbourne City ...

 

Berikut adalah daftar destinasi yang dilayani oleh Virgin Atlantic Airways.[1] Virgin Atlantic Airbus A340-600 di Bandar Udara Internasional Narita, Jepang Afrika Ghana Accra - Bandar Udara Internasional Kotoka Kenya Nairobi - Bandar Udara Internasional Jomo Kenyatta Nigeria Lagos - Bandar Udara Internasional Murtala Mohammed Afrika Selatan Cape Town - Bandar Udara Internasional Cape Town [musiman] Johannesburg - Bandar Udara Internasional OR Tambo Amerika Kepulauan Karibia Antigua da...

 

Peta yang menunjukkan letak Kibungan Data sensus penduduk di Kibungan Tahun Populasi Persentase 199514.148—200015.0361.31%200715.7000.60% Kibungan adalah munisipalitas di provinsi Benguet, Filipina. Pada tahun 2007, munisipalitas ini memiliki populasi sebesar 15.700 jiwa atau 2.949 rumah tangga. Pembagian wilayah Secara politis Kibungan terbagi atas 7 barangay, yaitu: Badeo Lubo Madaymen Palina Poblacion Sagpat Tacadang Pranala luar Philippine Standard Geographic Code Diarsipkan 2012-04-13 ...

Stasiun Bayeman Tampak luar Stasiun Bayeman, 2020Lokasi Jalan Raya Tongas / Pasuruan-ProbolinggoDungun, Tongas, Probolinggo, Jawa Timur 67252IndonesiaKoordinat7°44′05″S 113°07′08″E / 7.734597°S 113.118837°E / -7.734597; 113.118837Koordinat: 7°44′05″S 113°07′08″E / 7.734597°S 113.118837°E / -7.734597; 113.118837Ketinggian+6 mOperator Kereta Api IndonesiaDaerah Operasi IX Jember Letakkm 89+924 lintas Surabaya Kota-Proboling...

 

2014 Élections sénatoriales de 2020 en Charente-Maritime 27 septembre 2020 Type d’élection Élections sénatoriales Postes à élire 3 sièges de sénateur Union pour la réussite de la Charente-Maritime – Daniel Laurent Liste Les Républicains0 Voix 828 47,21 %   élus 2 Une gauche aux côtés des territoires – Mickaël Vallet Liste Parti socialisteDivers gauche Voix 500 28,51 %   élus 1  1 modifier - modifier le code - voir Wi...

 

52nd Infantry Division Torino52nd Infantry Division Torino insigniaActive1940–1943Country Kingdom of ItalyBranch Royal Italian ArmyRoleInfantrySizeDivisionEngagementsWorld War IICommandersNotablecommandersUgo de CarolisInsigniaIdentificationsymbol Torino Division gorget patchesMilitary unit The 52nd Infantry Division Torino (Italian: 52ª Divisione di fanteria Torino) was an infantry division of the Royal Italian Army during World War II. The Torino was named after the city of Tu...

Brazilian rock/blues band This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: O Bando do Velho Jack – news · newspapers · books · scholar · JSTOR (August 2009) (Learn how and when to remove this message) O Bando do Velho JackBackground informationOriginCampo Grande, MS, BrazilGenresBlues, classic rock and southe...

 

KōgenKaisar JepangBerkuasa214 – 158 SM (traditional)[1]PendahuluKaisar KōreiPenerusKaisar KaikaKelahiran-Kematian-PemakamanTsurugi no ike no shima no e no misasagi (Nara) Kaisar Kōgen (孝元天皇code: ja is deprecated , Kōgen-tennō) juga dikenal sebagai Ooyamatonekohikokunikuru no Mikoto, adalah Kaisar Jepang yang kedelapan,[2] menurut urutan tradisional suksesi.[3] Tidak ada catatan kapan dia hidup, tetapi diperkirakan dia memerintah mulai tahun 214 SM – 15...

 

For the length in general and comparison, see 10 nanometres. MOSFET technology node Semiconductordevicefabrication MOSFET scaling(process nodes) 020 µm – 1968 010 µm – 1971 006 µm – 1974 003 µm – 1977  1.5 µm – 1981 001 µm – 1984 800 nm – 1987 600 nm – 1990 350 nm – 1993 250 nm – 1996 180 nm – 1999 130 nm – 2001 090 nm – 2003 06...

الولاية الشمالية     الإحداثيات 17°37′23″N 29°25′16″E / 17.62306°N 29.42111°E / 17.62306; 29.42111   تقسيم إداري  البلد السودان[1][2]  التقسيم الأعلى السودان  العاصمة كرمة البلد  خصائص جغرافية  المساحة 348765 كيلومتر مربع  رمز جيونيمز 378389  أيزو 3166 SD-NO[3 ...

 

Mathematical group of the homotopy classes of loops in a topological space For the fundamental group of a factor, see von Neumann algebra. In the mathematical field of algebraic topology, the fundamental group of a topological space is the group of the equivalence classes under homotopy of the loops contained in the space. It records information about the basic shape, or holes, of the topological space. The fundamental group is the first and simplest homotopy group. The fundamental group is a...

 

Award ceremony for films of 2006 79th Academy AwardsOfficial posterDateFebruary 25, 2007SiteKodak TheatreHollywood, Los Angeles, California, U.S.Hosted byEllen DeGeneres[1]Preshow hostsChris ConnellyLisa Ling[2] André Leon Talley[3]Allyson Waterman[4]Produced byLaura Ziskin[5]Directed byLouis J. Horvitz[6]HighlightsBest PictureThe DepartedMost awardsThe Departed (4)Most nominationsDreamgirls (8)TV in the United StatesNetworkABCDuration3 hours, ...

生月 鯨太左衛門 基礎情報四股名 生月 鯨太左衛門本名 墨谷 要作生年月日 1827年4月16日没年月日 (1850-07-03) 1850年7月3日(23歳没)出身 肥前国松浦郡生月島身長 227 cm体重 169 kgBMI 32.8所属部屋 玉垣部屋得意技 張り手, 突っ張り成績現在の番付 引退最高位 西張出前頭生涯戦歴 3勝2敗115休幕内戦歴 3勝2敗115休優勝 0賞 0データ初土俵 1843年入幕 1843年引退 1850年趣味 女遊び備考■...

 

Yang MuliaIgnatius Pin-Mei KungHamba AllahUskup Shanghai1949.KeuskupanShanghaiTakhtaShanghaiPenunjukan15 Juli 1950Awal masa jabatan1950Masa jabatan berakhir12 Maret 2000PenerusJoseph Fan ZhongliangJabatan lainUskup Soochow (1949-50)Administrator Apostolik Soochow (1950-2000)Administrator Apostolik Keuskupan Agung Nanking (1950-2000)Kardinal-Pendeta San Sisto Vecchio (1991-2000)ImamatTahbisan imam28 Mei 1930Tahbisan uskup7 Oktober 1949oleh Antonio RiberiPelantikan kardinal30 Juni 1979 (in...

 

Cancelled NCAA women's ice hockey postseason tournament Collegiate ice hockey tournament 2020 NCAA National Collegiate women's ice hockey tournamentTeams8Finals siteAgganis ArenaBoston, Massachusetts ← 2019  NCAA women's ice hockey tournaments 2021 → The 2020 NCAA National Collegiate Women's Ice Hockey Tournament was a planned single-elimination tournament by eight schools to determine the national champion of women's NCAA Division I college ice hockey. The quarterfinals were schedu...

Прапор Британської Території в Індійському ОкеаніВикористання Пропорції1:2Затверджений8 листопада 1990Кольори синій білий червоний зелений коричневий жовтийТиппрапор заморської територіїПриналежністьБританська територія в Індійському океані  Прапор Британської Т...

 

Городской университет Дублина(DCU)Dublin City University Год основания 1975 Президент Ferdinand von Prondzynski Студенты 17 000 Юридический адрес Дублин Сайт dcu.ie  Медиафайлы на Викискладе Городско́й университе́т Ду́блина (англ. Dublin City University, ирл. Ollscoil Chathair Bhaile Átha Cliath) — один из четырёх унив�...

 

French atoll in the Mozambique Channel You can help expand this article with text translated from the corresponding article in French. (November 2019) Click [show] for important translation instructions. View a machine-translated version of the French article. Machine translation, like DeepL or Google Translate, is a useful starting point for translations, but translators must revise errors as necessary and confirm that the translation is accurate, rather than simply copy-pasting machine...

American archivist Herman KahnBornHerman Kahn(1907-08-13)August 13, 1907Rochester, New YorkDiedJune 5, 1975(1975-06-05) (aged 67)New Haven, ConnecticutOccupationarchivistSpouseAnne Suess Kahn Herman Kahn (August 13, 1907 – June 5, 1975) was an American archivist, and served as an Assistant Archivist of the United States between 1962 and 1968. Kahn was born in Rochester, New York, and studied history at the University of Minnesota.[1] He received his bachelor's degree from the u...

 

This article may be too technical for most readers to understand. Please help improve it to make it understandable to non-experts, without removing the technical details. (February 2018) (Learn how and when to remove this message) Apical ectodermal ridgeThe apical ectodermal ridge is a region of thickened epithelium at the most distal end of the limb bud. The zone of polarising activity (ZPA) is at the posterior part of the limb bud.DetailsIdentifiersLatincrista ectodermalis apicalisTEectoder...