Aktív Oberon

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2018. január 9-én felülvizsgált verziótól ; az ellenőrzések 16 szerkesztést igényelnek .
Aktív Oberon
Nyelvóra kötelező , moduláris , objektumorientált , többszálú , szerkezeti , típusbiztos
A végrehajtás típusa összeállította , értelmezte
Megjelent 1997
Szerző Brinch Hansen, Jürg Gutknecht , Pieter Muller , Patrik Reali
Fájlkiterjesztés _ .Mod, mod
Kiadás 2019
Típusrendszer statikus , erős
Főbb megvalósítások Aktív Oberon.Net, FOX, PACO, Ronin
Dialektusok Zonnon
Befolyásolt MATLAB , Modula-2 , Oberon , Object Oberon , Pascal
befolyásolta Aktív C# [1] , Composita, Go , Zonnon
Weboldal a2.inf.ethz.ch
Felület ARM , Cell , JVM , .NET , x86-32 , x86-64
OS A2 , Darwin , Linux , Solaris , Windows

Az Active Oberon  egy általános célú, típusbiztos , moduláris , objektumorientált  , többszálú programozási nyelv , amelyet 1996-1997 között fejlesztettek ki . egy csoport prof. Gutknecht a zürichi ETH-n (ETHZ) azzal a céllal, hogy az Oberon nyelvbe olyan tulajdonságokat vezessen be, amelyek az egyidejűséget aktív objektumon keresztül fejezik ki [2] .

A nyelv jellemzői

Az Active Oberon név tükrözi a nyelv fő koncepcióját - az Active Objects fogalmát , amely a többszálú és szinkronizálási mechanizmusok nyelvi szintű megvalósításában fejeződik ki.

Az Active Oberon kiterjeszti az Oberon nyelvet az objektum és az objektumhoz kapcsolódó tevékenység fogalmának bevezetésével . Az ilyen kapcsolatot Active Object -nek nevezik, és egy objektumpéldány azon képességét jelenti , hogy tevékenységgel rendelkezzen – saját végrehajtási szála [2] .

A nyelv a moduláris , típusbiztos programozási nyelvek közé tartozik, erős statikus gépeléssel , lehetővé téve a skaláris típusok implicit öntését kifejezésekben adatvesztés nélkül (például olyan egész szám használatával, ahol lebegőpontos számot kellett volna használni).

A modulok nem csak külön fordítást , beágyazást biztosítanak , hanem a lefordított (objektum) modulok dinamikus be-/kiürítésének megvalósítását is, amit például az ezen a nyelven írt A2 operációs rendszerben használnak. A dinamikus hivatkozási könyvtár valamilyen módon a modul analógjának tekinthető .

Az Active Oberonban, akárcsak a Modula-2 többi utódjában , a csatlakoztatott (importált) modul entitásainak eléréséhez a csatlakoztatott modul kötelező minősítése szükséges. Például, ha az A modul tartalmazza a B modult , és a modul v változóját használja , akkor a változóhivatkozásnak Bv formátumúnak kell lennie . Más szóval, az Active Oberon importálása alapértelmezés szerint nem teszi lehetővé az összes exportált entitás importálását a csatlakoztatott modulból.

A beágyazás a modul koncepciójára épül - a modulban deklarált összes típus teljesen átlátszó egymás számára, és hozzáférési specifikációk szükségesek a külső kliensek eléréséhez . A hozzáférési specifikációk lehetővé teszik az entitások exportálását vagy teljes hozzáféréssel (az azonosítót "*" (csillag) jelöli), vagy csak olvasási hozzáféréssel (az azonosítót "-" (mínusz) jelöli). Például a konstrukció:

TÍPUS Példa1 * = RECORD x * , y - , z : HOSSZÚ ; VÉGE ;

definiálja a rekordtípust (RECORD) Példa1 , a modulon kívülre exportálva, és három "long integer" típusú mezővel rendelkezik, és az " x " mező a "teljes hozzáférés" hozzáférési specifikációval van deklarálva, az " y " mező pedig a megadja a "csak olvasási hozzáférést", a ' z ' mező pedig egy rejtett mező, amely nem érhető el külső ügyfelek számára.

