Aktiv Oberon

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 9 januari 2018; kontroller kräver 16 redigeringar .
Aktiv Oberon
Språkklass imperativ , modulär , objektorienterad , multithreading , strukturell , typsäker
Utförandetyp sammanställt , tolkat
Framträdde i 1997
Författare Brinch Hansen, Jürg Gutknecht , Pieter Muller , Patrik Reali
Filtillägg _ .Mod, mod
Släpp 2019
Typ system statisk , stark
Stora implementeringar Aktiv Oberon.Net, FOX, PACO, Ronin
Dialekter Zonnon
Blivit påverkad MATLAB , Modula-2 , Oberon , Object Oberon , Pascal
påverkas Active C# [1] , Composita, Go , Zonnon
Hemsida a2.inf.ethz.ch
Plattform ARM , Cell , JVM , .NET , x86-32 , x86-64
OS A2 , Darwin , Linux , Solaris , Windows

Active Oberon  är ett generellt, typsäkert , modulärt , objektorienterat  , flertrådigt programmeringsspråk utvecklat 1996-1997 . en grupp av prof. Gutknecht vid ETH Zürich (ETHZ) med syftet att introducera i Oberon- språket egenskaper för att uttrycka samtidighet genom aktiva objekt [2] .

Funktioner i språket

Namnet Active Oberon återspeglar språkets huvudkoncept - konceptet Active Objects , uttryckt i implementeringen av multithreading och synkroniseringsmekanismer på språknivå.

Active Oberon utökar Oberon- språket genom att introducera begreppen för ett objekt och en aktivitet som är associerad med ett objekt. En sådan relation kallas ett Active Object , och betyder förmågan hos en objektinstans att ha en aktivitet - sin egen exekveringstråd [2] .

Språket tillhör modulära typsäkra programmeringsspråk med stark statisk typning , vilket möjliggör implicit casting av skalära typer i uttryck utan dataförlust (till exempel med användning av ett heltal där ett flyttalstal var tänkt att användas).

Moduler ger inte bara separat kompilering , inkapsling , utan också möjligheten att implementera dynamisk laddning/avlastning av kompilerade (objekt) moduler, som används till exempel i operativsystemet A2 skrivet på detta språk. På något sätt kan ett dynamiskt länkbibliotek betraktas som en analog till en modul .

I Active Oberon, liksom i andra efterföljare av Modula-2 , krävs en obligatorisk kvalifikation för den anslutna modulen när du får åtkomst till enheterna i en ansluten (importerad) modul. Till exempel, om modul A inkluderar modul B och använder modulens variabel v , måste variabelreferensen vara av formen Bv . Med andra ord tillåter importen i Active Oberon inte som standard att importera alla enheter som den exporterar från den anslutna modulen.

