Aktivní Oberon | |
---|---|
Jazyková třída | imperativní , modulární , objektově orientovaný , vícevláknový , strukturální , typově bezpečný |
Typ provedení | sestavil , interpretoval |
Objevil se v | 1997 |
Autor | Brinch Hansen, Jürg Gutknecht , Pieter Muller , Patrik Reali |
Přípona souboru | .Mod, mod |
Uvolnění | 2019 |
Typový systém | statický , silný |
Hlavní implementace | Aktivní Oberon.Net, FOX, PACO, Ronin |
Dialekty | Zonnon |
Byl ovlivněn | MATLAB , Modula-2 , Oberon , Object Oberon , Pascal |
ovlivnil | Active C# [1] , Composita, Go , Zonnon |
webová stránka | a2.inf.ethz.ch |
Plošina | ARM , Cell , JVM , .NET , x86-32 , x86-64 |
OS | A2 , Darwin , Linux , Solaris , Windows |
Active Oberon je univerzální, typově bezpečný , modulární , objektově orientovaný , vícevláknový programovací jazyk vyvinutý v letech 1996-1997 . skupina prof. Gutknecht na ETH Zurich (ETHZ) s cílem zavést do jazyka Oberon vlastnosti pro vyjádření souběžnosti prostřednictvím aktivních objektů [2] .
Název Active Oberon odráží hlavní koncept jazyka - koncept Active Objects , vyjádřený v implementaci multithreadingových a synchronizačních mechanismů na jazykové úrovni.
Aktivní Oberon rozšiřuje jazyk Oberon zavedením konceptů objektu a aktivity spojené s objektem. Takový vztah se nazývá aktivní objekt a znamená schopnost instance objektu mít aktivitu – vlastní vlákno provádění [2] .
Jazyk patří k modulárním typově bezpečným programovacím jazykům se silným statickým typováním , umožňujícím implicitní přetypování skalárních typů ve výrazech bez ztráty dat (například pomocí celého čísla, kde mělo být použito číslo s plovoucí desetinnou čárkou).
Moduly poskytují nejen samostatnou kompilaci , zapouzdření , ale také možnost implementovat dynamické načítání/vyjímání zkompilovaných (objektových) modulů, což se využívá např. v operačním systému A2 napsaném v tomto jazyce. Nějakým způsobem lze dynamicky propojovanou knihovnu považovat za analog modulu .
V Active Oberon, stejně jako v dalších nástupcích Modula-2 , je při přístupu k entitám připojeného (importovaného) modulu vyžadována povinná kvalifikace připojeného modulu. Pokud například modul A obsahuje modul B a používá proměnnou modulu v , pak odkaz na proměnnou musí mít tvar Bv . Jinými slovy, import v Active Oberon standardně neumožňuje importovat z připojeného modulu všechny entity, které exportuje.
Zapouzdření je postaveno na konceptu modulu – všechny typy deklarované v modulu jsou vzájemně zcela transparentní a pro přístup externích klientů jsou vyžadovány specifikátory přístupu . Specifikátory přístupu umožňují exportovat entity buď s plným přístupem (identifikátor je označen "*" (hvězdička)), nebo s přístupem pouze pro čtení (identifikátor je označen znaménkem "-" (mínus)). Například konstrukce:
TYP Příklad1 * = RECORD x * , y - , z : LONGINT ; KONEC ;definuje typ záznamu (RECORD) Příklad1 , exportovaný mimo modul a mající tři pole typu "long integer" a pole " x " je deklarováno specifikátorem přístupu "full access", pole " y " je deklarováno pomocí specifikátor "přístup pouze pro čtení" a pole ' z ' je skryté pole, které není přístupné externím klientům.
Jazyk podporuje polymorfismus , přetěžování operátorů (pro strukturální typy), delegáty , které jsou kompatibilní s metodami i procedurami. Typy objektů jsou RECORD a referenční typ OBJECT . Mohou mít metody a operace. Typ OBJECT může mít tělo a aktivitu. Všechny metody jsou virtuální . Neexistuje žádná vícenásobná dědičnost , místo toho se používá koncept vícenásobné dědičnosti rozhraní ( DEFINICE v jazykových termínech ).
Syntaxe jazyka se během vývoje prakticky nemění - vývojáři preferují zpřesňování sémantiky stávajících syntaktických konstrukcí pomocí zavedených sémantických modifikátorů , což umožňuje eliminovat značné množství úprav při zavádění nové funkcionality, zjednodušuje kompilátor, takže jeho kód je přístupnější pro pochopení a úpravu a také umožňuje snadné učení a používání jazyka. Modifikátory jsou uzavřeny ve složených závorkách {} za názvem proměnné, typem nebo klíčovým slovem. Například konstrukce:
VAR Příklad2 : PROCEDURE { REALTIME , C } ( VAR low , high : LONGINT ): BOOLEAN ;deklaruje procedurální proměnnou Example2 ukazující na proceduru v reálném čase s konvencí volání CCALL, která přebírá dva parametry typu long integer a vrací booleovskou hodnotu.
Popis objektu obecně odpovídá popisu modulu , s výjimkou syntaxe záhlaví a absence sekce IMPORT. Metody jsou zcela popsány uvnitř popisu objektu, operace až na vzácné výjimky mohou být popsány mimo tělo objektu. Objekt může mít libovolný počet inicializátorů a ne více než jeden finalizátor . Vestavěná procedura NEW , která se používá k vytváření proměnných referenčního typu, volá inicializátor vybraný kompilátorem na základě podpisu parametrů. Inicializátor je označen znakem & před názvem metody. Finalizátor, metoda bez parametrů, které předchází znak ~ , se volá automaticky, když je objekt vyřazen.
Posloupnost příkazů uzavřená v závorkách příkazu BEGIN END se nazývá blok příkazů . Blok příkazů může také obsahovat seznam modifikátorů a sekci zaručeného dokončení ( KONEČNĚ ).
Proměnnou, stejně jako pole záznamu nebo objektu, lze inicializovat konstantním výrazem, když je deklarován:
TYP Bod = RECORD x := 0 , y := 0 : LONGINT ; KONEC ; VAR i := 0 , j := 10 , k := 100 : INTEGER ; Bod : Bod ; (* pole x, y záznamu jsou inicializována na 0 *)Jazyk nabízí bohatou sadu vestavěných typů:
Pro Active Oberon jsou implementovány dva multithreadingové modely založené na práci Brinche Hansena a Tonyho Hoare [3] :
Zdrojový kód napsaný pomocí primitivní syntaxe synchronizace blokování Active Oberon lze použít pro oba modely multithreadingu - kompilátor vygeneruje kód potřebný pro konkrétní model. Díky tomuto přístupu není potřeba přepisovat software pro různé modely. Pouze malé části zdrojového kódu vyžadují přizpůsobení (jako je zpracování přerušení), aby bylo potlačeno automatické generování přepínačů v dané části strojového kódu. Za tímto účelem je blok příkazů označen modifikátorem {UNCOOPERATIVE} .
Aktivní objektyVlákno je zapouzdřeno v objektu a jako jeho nedílná součást je vytvořeno v okamžiku vytvoření instance aktivního objektu . Pro označení aktivity objektu je jeho tělo označeno modifikátorem ACTIVE .
Po přidělení instance objektu se spustí inicializátor (pokud existuje) a poté tělo objektu (pokud existuje). Pokud je objekt označen jako aktivní, je vytvořena aktivita, ve které je tělo objektu spouštěno asynchronně, jinak se spouštění provádí synchronně na vláknu, ve kterém byla instance vytvořena.
Aktivita objektu končí, když je dokončeno provádění těla objektu. Zatímco se tělo provádí, objekt nadále existuje, i když na něj nejsou žádné odkazy. Poté se objekt stává pasivním a lze s ním nakládat podle běžných pravidel.
Příklad popisu a použití aktivního objektu:
MODUL Příklad 3 ; TYP ActiveObject = OBJECT Stav VAR : SET ; POSTUP & Nový ; ZAČÍT stav := {}; KONEC Nový ; PROCEDURE & Init * ( stav : SET ); ZAČÍT SEBE . stav := stav ; KONEC Init ; POSTUP ~ Dokončit ; ZAČÍT ... KONEC Ukončit ; ZAČÍT { AKTIVNÍ } ... END ActiveObject ; VAR objekt : ActiveObject ; ZAČÍT NOVÝ ( objekt ); objekt . Init ( { 0 .. 7 , 9 , 12 , 30 .. 31 } ) ; NOVÝ ( objekt , {} ); KONEC Příklad3 . Meziprocesová komunikaceVolání metod sdílených aktivních a neaktivních objektů funguje jako komunikační mechanismus mezi aktivními objekty. Protože aktivní objekty existují v prostředí s více vlákny, je k dispozici mechanismus pro koordinaci souběžného přístupu k jejich stavu. Interakce prostřednictvím zpráv lze provádět pomocí speciálních softwarových rámců [5] .
Ochrana souběžnostiBlok příkazů označený modifikátorem EXCLUSIVE se nazývá exkluzivní oblast . Exkluzivní oblast v Active Oberon odpovídá konceptu Hansenovy kritické oblasti [6] . Pokud výhradní rozsah pokrývá celý soubor metody, pak se nazývá exkluzivní metoda (exkluzivní metoda) a kombinuje Hansenův koncept s Hoareovým monitorovacím postupem [7] [8] . Na rozdíl od procedury monitorování nemusí být objektová metoda exkluzivní, v takovém případě může pozorovat nekonzistentní stavy objektu. Exkluzivní rozsah může mít současně maximálně jednu aktivitu.
Model zabezpečení v Active Oberon je tedy monitor umístěný na monitoru založeném na instancích . Modul je považován za objekt typu singleton instance a jeho procedury mohou být také exkluzivní, čímž chrání modul jako celek.
Hlavní myšlenkou monitoru (a aktivního objektu) je, že s monitorem je spojen určitý invariant – výraz, který určuje konzistentní vnitřní stav objektu a dokazuje správnost jeho chování [9] . Inicializátory a exkluzivní metody jsou jazykem poskytované nástroje pro udržování invariantů objektu a skrývání jeho vnitřního stavu. Inicializátor objektu nastaví jeho invariant a exkluzivní metody jej podporují. Když se pojem monitor spojí s pojmem modul, vznikne výkonný mechanismus pro strukturování operačních systémů [10] [11] [12] .
Příklad použití exkluzivní sekce:
(* Postupy nastavení a resetování se vzájemně vylučují *) TYP Můj kontejner = OBJEKT VAR x , y : LONGINT ; (* Invariant: y = f(x) *) PROCEDURE Set ( x : LONGINT ); BEGIN { EXCLUSIVE } (* měnící se x a y atomicky *) SEBE . x := x ; y := f ( x ) END Set ; POSTUP Reset ; ZAČÍT ... BEGIN { EXCLUSIVE } (* měnící se x a y atomicky *) x := x0 ; y := y0 ; KONEC ; .... KONEC Resetovat ; KONEC MyContainer ; SynchronizaceNa rozdíl od většiny implementací monitorů, které k synchronizaci využívají Hoareovy podmíněné proměnné [8] (založené na frontách událostí Brinche Hansena [6] ), synchronizaci aktivit zajišťuje operátor AWAIT , který bere jako argument logický výraz – podmínku pokračování programu . provedení v těle předmětu. Aby byla zajištěna správná synchronizace, musí být AWAIT ve výhradním rozsahu. Pokud není splněna podmínka pokračování , AWAIT pozastaví aktivitu a pokud je ve výhradním rozsahu, uvolní zachycenou oblast po dobu pozastavení, což umožňuje jiným aktivitám změnit stav objektu a uvést podmínku pokračování do pravdivé. Pozastavená aktivita bude pokračovat pouze v případě, že může znovu vstoupit do výhradního rozsahu.
Příklad synchronizace uvnitř sdílené vyrovnávací paměti:
TYP Synchronizátor = OBJEKT VAR wake : BOOLEAN POSTUP Počkejte ; ZAČÁTEK { EXCLUSIVE } AWAIT ( probuzení ); vzhůru := NEPRAVDA ; KONEC Počkejte ; POSTUP Probuzení ; ZAČÁTEK { EXCLUSIVE } vzhůru := PRAVDA ; KONEC Probuzení ; KONEC synchronizátor ;Aktivní Oberon postrádá strukturované zpracování výjimek – ty jsou spravovány centrálně runtime prostředím.
Příkaz ASSERT bere jako povinný argument logický výraz, při jehož porušení je program přerušen a stejně jako při provádění příkazu HALT bezpodmínečné zastavení je řízení přeneseno na centralizovanou obsluhu výjimek. Pokud lze podmínku příkazu ASSERT vyhodnotit v době kompilace, vygeneruje se chyba kompilace, pokud podmínka není splněna. Příkazy ASSERT a HALT mohou mít volitelný parametr, specifikátor výjimky, který může obslužná rutina analyzovat.
Po ošetření výjimky se řízení přenese do další sekce zaručeného dokončení KONEČNĚ v zásobníku volání , pokud existuje. Pokud je pak tělo aktivního objektu označeno modifikátorem SAFE , aktivita se restartuje, jinak je aktivita ukončena.
Informace o typu běhu (metainformace ) mají pouze strukturální typy (pole, záznamy, objekty ). Metainformace jsou uloženy ve speciální struktuře nazývané deskriptor typu . Deskriptor typu obsahuje údaje o typech a jménech proměnných a polí, tabulku dědičnosti, tabulku virtuálních metod a tabulky implementovaných rozhraní .
Aktivní Oberon využívá automatickou správu paměti pomocí přerušitelného (preemptovatelného) sběrače odpadků v reálném čase [13] , založeného na metodě Mark and Sweep. Garbage collector běží na samostatném vláknu a aktivity (vlákna), které mají prioritu vyšší než priorita aktivity garbage collector, mohou pozastavit jeho provádění. V tomto případě je strom objektů zmrazen. V současnosti mohou činnost garbage collectoru přerušit pouze entity v reálném čase, dynamická alokace paměti je v nich zakázána a kompilátor to hlídá.
Správa paměti je založena na použití typizovaných oblastí paměti . Taková sekce ukládá ukazatel na deskriptor typu . Pomocí informací o typu běhu nalezených v deskriptoru typu najde nástroj pro uvolnění paměti proměnné a pole referenčního typu a označí bloky, na které ukazují. Jinými slovy, garbage collector nemusí kontrolovat každou hodnotu podobnou ukazateli, aby zjistil, zda se jedná o platný ukazatel na hromadě – pomocí informací poskytnutých deskriptorem typu přesně ví, které prvky zpracovat, což výrazně zvyšuje rychlost a přesnost práce a snižuje zátěž procesu.odvoz odpadu. Pro urychlení alokace paměti jsou volné oblasti umístěny do volných seznamů obsahujících bloky paměti určitých velikostí.
Proměnné typu reference označené modifikátorem UNTRACED jsou nesledovatelné ukazatele . Takové ukazatele nejsou sledovány garbage collectorem a paměťová místa, na která odkazují, lze kdykoli získat zpět, pokud byly přiděleny běhovým prostředím a neexistují na ně žádné dostupné odkazy, které by garbage collector zvažoval. Často se takové modifikátory používají k řešení paměti přidělené mimo běhové prostředí Active Oberon nebo s nebezpečnými ukazateli.
Runtime prostředí je zodpovědné za přidělení času CPU, zajišťuje (spolu s kompilátorem), že ve výlučném rozsahu není více než jedna aktivita, zajišťuje včasnou kontrolu podmínek AWAIT a obnovení pozastavených aktivit. Výrazy podmínky pokračování v rámci objektu jsou přehodnoceny ve všech výstupních bodech z výhradních oborů. To znamená, že změna stavu objektu mimo výhradní rozsah nezpůsobí přepočet podmínek. Když o stejné výlučné území soutěží několik aktivit, pak jsou aktivity se splněnými podmínkami zvažovány před těmi, které chtějí pouze vstoupit do chráněného území [3] [14] .
Aktivní Oberon postrádá prostředky k přímému řízení dynamického nakládání a vykládání modulů. Jazyk nabízí pouze sekci importu ( IMPORT ), která obsahuje seznam zásuvných modulů a sekci inicializace modulu. Runtime musí zajistit, aby byly plug-iny připojeny a inicializovány před inicializací aktuálního modulu. Dynamické spojování modulu se provádí pomocí mechanismu dynamického spojování . Modul nelze uvolnit, dokud na něj není odkazováno ze seznamu připojení jiného načteného modulu. Aby se tedy odstranil problém kruhových odkazů, moduly by měly být vykládány v opačném pořadí načítání.
Modul Depeše poskytuje centralizované zpracování výjimek. Parametry akceptované příkazy ASSERT a HALT lze použít ke klasifikaci výjimky.
Po zpracování výjimky v modulu Traps běhové prostředí vyhledá KONEČNĚ zaručené úseky dokončení a předá jim řízení, aby provedly závěrečné operace.
Pokud je aktivita označena modifikátorem SAFE a v těle objektu není sekce KONEČNĚ , je aktivita restartována, jinak je aktivita ukončena.
Runtime API poskytuje možnost nastavit si vlastní obslužnou rutinu výjimek.
Programovací jazyky | |
---|---|
|