A nyelv támogatja a polimorfizmust , az operátor-túlterhelést (strukturális típusoknál), a delegációkat , amelyek kompatibilisek mind a metódusokkal, mind az eljárásokkal. Az objektumtípusok a RECORD és a referenciatípus az OBJECT . Lehetnek módszereik és műveleteik. Egy TÁRGYtípusnak lehet teste és tevékenysége. Minden módszer virtuális . Nincs többszörös öröklődés , helyette az interfészek többszörös öröklődésének fogalmát ( nyelvi értelemben DEFINÍCIÓ ) használják.

Szintaxis és szemantika

A nyelv szintaxisa gyakorlatilag nem változik a fejlesztés során - a fejlesztők előszeretettel finomítják a meglévő szintaktikai konstrukciók szemantikáját a bevezetett szemantikai módosítók segítségével , ami lehetővé teszi az új funkciók bevezetésekor jelentős mennyiségű szerkesztés kiküszöbölését, egyszerűsíti a fordítót, ezáltal A kód könnyebben hozzáférhető a megértéshez és módosításhoz, valamint megkönnyíti a nyelv tanulását és használatát. A módosítókat a változó neve, típusa vagy kulcsszava után kapcsos zárójelek közé kell tenni {}. Például a konstrukció:

VAR 2. példa : ELJÁRÁS { REALTIME , C } ( VAR alacsony , magas : LONGINT ): BOOLE ;

deklarál egy Példa2 eljárási változót , amely egy valós idejű eljárásra mutat a CCALL hívási konvencióval, amely két hosszú egész típusú paramétert vesz igénybe, és egy logikai értéket ad vissza.

Az objektum leírása általában megfelel a modul leírásának , kivéve a fejléc szintaxisát és az IMPORT szakasz hiányát. A metódusok teljes egészében az objektumleíráson belül vannak leírva, a műveletek – ritka kivételektől eltekintve – az objektum törzsén kívül is leírhatók. Egy objektumnak tetszőleges számú inicializálója lehet, és legfeljebb egy véglegesítő . A referencia típusú változók létrehozására szolgáló NEW beépített eljárás a paraméterek aláírása alapján a fordító által kiválasztott inicializálót hívja meg. Az inicializáló a metódus neve előtt & jellel van jelölve . A véglegesítő, egy paraméter nélküli metódus, amelyet egy ~ jel előz meg , automatikusan meghívásra kerül, amikor egy tárgyat eldobnak.

A BEGIN END zárójelekbe zárt utasítássorozatot utasításblokknak nevezzük . Az utasításblokk tartalmazhat módosítólistát és egy garantált befejezés ( VÉGRE ) részt is.

Egy változó, valamint egy rekord vagy egy objektum mezője egy állandó kifejezéssel inicializálható, amikor deklarálják:

TÍPUS Pont = RECORD x := 0 , y := 0 : HOSSZÚ ; VÉGE ; VAR i := 0 , j := 10 , k := 100 : INTEGER ; Pont : Pont ; (* a rekord x, y mezői 0-ra vannak inicializálva *)

Adattípusok

A nyelv a beépített típusok gazdag készletét kínálja:

  • Alaptípusok
    • logikai érték: BOOLEAN ;
    • karakter: CHAR8 , CHAR16 , CHAR32 és az alapértelmezett karaktertípus CHAR álneve ;
    • előjeles egész számok: SIGNED8 , SIGNED16 , SIGNED32 , SIGNED64 és álnevek SMALLINT , INTEGER , LONGINT , HUGEINT ;
    • előjel nélküli egész számok: UNSZIGNED8 , NEM ELŐJELZETT16 , NEM ELŐjelezve32 , NEM ELŐÍRT64 ;
    • valódi: REAL , LONGREAL ;
    • komplex: KOMPLEX , HOSSZÚKOMPLEX ;
    • gép függő: MÉRET , CÍM ;
    • készlet: SET, SET8, SET16, SET32, SET64 ;
    • bővíthető felsorolások: ENUM ;
  • szerkezeti
    • tömbök: ARRAY  - statikus, dinamikus, nyitott, matematikai;
    • nyújtható szerkezetek: RECORD ;
    • objektum: OBJECT ;
  • Különleges
    • eljárási;
    • delegáltak: eljárási változók, amelyek mind az eljárásokkal, mind a módszerekkel kompatibilisek;
    • gépelt mutatók szerkezeti típusokra;
    • általános mutatók: ANY , OBJECT , ARRAY ;
  • rendszer: SYSTEM.BYTE