Encapsulation bygger på konceptet med en modul - alla typer som deklareras i en modul är helt transparenta för varandra, och åtkomstspecifikationer krävs för åtkomst av externa klienter . Åtkomstspecifikationer låter dig exportera enheter antingen med full åtkomst (identifieraren är markerad med en "*" (asterisk)), eller med skrivskyddad åtkomst (identifieraren är markerad med ett "-" (minustecken). Till exempel konstruktionen:

TYP Exempel1 * = RECORD x * , y - , z : LONGINT ; SLUT ;

definierar posttypen (RECORD) Exempel1 , exporterad utanför modulen och har tre fält av typen "långt heltal", och fältet " x " deklareras med åtkomstspecifikationen "full tillgång", fältet " y " deklareras med specifikationen "skrivskyddad åtkomst" och ' z '-fältet är ett dolt fält, inte tillgängligt för externa klienter.

Språket stöder polymorfism , operatörsöverbelastning (för strukturella typer), delegater som är kompatibla med både metoder och procedurer. Objekttyperna är RECORD och referenstypen OBJECT . De kan ha metoder och operationer. En OBJEKTtyp kan ha en kropp och en aktivitet. Alla metoder är virtuella . Det finns inget multipelt arv , istället används begreppet multipelt arv av gränssnitt ( DEFINITION i språktermer).

Syntax och semantik

Språkets syntax förändras praktiskt taget inte under utvecklingen - utvecklare föredrar att förfina semantiken för befintliga syntaktiska konstruktioner med de introducerade semantiska modifierarna , vilket gör det möjligt att eliminera en betydande mängd redigeringar när man introducerar ny funktionalitet, förenkla kompilatorn, vilket gör det kod mer tillgänglig för förståelse och modifiering, och ger också enkel inlärning och användning av språket. Modifierare omges av klammerparenteser {} efter ett variabelnamn, typ eller nyckelord. Till exempel konstruktionen:

VAR Exempel2 : PROCEDUR { REALTIME , C } ( VAR låg , hög : LONGINT ): BOOLEAN ;

deklarerar en procedurvariabel Exempel2 som pekar på en realtidsprocedur med CCALL-anropskonventionen som tar två långa heltalstypparametrar och returnerar ett booleskt värde.

Beskrivningen av objektet, i allmänhet, motsvarar beskrivningen av modulen , förutom rubriksyntaxen och frånvaron av IMPORT-avsnittet. Metoder beskrivs helt i objektbeskrivningen, operationer, med sällsynta undantag, kan beskrivas utanför objektets kropp. Ett objekt kan ha ett godtyckligt antal initialiserare och inte mer än en slutbehandlare . Den NYA inbyggda proceduren , som används för att skapa variabler av en referenstyp, anropar en initialiserare vald av kompilatorn baserat på parametrarnas signatur. Initialiseraren är markerad med & framför metodnamnet. En finalizer, en metod utan parametrar som föregås av ett ~ -tecken , anropas automatiskt när ett objekt kasseras.

En sekvens av satser omslutna av BEGIN END- satsparenteser kallas ett satsblock . Utlåtandeblocket kan också innehålla en lista med modifierare och en garanterad komplettering ( FINALLY ) sektion.

En variabel, såväl som ett fält för en post eller ett objekt, kan initieras med ett konstant uttryck när de deklareras:

TYP Punkt = RECORD x := 0 , y := 0 : LONGINT ; SLUT ; VAR i := 0 , j := 10 , k := 100 : HELTAL ; Point : Point ; (* x, y-fälten i posten initieras till 0 *)

Datatyper

Språket erbjuder en rik uppsättning inbyggda typer:

  • Grundläggande typer
    • boolean: BOOLEAN ;
    • tecken: CHAR8 , CHAR16 , CHAR32 och CHAR- aliaset för standardteckentypen;
    • signerade heltal: SIGNED8 , SIGNED16 , SIGNED32 , SIGNED64 och alias SMALLINT , INTEGER , LONGINT , HUGEINT ;
    • osignerade heltal: UNSIGNED8 , UNSIGNED16 , UNSIGNED32 , UNSIGNED64 ;
    • verklig: REAL , LONGREAL ;
    • komplex: KOMPLEX , LÅNGKOMPLEX ;
    • maskinberoende: STORLEK , ADRESS ;
    • set: SET, SET8, SET16, SET32, SET64 ;
    • expanderbara enums: ENUM ;
  • strukturell
    • arrayer: ARRAY  - statisk, dynamisk, öppen, matematisk;
    • utdragbara strukturer: RECORD ;
    • objekt: OBJECT ;
  • Särskild
    • processuella;
    • delegater: procedurvariabler som är kompatibla med både förfaranden och metoder;
    • maskinskrivna pekare till strukturella typer;
    • generiska pekare: ANY , OBJECT , ARRAY ;
  • system: SYSTEM.BYTE

Multithreading

För Active Oberon implementeras två multithreading-modeller, baserade på Brinch Hansens och Tony Hoares arbete [3] :

Källkod skriven med Active Oberons primitiva syntax för blockerande synkronisering kan användas för båda modellerna av multithreading - kompilatorn kommer att generera koden som behövs för en viss modell. Med detta tillvägagångssätt finns det inget behov av att skriva om programvara för olika modeller. Endast små delar av källkoden kräver anpassning (såsom avbrottshantering) för att undertrycka automatisk generering av omkopplare i en given del av maskinkoden. För att göra detta markeras satsblocket med modifieraren {UNCOOPERATIVE} .

Aktiva objekt

En tråd är inkapslad i ett objekt och, som en integrerad del av det, skapas i det ögonblick som det aktiva objektet instansieras . För att indikera aktiviteten hos ett objekt markeras dess kropp med AKTIVA modifieraren .

Efter att objektinstansen har tilldelats exekveras initialiseraren (om någon) och sedan objektets kropp (om någon). Om objektet är markerat som aktivt skapas en aktivitet där kroppen av objektet exekveras asynkront, annars utförs exekveringen synkront på tråden där instansen skapades.

Aktiviteten för ett objekt slutar när exekveringen av objektets kropp är klar. Medan kroppen exekveras fortsätter objektet att existera, även om det inte finns några referenser till det. Därefter blir föremålet passivt och kan kasseras enligt de vanliga reglerna.

Ett exempel på att beskriva och använda ett aktivt objekt:

MODUL Exempel3 ; TYP ActiveObject = OBJECT VAR- läge : SET ; PROCEDUR & Nytt ; BÖRJA tillstånd := {}; SLUT Nytt ; PROCEDUR & Init * ( tillstånd : SET ); BÖRJA SJÄLV . tillstånd := tillstånd ; END Init ; PROCEDUR ~ Slutföra ; BÖRJA ... END Slutför ; BÖRJA { AKTIV } ... END ActiveObject ; VAR objekt : ActiveObject ; BÖRJA NYTT ( objekt ); objekt . Init ( { 0 .. 7 , 9 , 12 , 30 .. 31 } ); NYTT ( objekt , {} ); SLUT Exempel3 . Kommunikation mellan processer

Anrop till metoder för delade aktiva och inaktiva objekt fungerar som en kommunikationsmekanism mellan aktiva objekt. Eftersom aktiva objekt existerar i en flertrådig miljö tillhandahålls en mekanism för att koordinera samtidig åtkomst till deras tillstånd. Interaktion genom meddelandehantering kan utföras med hjälp av speciella mjukvaruramverk [5] .

Samtidighetsskydd

Ett block av satser markerade med EXCLUSIVE- modifieraren kallas en exklusiv region . Det exklusiva området i Active Oberon motsvarar begreppet Hansens kritiska område [6] . Om den exklusiva omfattningen täcker hela metoden kallas den för en exklusiv metod (exklusiv metod) och kombinerar Hansens koncept med Hoare-monitorproceduren [ 7 ] [8] . Till skillnad från en monitorprocedur behöver inte en objektmetod vara exklusiv, i vilket fall den kan observera inkonsekventa objekttillstånd. En exklusiv omfattning kan ha högst en aktivitet åt gången.

Säkerhetsmodellen i Active Oberon är alltså en monitor placerad på en instansbaserad monitor . En modul betraktas som en enstaka instansobjekttyp, och dess procedurer kan också vara exklusiva och skydda modulen som helhet.

Huvudidén med en monitor (och ett aktivt objekt) är att en viss invariant  är associerad med monitorn - ett uttryck som bestämmer objektets konsekventa interna tillstånd och bevisar riktigheten av dess beteende [9] . Initialiserare och exklusiva metoder är språkförsedda verktyg för att upprätthålla ett objekts invarianter och dölja dess interna tillstånd. Ett objekts initialiserare ställer in dess invariant, och exklusiva metoder stödjer det. När begreppet en bildskärm kombineras med begreppet en modul, bildas en kraftfull mekanism för att strukturera operativsystem [10] [11] [12] .

Ett exempel på användning av den exklusiva sektionen:

(* Inställnings- och återställningsprocedurer utesluter varandra *) TYP MyContainer = OBJEKT VAR x , y : LONGINT ; (* Invariant: y = f(x) *) PROCEDUR Set ( x : LONGINT ); BÖRJA { EXKLUSIVT } (* ändrar x och y atomärt *) SJÄLV . x := x ; y := f ( x ) END Set ; PROCEDUR Återställ ; BÖRJA ... BÖRJA { EXKLUSIVT } (* ändrar x och y atomärt *) x := x0 ; y := y0 ; SLUT ; .... END Återställ ; END MyContainer ; Synkronisering

Till skillnad från de flesta monitorimplementeringar som använder Hoares villkorsvariabler [8] för synkronisering (baserat på Brinch Hansens [6] händelseköer ), tillhandahålls synkronisering av aktiviteter av AWAIT- operatorn , som tar som argument ett logiskt uttryck - ett villkor för att fortsätta programmet utförande i kroppen av ett föremål. För att säkerställa korrekt synkronisering måste AWAIT vara i exklusiv omfattning. Om fortsättningsvillkoret inte är uppfyllt , avbryter AWAIT aktiviteten och, om det är i en exklusiv omfattning, frigör det fångade området under avstängningens varaktighet, vilket tillåter andra aktiviteter att ändra objektets tillstånd och göra fortsättningsvillkoret sant. En avstängd aktivitet kommer bara att fortsätta köras om den kan återinträda i det exklusiva omfattningen.

Ett exempel på synkronisering inuti en delad buffert:

TYP Synkroniserare = OBJEKT VAR wake : BOOLEAN PROCEDUR Vänta ; BÖRJA { EXKLUSIVT } AWAIT ( vaken ); vaken := FALSK ; END Vänta ; PROCEDUR WakeUp ; BÖRJA { EXKLUSIVT } vaken := SANT ; END WakeUp ; END Synchronizer ;

Hantering av fel och undantag

Active Oberon saknar strukturerad undantagshantering - de hanteras centralt av runtime-miljön.

ASSERT - satsen tar som ett obligatoriskt argument ett logiskt uttryck, i händelse av överträdelse som programmet avbryts och, precis som vid exekvering av HALT ovillkorliga stop-satsen , överförs kontrollen till den centraliserade undantagshanteraren. Om villkoret för ASSERT- satsen kan utvärderas vid kompilering, genereras ett kompileringsfel om villkoret inte är uppfyllt. ASSERT- och HALT -satserna kan ha en valfri parameter, en undantagsspecifikator, som kan analyseras av hanteraren.

Efter att undantaget har hanterats, överförs kontrollen till nästa garanterade slutförande sektion ÄNTLIGEN i anropsstacken , om den finns. Sedan, om huvuddelen av det aktiva objektet är märkt med SAFE- modifieraren , kommer aktiviteten att startas om, annars avslutas aktiviteten.

Runtime Environment

Information om körtidstyper

Endast strukturella typer (matriser, poster, objekt) har information om körtidstyp (metainformation). Metainformationen lagras i en speciell struktur som kallas en Type Descriptor . Typbeskrivningen innehåller data om typerna och namnen på variabler och fält, en arvstabell, en tabell över virtuella metoder och tabeller över implementerade gränssnitt .

Minneshantering

Active Oberon använder automatisk minneshantering med en avbrytbar (förvägbar) sopsamlare i realtid [ 13] , baserad på Mark and Sweep-metoden. Sophämtaren körs på en separat tråd, och aktiviteter (trådar) som har en högre prioritet än prioritet för sophämtaraktiviteten kan pausa dess genomförande. I det här fallet är objektträdet fruset. För närvarande kan endast realtidsenheter avbryta sopsamlarens aktivitet, dynamisk minnesallokering är förbjuden i dem , och kompilatorn övervakar detta.

Minneshantering baseras på användningen av maskinskrivna minnesområden . Ett sådant avsnitt lagrar en pekare till en typbeskrivning . Med hjälp av runtime-typinformationen som finns i typbeskrivningen hittar sopsamlaren variablerna och fälten för referenstypen och markerar blocken de pekar på. Med andra ord behöver sopsamlaren inte kontrollera varje pekarliknande värde för att se om det är en giltig pekare på högen  - med hjälp av informationen från typbeskrivningen vet den exakt vilka element som ska bearbetas, vilket avsevärt ökar hastighet och noggrannhet i arbetet och minskar belastningen på processen.sopsamling. För att påskynda minnesallokeringen placeras lediga områden på fria listor som innehåller minnesblock av vissa storlekar.

Variabler av referenstyp markerade med UNTRACED- modifieraren är icke- spårbara pekare . Sådana pekare spåras inte av sopsamlaren och minnesplatserna de hänvisar till kan återvinnas när som helst om de tilldelats av runtime-miljön och det inte finns några nåbara referenser till dem som tas i beaktande av sopsamlaren. Ofta används sådana modifierare för att hantera minne som tilldelats utanför Active Oberon-körtiden, eller med osäkra pekare.

Hantera objektaktivitet

Runtime-miljön ansvarar för att allokera CPU-tid, säkerställer (tillsammans med kompilatorn) att det inte finns mer än en aktivitet i det exklusiva omfånget, säkerställer att AWAIT- villkoren kontrolleras i tid och att avbrutna aktiviteter återupptas. Fortsättningsvillkorsuttryck inom ett objekt omvärderas vid alla utgångspunkter från exklusiva omfattningar. Detta innebär att ändring av ett objekts tillstånd utanför det exklusiva tillämpningsområdet inte medför att villkoren räknas om. När flera verksamheter konkurrerar om samma exklusiva område, så anses verksamhet med uppfyllda villkor före de som endast vill ta sig in i skyddsområdet [3] [14] .

Anslutning och initiering av moduler

Active Oberon saknar medel för att direkt styra den dynamiska lastningen och lossningen av moduler. Språket erbjuder endast en importsektion ( IMPORT ), som innehåller en lista över plugin-program och en modulinitieringssektion. Körtiden måste säkerställa att plugin-program är anslutna och initierade innan den aktuella modulen initieras. Dynamisk länkning av en modul görs genom den dynamiska länkmekanismen . En modul kan inte laddas ur förrän den refereras från anslutningslistan för en annan laddad modul. För att eliminera problemet med cirkulära referenser bör modulerna därför lossas i omvänd ordningsföljd.

Hantering av fel och undantag

Traps - modulen tillhandahåller centraliserad undantagshantering. Parametrarna som accepteras av ASSERT- och HALT- satserna kan användas för att klassificera undantaget.

Efter att ha hanterat undantaget i Traps -modulen letar körtiden efter ÄNTLIGEN garanterade slutförandesektioner och överför kontrollen till dem för att utföra de sista operationerna.

Om aktiviteten är markerad med SAFE- modifieraren och det inte finns någon FINALLY- sektion i objektets brödtext, startas aktiviteten om, annars avslutas aktiviteten.

Runtime API ger möjlighet att ställa in din egen undantagshanterare.

Språktillägg

Programexempel

Hej världen!

MODUL Hello World ; IMPORTKernelLog ; _ BÖRJA KernelLog . String ( "Hej, värld!" ); SLUT Hello World .

Att lösa det klassiska problemet med leverantör och konsument

MODUL BoundedBuffers ; TYP Objekt * = OBJECT ; Buffert * = OBJEKT VAR h , n : HELTAL ; B : ARRAY * AV Artikel ; PROCEDUR Get * (): Item ; VAR x : Artikel ; BÖRJA { EXKLUSIVT } AWAIT ( n # 0 ); (*bufferten är inte tom*) x := B [ h ]; h := ( h + 1 ) MOD LEN ( B ); DEC ( n ); RETURNERA x SLUT ; PROCEDUR Put * ( x : Item ); BÖRJA { EXKLUSIVT } AWAIT ( n # LEN ( B )); (* bufferten inte full *) B [( h + n ) MOD LEN ( B )] := x ; INC ( n ) END Put ; PROCEDUR & Init ( max : HELTAL ); BÖRJA (*initiering*) NYTT ( B , max ); h : = 0 n := 0 END Init ; END Buffert ; END BoundedBuffers .

Länkar

Se även

Anteckningar

  1. Aktiv C#-projektsida Arkiverad 4 september 2011.
  2. ↑ 1 2 J. Gutknecht. Behöver fisken verkligen fjärrkontroll? A Proposal for Self-Active Objects in Oberon., 1997.
  3. ↑ 1 2 3 P.J. Muller. Active Object System. Design och multiprocessorimplementering. — ETH Zürich, 2002., Diss. ETH #14755.
  4. Florian Negele. Kombinera låsfri programmering med kooperativ multitasking för ett bärbart multiprocessorruntime-system, ETH Zürich, 2014, Diss. ETH nr. 22298
  5. Florian Negele. A2 Concurrency Framework, ETH Zürich, 3 juni 2009
  6. ↑ 1 2 P. Brinch Hansen. strukturerad multiprogrammering. Communications of the ACM, 15(7), juli 1972
  7. P. Brinch Hansen. operativsystemets principer. Prentice Hall, 1973.
  8. ↑ 1 2 C.AR Hoare. Bildskärmar: Ett struktureringskoncept för operativsystemet. Communications of the ACM, 17(10):549-557, oktober 1974.
  9. EGT Dahl. Monitorer återbesökt. I A.W. Roscoe, redaktör, A Classical Mind - Essays in Honor of C.A.R. Hoare. Prentice Hall,
    1994.
  10. JL Keedy. Om att strukturera operativsystem med bildskärmar. ACM Operating Systems Review, 13(1), januari 1979.
  11. N. Wirth. Modula: Ett språk för modulär multiprogrammering. Software - Practice and Experience, 7:3-35, 1977.
  12. N. Wirth. Användningen av Modula. Software - Practice and Experience, 7:37-65, 1977.
  13. Ulrike Glavitsch. Sophämtning i realtid i A2. Institutet för datorsystem, ETH Zürich
  14. P. Reali. Aktiv Oberon-språkrapport. — ETH Zürich, 2004.