A Limbo programozási nyelv

Párhuzamosság

Csatorna

A csatorna, melynek típusa

chan of adattípus

meghatározott típusú elemek küldésére és fogadására alkalmas kommunikációs mechanizmus. Használhatjuk lokális folyamatok közötti kommunikációra, vagy könyvtári eljárásokkal csatlakozhatnak megnevezett célállomásokhoz. Például,

chan of (int, string)

egy olyan csatorna, mely egy egészből és egy sztringből álló sort továbbít. Ha egy ilyen típusú csatorna példányát (legyen ez pl. a c) deklaráltuk és inicializáltuk, akkor a

c <-= (123, "Hello");

utasítás ilyen sorokat küld át rajta.

Csatorna létrehozása

A

chan of adat-típus

értéke a megadott típusú inicializált csatorna. A deklaráció a csatornát nil-re inicializálja, a csatornát használata előtt létre kell hozni. Például:

ch: chan of int; # csak deklarálás, ch-t nil-re állítja . . . ch = chan of int; # létrehozza cstornát, és hozzárendeli

Csatorna kommunikáció

A <- kommunikációs operátor típusa chan of sometype. A kifejezés értéke a korábban csatornára küldött első olvasatlan elem, és típusa a csatornához társított típus. Ha a csatorna üres, a program várakozik, amíg adat nem érkezik.

Speciális esetben a <- operátor típusa lehet array of chan of sometype. Ebben az esetben a tömb minden csatornája tesztelésre kerül, és fair módon egy olyan választódik ki, melyen van adat. A kifejezés (melyben szerepel a <- operátor) (int, sometype ) típusú sort eredményez; ahol az első tag megadja az aktív csatorna tömbbeli indexét, a második tag a csatornáról olvasott érték. Ha nincs olyan csatorna, melyben van adat, a kifejezés várakozik.


Az alt utasítás

Az alt utasítás a kommunikációs csatornák készenlététől függő utasítások közül egynek átadja a vezérlést. Szintaxisa a case utasítás szintaxisához hasonlít:

alt { minősítő-utasítás-sorozat }

A minősítők azonban különböznek a case minősítőitől. Az alt utasításban minden minősítő * vagy kifejezés, ami tartalmazza a <- kommunikációs operátort, amely küldést ill. fogadást is jelenthet. Például:

outchan := chan of string; inchan := chan of int; alt { i := <-inchan => sys->print("Received %d\n", i); outchan <- = "message" => sys->print("Sent the message\n"); }

Az alt utasítás végrehajtása a következő: a minősítő listában szereplő csatornák mindegyike kiértékelődik aszerint, hogy készen áll-e küldésre ill. fogadásra (ez az operátortól függ). Ha nincs készen álló csatorna, akkor a program blokkolódik, amíg legalább egy csatorna készen nem lesz. A készen állók közül véletlenszerűen választódik ki egy, és végrehajtódik az utasítás.

Ha a * minősítő szerepel, és nincs készen álló csatorna, a program nem blokkolódik, hanem a *-hoz rendelt utasítások hajtódnak végre.

Ha egy minősítő kifejezésben két kommunikációs operátor is szerepel, az alt csak a bal oldalit teszteli. Ha különböző szálakban kettő vagy több alt utasítás ugyanazon csatornán akar küldeni (vagy fogadni), a kérések egy sorba kerülnek, és ha megszűnik a csatorna blokkoltsága, az alt-ot elsőként végrehajtó szál aktiválódik.

Mint a case utasításnál, a minősítők és a hozzájuk tartozó utasítások külön blokkokat képeznek, az egyes minősítőknél deklarált változók láthatósága a következő minősítőnél (a blokk végén) megszűnik. Így a következő példában az i változó hatásköre a megadott két sorra korlátozódik:

i := <-inchan => sys->print("Received %d\n", i);

A <- operátornak paraméterként adható csatornákból álló tömb. Ez a jelölés leegyszerűsítése az olyan az alt utasításnak, melyben a csatornák azonos típusúak, és hasonlóan viselkednek. Ebben a változatban a kommunikációs kifejezés értéke egy sor, amely tartalmazza a csatorna indexét, amelyen keresztül a kommunikáció zajlott, és az értéket. Például:

a: array [2] of chan of string; a[0] = chan of string; a[1] = chan of string; . . . (i, s) := <- a; # s most az a[i] csatornabeli sztringet tartalmazza

a <- operátor vár, amíg az a valamelyik tagja kész nem lesz, véletlenszerűen választ egyet (ha mindkettő kész), és az indexből és a sztringből álló sorral tér vissza.

Az alt utasítás végrehajtása során a minősítőkben szereplő kifejezések előre nem meghatározott sorrendben értékelődnek ki, és bizonyos részkifejezések kiértékelése előbb megtörténhet, mint a csatornák készenlétének tesztelése. Ezért a kifejezések minősítése nem használhat fel mellékhatásokat, és kerülnie kell a végrehajtást késleltető részeket. Például a köv. minősítőkben

ch <- = getchar() => # Rossz ötlet! ich <- = next++ => # Rossz ötlet!

a getchar() függvény korán hívható az alt-ban, ha várakozik, a teljes alt utasítás várakozni fog. Hasonlóan, a next++ kiértékelése az ich készenállásának ellenőrzése előtt megtörténhet.

A send kifejezés

A send-kifejezés alakja:

send-kifejezés: balérték-kifejezés <- = kifejezés

Az

e1 <- = e2

kifejezésben az e1 balérték chan of typetípusú kell legyen, e2 ugyanúgy. e2 értékét a csatornára tesszük. Ha nincs olyan taszk, mely fogadná az értéket, a küldő blokkolódik.

A spawn utasítás

A spawn utasítás segítségével új vezérlési szálat hozhatunk lérte.
Általános alakja:

spawn term ( kifejezés-listopt ) ;

A term és a kifejezés-lista függvényhívás kell legyen. A spawn egy független, aszinkronok vezérlési szálat hoz létre, ez hívja a függvényt az új szál környezetben. Ez a függvény hozzáférhet a származtatott szálban elérhető objektumokhoz, a két szál ugyanazon memóriaterületen osztozik. Az elérhető objektumok az aktuális modul globális adatai és a származtatott függvénynek átadott adatok. A szálak előre ütemezve vannak, így a szálak által (közösen) használt objektumokban bármikor változás léphet fel.
A nyelvben nincsenek explicit szinkronizációs utasítások.<