Többszálú

Az Active Oberon esetében két többszálas modellt valósítottak meg Brinch Hansen és Tony Hoare [3] munkái alapján :

Az Active Oberon blokkoló szinkronizációs primitív szintaxisával írt forráskód mindkét többszálú modellhez használható – a fordító generálja az adott modellhez szükséges kódot. Ezzel a megközelítéssel nincs szükség a szoftverek átírására a különböző modellekhez. A forráskódnak csak kis részei igényelnek adaptációt (például megszakításkezelést) a kapcsolók automatikus generálásának megakadályozása érdekében a gépi kód adott részében. Ehhez az utasításblokkot az {UNCOOPERATIVE} módosítóval kell megjelölni .

Aktív objektumok

Egy szál egy objektumba van beágyazva , és annak szerves részeként az aktív objektum példányosításának pillanatában jön létre. Egy objektum aktivitásának jelzésére a testét az ACTIVE módosítóval jelöljük .

Az objektumpéldány lefoglalása után az inicializáló (ha van ilyen) végrehajtásra kerül, majd az objektum törzse (ha van). Ha az objektum aktívként van megjelölve, akkor létrejön egy tevékenység, amelyben az objektum törzse aszinkron módon hajtódik végre, ellenkező esetben a végrehajtás szinkron módon történik azon a szálon, amelyben a példányt létrehozták.

Egy objektum tevékenysége akkor ér véget, amikor az objektum testének végrehajtása befejeződik. Amíg a törzs végrehajtódik, az objektum továbbra is létezik, még akkor is, ha nincs rá hivatkozás. Ezt követően a tárgy passzívvá válik, és a szokásos szabályok szerint selejtezhető.

Példa egy aktív objektum leírására és használatára:

MODUL Példa 3 ; TÍPUS ActiveObject = OBJECT VAR állapot : SET ; ELJÁRÁS & ​​Új ; KEZDŐDIK állapot := {}; VÉGE Új ; PROCEDURE & Init * ( állapot : SET ); KEZDŐDIK ÉN . állapot := állapot ; VÉGE Init ; ELJÁRÁS ~ Véglegesítés ; KEZDŐDIK ... VÉGE Lezárás ; KEZDÉS { AKTÍV } ... END ActiveObject ; VAR objektum : ActiveObject ; KEZDŐDIK ÚJ ( tárgy ); tárgyat . Init ( { 0 .. 7 , 9 , 12 , 30 .. 31 } ); ÚJ ( objektum , {} ); VÉGE 3. példa . Folyamatközi kommunikáció

A megosztott aktív és inaktív objektumok metódusainak hívásai kommunikációs mechanizmusként működnek az aktív objektumok között. Mivel az aktív objektumok többszálú környezetben léteznek, egy mechanizmus biztosított az állapotukhoz való egyidejű hozzáférés koordinálására. Az üzenetküldés útján történő interakció speciális szoftverkeretrendszerek segítségével valósítható meg [5] .

Párhuzamos védelem

Az EXCLUSIVE módosítóval jelölt utasításblokkot kizárólagos régiónak nevezzük . Az Active Oberon exkluzív területe megfelel Hansen kritikus területe koncepciójának [6] . Ha a kizárólagos hatókör lefedi a módszer teljes törzsét, akkor azt exkluzív módszernek (exkluzív módszer) nevezzük, és Hansen koncepcióját a Hoare monitorozási eljárással kombinálja [7] [8] . Ellentétben a monitor eljárással, az objektum metódusnak nem kell kizárólagosnak lennie, ilyenkor inkonzisztens objektumállapotokat figyelhet meg. Egy kizárólagos hatókör egyszerre legfeljebb egy tevékenységet tartalmazhat.

Így az Active Oberon biztonsági modellje egy példány alapú monitoron elhelyezett monitor . Egy modul egypéldányos objektumtípusnak minősül, és eljárásai is lehetnek kizárólagosak, védve a modul egészét.

A monitor (és egy aktív objektum) fő gondolata az, hogy egy bizonyos invariáns  kapcsolódik a monitorhoz - egy kifejezés, amely meghatározza az objektum következetes belső állapotát, és bizonyítja viselkedésének helyességét [9] . Az inicializálók és a kizárólagos metódusok nyelv által biztosított eszközök az objektum invariánsainak fenntartására és belső állapotának elrejtésére. Egy objektum inicializálója beállítja az invariánst, és a kizárólagos metódusok támogatják. Ha a monitor fogalmát a modul fogalmával kombináljuk, akkor egy erőteljes mechanizmus jön létre az operációs rendszerek strukturálására [10] [11] [12] .

Példa az exkluzív szakasz használatára:

(* A beállítási és visszaállítási eljárások kölcsönösen kizárják egymást *) TÍPUS MyContainer = OBJEKTUM VAR x , y : LONGINT ; (* Invariáns: y = f(x) *) ELJÁRÁS Beállítva ( x : HOSSZÚ ); KEZDÉS { KIZÁRÓLAGOS } (* x-et és y-t atomosan megváltoztatva *) ÉN . x := x ; y := f ( x ) VÉGE Beállítva ; ELJÁRÁS Reset ; KEZDŐDIK ... KEZDÉS { KIZÁRÓLAGOS } (* x-et és y-t atomosan megváltoztatva *) x := x0 ; y := y0 ; VÉGE ; .... VÉGE Reset ; VÉGE MyContainer ; Szinkronizálás

Ellentétben a legtöbb monitor implementációval, amely Hoare feltételes változóit [8] használja a szinkronizáláshoz (Brinch Hansen [6] eseménysorai alapján), a tevékenységek szinkronizálását az AWAIT operátor biztosítja , amely argumentumként egy logikai kifejezést vesz fel – a program folytatásának feltételét. végrehajtás egy tárgy testében. A megfelelő szinkronizálás érdekében az AWAIT -nek kizárólagos hatókörben kell lennie. Ha a folytatási feltétel nem teljesül , az AWAIT felfüggeszti a tevékenységet, és ha kizárólagos hatókörben van, felszabadítja a befogott területet a felfüggesztés idejére, ami lehetővé teszi, hogy más tevékenységek megváltoztassák az objektum állapotát, és igazzá tegyék a folytatási feltételt. A felfüggesztett tevékenység csak akkor fut tovább, ha újra belép a kizárólagos hatókörbe.

Példa a megosztott pufferen belüli szinkronizálásra:

TÍPUS Szinkronizáló = OBJECT VAR wake : BOOLEAN ELJÁRÁS Várjon ; KEZDÉS { EXKLUZÍV } AWAIT ( ébren ); ébren := HAMIS ; VÉGE Várj ; ELJÁRÁS WakeUp ; KEZDÉS { EXKLUZÍV } ébren := IGAZ ; END WakeUp ; VÉGE szinkronizáló ;

Hibák és kivételek kezelése

Az Active Oberonból hiányzik a strukturált kivételkezelés – ezeket központilag a futási környezet kezeli.

Az ASSERT utasítás kötelező argumentumként vesz fel egy logikai kifejezést, amelynek megsértése esetén a program megszakad, és a HALT feltétel nélküli stop utasítás végrehajtásához hasonlóan a központi kivételkezelőhöz kerül a vezérlés. Ha az ASSERT utasítás feltétele a fordításkor kiértékelhető, akkor fordítási hiba keletkezik, ha a feltétel nem teljesül. Az ASSERT és HALT utasításoknak lehet egy opcionális paramétere, egy kivételspecifikátor, amelyet a kezelő elemezhet.

A kivétel kezelése után az irányítás átkerül a következő garantált befejezési szakaszra VÉGRE a hívási veremben , ha van ilyen. Ezután, ha az aktív objektum törzsét a SAFE módosító jelöli , a tevékenység újraindul, ellenkező esetben a tevékenység leáll.

Futókörnyezet

Információk a futásidejű típusokról

Csak a szerkezeti típusok (tömbök, rekordok, objektumok) rendelkeznek futásidejű típusú információval (metainformáció). A metainformáció egy speciális struktúrában, úgynevezett Type Descriptorban tárolódik . A típusleíró adatokat tartalmaz a változók és mezők típusairól és neveiről, egy öröklődési táblát, egy virtuális metódustáblázatot és a megvalósított interfészek tábláit .

Memóriakezelés

Az Active Oberon automatikus memóriakezelést használ egy megszakítható (preemptable) valós idejű szemétgyűjtővel [13] , amely a Mark and Sweep módszeren alapul. A szemétgyűjtő külön szálon fut, és azok a tevékenységek (szálak), amelyek prioritása magasabb, mint a szemétgyűjtő tevékenység prioritása, szüneteltethetik a végrehajtását. Ebben az esetben az objektumfa lefagy. Jelenleg csak valós idejű entitások szakíthatják meg a szemétgyűjtő tevékenységét, a dinamikus memóriafoglalás tilos bennük , és a fordító ezt figyeli.

A memóriakezelés a beírt memóriaterületek használatán alapul . Egy ilyen szakasz egy típusleíró mutatót tárol . A típusleíróban található futásidejű típusinformációk felhasználásával a szemétgyűjtő megkeresi a referenciatípus változóit és mezőit, és megjelöli azokat a blokkokat, amelyekre mutatnak. Vagyis a szemétgyűjtőnek nem kell minden mutatószerű értéket ellenőriznie, hogy az érvényes mutató-e a kupacban  – a típusleíró által megadott információk alapján pontosan tudja, hogy mely elemeket kell feldolgozni, ami jelentősen növeli a a munka sebessége és pontossága és csökkenti a folyamat terhelését.szemétgyűjtés. A memóriakiosztás felgyorsítása érdekében a szabad területek bizonyos méretű memóriablokkokat tartalmazó szabad listákra kerülnek.

Az UNTRACED módosítóval jelölt referencia típusú változók nem nyomon követhető mutatók . Az ilyen mutatókat a szemétgyűjtő nem követi nyomon, és a hivatkozott memóriahelyek bármikor visszaigényelhetők, ha a futásidejű környezet lefoglalta őket, és nincsenek elérhető hivatkozások, amelyeket a szemétgyűjtő figyelembe vesz. Az ilyen módosítókat gyakran az Active Oberon futási környezeten kívül lefoglalt memória vagy nem biztonságos mutató kezelésére használják.

Objektumtevékenység kezelése

A futási környezet felelős a CPU-idő lefoglalásáért, biztosítja (a fordítóval együtt), hogy a kizárólagos hatókörben legfeljebb egy tevékenység szerepeljen, gondoskodik az AWAIT feltételek időben történő ellenőrzéséről és a felfüggesztett tevékenységek folytatásáról. Az objektumon belüli folytatási feltétel kifejezések újraértékelésre kerülnek a kizárólagos hatókörök összes kilépési pontján. Ez azt jelenti, hogy egy objektum állapotának a kizárólagos hatókörön kívüli megváltoztatása nem okozza a feltételek újraszámítását. Ha több tevékenység verseng ugyanarra a kizárólagos területre, akkor a teljesített feltételekkel rendelkező tevékenységeket az előbbiek tekintik, amelyek csak a védett területre kívánnak belépni [3] [14] .

Modulok csatlakoztatása és inicializálása

Az Active Oberon nem rendelkezik a modulok dinamikus be- és kirakodásának közvetlen vezérléséhez szükséges eszközökkel. A nyelv csak egy import szakaszt ( IMPORT ) kínál, amely tartalmazza a beépülő modulok listáját és a modul inicializálási szakaszát. A futásidőnek biztosítania kell, hogy a beépülő modulok csatlakoztatva legyenek és inicializálva legyenek az aktuális modul inicializálása előtt. A modulok dinamikus összekapcsolása a dinamikus összekapcsolási mechanizmuson keresztül történik . Egy modult nem lehet kirakni, amíg nem hivatkozik rá egy másik betöltött modul csatlakozási listájáról. Így a körkörös hivatkozások problémájának kiküszöbölése érdekében a modulokat a betöltés fordított sorrendjében kell kirakni.

Hibák és kivételek kezelése

A Traps modul központi kivételkezelést biztosít. Az ASSERT és HALT utasítások által elfogadott paraméterek használhatók a kivételek osztályozására.

A Traps modul kivételének kezelése után a futási környezet megkeresi a VÉGRE garantált befejezési szakaszokat , és átadja nekik a vezérlést a végső műveletek végrehajtásához.

Ha a tevékenység BIZTONSÁGOS módosítóval van megjelölve, és az objektum törzsében nincs VÉGRE szakasz , akkor a tevékenység újraindul, ellenkező esetben a tevékenység leáll.

A futásidejű API lehetővé teszi a saját kivételkezelő beállítását.

Nyelvi kiterjesztések

Programpéldák

Helló Világ!

MODUL Hello World ; IMPORTKernelLog ; _ KEZDŐDIK KernelLog . String ( "Hello, World!" ); VÉGE Hello World .

A beszállító és fogyasztó klasszikus problémájának megoldása

MODUL BoundedBuffers ; TÍPUS Elem * = TÁRGY ; Puffer * = OBJEKTUM VAR h , n : INTEGER ; B : ARRAY * OF tétel ; ELJÁRÁS Get * (): Tétel ; VAR x : Tétel ; KEZDÉS { EXKLUZÍV } VÁR ( n # 0 ); (*a puffer nem üres*) x := B [ h ]; h := ( h + 1 ) MOD LEN ( B ); DEC ( n ); VISSZA x VÉGE Get ; ELJÁRÁS Put * ( x : Tétel ); KEZDÉS { EXKLUZÍV } VÁR ( n # LEN ( B )); (* puffer nincs tele *) B [( h + n ) MOD LEN ( B )] := x ; INC ( n ) VÉGE Put ; PROCEDURE & Init ( max : INTEGER ); BEGIN (*inicializáló*) ÚJ ( B , max ); h : = 0 n := 0 VÉGE Init ; VÉGE puffer ; END BoundedBuffers .

Linkek

Lásd még

Jegyzetek

  1. Aktív C# projekt oldal Archiválva : 2011. szeptember 4.
  2. ↑ 1 2 J. Gutknecht. A halaknak valóban távirányítóra van szükségük? Javaslat önaktív objektumokra in Oberon., 1997.
  3. ↑ 1 2 3 P.J. Muller. Aktív objektumrendszer. Tervezés és többprocesszoros megvalósítás. — ETH Zürich, 2002., Diss. ETH #14755.
  4. Florian Negele. Zárolásmentes programozás és kooperatív többfeladatos munka kombinálása hordozható többprocesszoros futásidejű rendszerhez, ETH Zurich, 2014, Diss. ETH sz. 22298
  5. Florian Negele. A2 Concurrency Framework, ETH Zürich, 2009. június 3
  6. ↑ 1 2 P. Brinch Hansen. strukturált többprogramozás. Az ACM közleményei, 15(7), 1972. július
  7. P. Brinch Hansen. operációs rendszer alapelvei. Prentice Hall, 1973.
  8. ↑ 1 2 C.AR Hoare. Monitorok: Az operációs rendszer felépítésének koncepciója. Az ACM közleményei, 17(10):549-557, 1974. október.
  9. OJ Dahl. Monitors Revisited. In A.W. Roscoe, szerkesztő: A Classical Mind – Essays in Honor of C.A.R. Hoare. Prentice Hall,
    1994.
  10. JL Keedy. Az operációs rendszerek monitorokkal történő strukturálásáról. ACM Operating Systems Review, 13(1), 1979. január.
  11. N. Wirth. Modula: A moduláris multiprogramozás nyelve. Szoftver – Gyakorlat és tapasztalat, 7:3-35, 1977.
  12. N. Wirth. A Modula használata. Szoftver – Gyakorlat és tapasztalat, 7:37-65, 1977.
  13. Ulrike Glavitsch. Valós idejű szemétgyűjtés az A2-ben. Institute of Computer Systems, ETH Zürich
  14. P. Reali. Aktív Oberon nyelvi jelentés. – ETH Zürich, 2004.