next up previous contents index
Next: Managertasks Up: L3 Referenzhandbuch Previous: Ein-/Ausgabe auf dem Bildschirm

Intertask Kommunikation

Einführung

Jeglicher Informationsaustausch in einem L3 System erfolgt durch Versand einer Botschaft von einer Task an eine andere. Eine Task ist der Sender, die andere der Empfänger einer Botschaft. Prinzipiell kann jede Task irgendwelche Botschaften an irgendeine andere senden. Eine Botschaft wird jedoch vom avisierten Empfänger nur angenommen, wenn der Empfänger seine Empfangsbereitschaft hergestellt hat. Die Kommunikation ist synchron. Eine Task kann empfangsbereit für Sendungen einer bestimmten Task sein (geschlossenes Warten) oder auch empfangsbereit für Sendungen jeder beliebigen Task (offenes Warten). Der Sende-/Empfangsvorgang ist atomar. Es gibt nur die Zeit vor der Übermittlung einer Botschaft und die Zeit nach der Übermittlung. Der Fall, daß eine Botschaft »teilweise empfangen« wurde, ist nicht möglich. Die eigentliche Übermittlung einer Botschaft ist logisch zeitlos.

Tatsächlich kann die Übermittlung sehr wohl einige Zeit benötigen, z.B. wenn mehrere lange Bytestrings übertragen werden. Es ist sogar der Fall denkbar, daß der Rechner ordnungsgemäß abgeschaltet wird und eine Botschaftübermittlung faktisch vor dem Abschalten und dem damit verbundenen Fixpunkt begann und nach dem Wiedereinschalten beendet wird. Trotzdem garantiert der Systemkern für die beiden beteiligten Tasks die Atomizität des Botschaftstransfers.

Die Objekte der Kommunikation, die Botschaften, sind strukturierte Datenobjekte. Die Struktur und der Inhalt einer Botschaft sind im Botschaftsvektor der Task beschrieben. Der Botschaftsvektor, der ein Teil des Prozeßkontrollblocks einer jeden Task ist, ist ein String von 32 Doppelworten. In diesen String werden in beliebiger Mischung und Anordnung Einträge für Botschaftsobjekte der Typen INT, Bytesequenz (z.B. TEXT) oder DATASPACE gemacht. Ein Eintrag für INT und DATASPACE ist ein Doppelwort, ein Bytesequenz-Eintrag zwei Doppelworte lang. Eine Botschaft kann einen bis sechzehn Integer, einen bis sechzehn Datenräume, einen bis sieben Texte oder beliebige Mischungen daraus bis zur maximalen Eintragslänge von sechzehn Doppelworten aufnehmen.

Der Aufbau einer Botschaft wird vom Absender durch Initialisierung des Botschaftsvektors mit der Prozedur new msg eingeleitet. put msg (param) »füllt« den Botschaftsvektor mit Objekten des definierten Typs. Die fertige Botschaft wird dann durch send oder call an den Empfänger geschickt.

Der Empfänger initialisiert ebenfalls seinen Botschaftsvektor (new msg) und spezifiziert durch invite msg (param) den Aufbau der erwarteten Botschaft. Anschließend geht die empfangswillige Task in geschlossenes Warten (receive) oder offenes Warten (wait) über. Nach Empfang der Botschaft wird der Botschaftsvektor durch get msg (param) ausgewertet.

Beispiel:

(* TASK sender *) 
 
(*1*)    INT VAR result, integer := 1234 ; 
(*2*)    TEXT VAR string := "Hallo Empfänger!" ; 
(*3*)    DATASPACE VAR space := dataspace (std); 
 
(*4*)     new msg; 
(*5*)     put msg (integer); 
(*6*)     put msg (string); 
(*7*)     put msg (space); 
(*8*)         send (/"empfänger",never,result); 
 
(*9*)     IF result = communication ok 
             THEN putline ("O.K.") 
             ELSE putline ("K.O.") 
          FI; 
 
 
 
(* TASK empfänger *) 
 
(*10*)   INT VAR my int, maxlength := 40, 
                 result; 
 
         TEXT VAR textvar := ""; 
         DATASPACE VAR rec ds; 
 
(*11*)   new msg; 
(*12*)   invite msg (int msg); 
(*13*)   invite msg (string msg, textvar, maxlength); 
(*14*)   invite msg (int msg); 
(*15*)   invite msg (ds msg ); 
(*16*)      receive (/"sender",never,result); 
(*17*)   get msg (my int); 
(*18*)   get msg (textvar); 
(*19*)   get msg (rec ds); 
 
(*20*)   FILE VAR f := sequential file (output, logfile); 
         putline (f, (text (my int))); 
         putline (f, (textvar)); 
         putline (f, (text (index (rec ds)))); 
 
  (* So kann der Inhalt des empfangenen Datenraums *) 
  (* in eine Textdatei kopiert werden: *) 
 
         copy (rec ds, "neue datei um " + time) ;

Dieses Beispiel skizziert den Ablauf einer einmaligen Botschaftsübermittlung zwischen einem Sender und einem Empfänger. In der sendenden Task wird zunächst der Inhalt der Botschaft festgelegt. Es sollen die Zahl '1234', der Text 'Hallo Empfänger!' und ein Datenraum, der die zuletzt benutzte Datei enthält (wird durch die PROC std geliefert) an die Task 'empfänger' geschickt werden.

Diese in Zeile 1 bis 3 deklarierten Objekte werden nach Initialisierung des Botschaftsvektors (Zeile 4) durch put msg in den Botschaftsvektor eingetragen (Zeile 5 bis 7). Die eigentliche Übertragung (Zeile 8) erfolgt mit der Option never (ggf. beliebig lange auf Empfangsbereitschaft des Empfängers warten) für das Sende- Timeout.

Anschließend wird das vom Systemkern in 'result' gelieferte Ergebnis der Operation ausgewertet.

Der Empfänger legt ebenfalls Objekte für den Empfang der erwarteten Botschaft fest (10), initialisiert seinen Botschaftsvektor (11) und bestimmt die Interpretation der erwarteten Objekte (invite msg (..) ).

Hinweis: da Texte als Bytestrings verschickt werden (Zeile 14), muß die empfangende Task zwei Abschnitte des Botschaftsvektors freihalten. Siehe dazu den folgenden Abschnitt über den Aufbau des Botschaftsvektors.

Anschließend geht die empfangende Task in den Zustand »geschlossenes Warten« (Botschaften werden nur von 'sender' akzeptiert (Zeile 16)). Nach Empfang einer Botschaft wird der Inhalt des Botschaftsvektors in die entsprechenden Variablen übernommen (Zeile 17 bis 19) und in einer Datei protokolliert (Zeile 20).

Die wesentliche Erkenntnis an dieser Stelle soll sein, daß zwischen Sender und Empfänger eine Absprache über den Aufbau der gesendeten und erwarteten Botschaft existieren muß, da durch nachträgliche Inspektion der Inhalt einer empfangenen Botschaft nicht sicher entschlüsselt werden kann.

Solche Absprachen sind für wichtige Bereiche der Intertask Kommunikation bereits getroffen. Ihre Beschreibung ist Inhalt von Kapitel 13 ff.: Protokolle.

Achtung: Über die Intertask Kommunikation wird nicht nur die von Ihnen programmierte Kommunikation abgewickelt, sondern zum Beispiel auch die normale Ein/Ausgabe.

JEDE EINGABE/AUSGABE OPERATION BENUTZT DEN BOTSCHAFTSVEKTOR.

Der Botschaftsvektor wird also von Testausgaben gegebenenfalls zerstört !

Würde also im vorangegangenen Beispiel zwischen Zeile 16 und Zeile 17 das Kommando putline ("Die Nachricht ist angekommen") eingefügt, wäre der Botschaftsvektor der empfangenden Task zerstört und sie könnte die für sie bestimmte Nachricht nicht mehr korrekt auswerten.

Das Programm

new msg; 
put msg (int msg); 
put msg (ds msg) 
    put ("HALLO"); 
...

ist folgendermaßen zu lesen:

initialisiere den Botschaftsvektor; 
erster Abschnitt wird Integer; 
zweiter Abschnitt wird Datenraum; 
   initialisiere den Botschaftsvektor; (* !!!!! *) 
   erster Abschnitt wird Integer ; (*'Gib-aus Code'*) 
   zweiter Abschnitt wird Text   ; (* 'HALLO' *) 
       call (/"my display", never, never, result); 
....

Der Aufbau des Botschaftsvektors

Der Botschaftsvektor ist ein 128 Byte langer Abschnitt im Prozeßkontrollblock einer Task.

MDV  RDV  B1  B2 .... B15  B16  E1  E2 .... E13  E14

Die Doppelworte 'MDV' und 'RDV' beschreiben die Typen der folgenden Einträge, B1 bis B16 sind Botschaftsabschnitte, E1 bis E14 Eigenadressen.

MDV: Message Dope Vector.
Der Message Dope Vektor beschreibt die Typen der zu sendenden Datenobjekte in den Botschaftsabschnitten B1 bis B16. Der Inhalt wird implizit durch die put msg Operationen beim Aufbau der Sendung erzeugt. Für jeden Abschnitt B1 bis B16 wird in zwei Bit der Typ festgehalten. MDV wird durch new msg gelöscht.

RDV: Receive Dope Vector.
Der Receive Dope Vektor beschreibt die Typen der zu empfangenden Datenobjekte in den Botschaftsabschnitten B1 bis B16. Der Inhalt wird implizit durch die invite msg Operationen beim Empfangsaufbau erzeugt. Für jeden Abschnitt B1 bis B16 wird in zwei Bit der Typ festgehalten. RDV wird durch new msg gelöscht.

B1 bis B16: Botschaftsabschnitte.
Die Botschaftsabschnitte enthalten die eigentlichen Botschaften in Form von Integer Einträgen. Die Interpretation dieser Einträge unterliegt folgender Systematik:

Sender vor der Sendung:
int msg:
der Abschnitt Bx enthält die Zahl.
ds msg:
der Abschnitt Bx enthält den internen Datenraumbezeichner.
string msg:
der Abschnitt Bx+1 enthält die Startadresse des Bytestring in der Task. Der Abschnitt Bx enthält die Stringlänge.

Nach erfolgreicher Sendung ist ein gesendeter Datenraum gelöscht. INTs oder Strings werden als Kopien versendet.

Empfänger nach der Sendung:
int msg:
der Abschnitt Bx enthält die Zahl.
ds msg:
der Abschnitt Bx enthält den internen Datenraumbezeichner des empfangenen Datenraums.
string msg:
der Abschnitt Bx enthält die Stringlänge des Bytestring. Der Abschnitt Ex+1 enthält die Adresse.

Da der Empfänger im Falle der string msg eine Fremdadresse erhält, muß noch die Angabe eines geeigneten Platzes im eigenen Adreßraum folgen. Nur zu diesem Zweck werden die Eigenadressen E1 bis E14 benötigt.

E1 bis E14: Eigenadressen
In diesem Abschnitt werden für string msg die Adresse und die akzeptierte Länge für den jeweiligen Bytestring im eigenen Adreßraum festgehalten. Die Einträge werden z.B. durch PROC invite msg (INT CONST typ, TEXT VAR string, INT CONST max length) implizit vorgenommen.

Dieser Abschnitt des Botschaftsvektors wird also nur benutzt, wenn Bytestrings empfangen werden sollen.

Prozeduren und Konstanten

Die ELAN Schnittstelle zur Intertask-Kommunikation umfaßt neben den Prozeduren zum Aufbau von Botschaften und den Sende-/Empfangsoperationen auch noch eine Reihe vom Konstanten zur Auswertung von Botschaften und Antworten.

tabular5855

tabular5860

Der Aufbau von Botschaften

new msg

PROC new msg

Wirkung: Initialisierung des Botschaftsvektors der Task, um den Kommunikationsaufbau zu beginnen.
Bemerkung: Der (interne) Zähler für die Einhaltung der maximal zulässigen Botschaftsvektorlänge, der durch put, get, invite hochgezählt wird, wird auf 0 zurückgesetzt. Ein Botschaftsvektor kann nicht teilweise neuaufgebaut werden, wenn ein Fehler aufgetreten ist.

Botschaftsabschnitte und Eigenadressen werden nicht gelöscht. Bei Analyse des Botschaftsvektors können also durchaus noch alte Inhalte in diesen Abschnitten enthalten sein.

put msg

PROC put msg (INT CONST int)

Wirkung: In den nächsten Abschnitt des Botschaftsvektors wird der INTEGER Wert 'int' eingetragen.

PROC put msg (DINT CONST int)

Wirkung: In die nächsten beiden Abschnitte des Botschaftsvektors wird der DINT Wert 'dint' als int msg, int msg eingetragen.

PROC put msg (INT CONST bool)

Wirkung: In den nächsten Abschnitt des Botschaftsvektors wird der BOOLsche Wert 'bool' als int msg eingetragen.

PROC put msg (DATASPACE VAR ds)

Wirkung: In den nächsten Abschnitt des Botschaftsvektors wird der Wert des Datenraumbezeichners 'ds' eingetragen. 'ds' selbst wird ungültig. Nach Ausführung der send bzw. call Operation ist der Datenraum gelöscht. Falls eine Kopie des Datenraumobjekts 'ds' an die empfangende Task geschickt werden soll, muß vor send oder call eine Kopie, die in der sendenden Task verbleibt, angelegt werden. Da der Datenraumbezeichner schon beim Eintrag in den Botschaftsvektor gelöscht wird, kann der Datenraum über den Bezeichner anschließend nicht mehr erreicht werden. Falls die send/call Operation nicht durchgeführt werden kann, sollte der Bezeichner wieder aus dem Botschaftsvektor mit get msg in den Bezeichner zurückgelesen werden, damit der Datenraum nicht als »Leiche« in der Task verbleibt.

PROC put msg (TEXT CONST string)

Wirkung: In die nächsten beiden Abschnitte des Botschaftsvektors wird der Text 'string' als Typ string msg eingetragen. Im Botschaftsvektor stehen aktuelle Länge und Adresse von 'string'.

PROC put msg (INT CONST stringaddr, stringlength)

Wirkung: In die nächsten beiden Abschnitte des Botschaftsvektors wird der Wert 'stringlength' und die Adresse 'string addr' als string msg eingetragen. Damit lassen sich beliebige Bytesequenzen übertragen.
Bemerkung: Eine Bytefolge, die übertragen werden soll, muß nicht unbedingt im Standarddatenraum stehen, sondern kann aus einem beliebigen Datenraum der Task sein.

invite msg

PROC invite msg (INT CONST typ)

Wirkung: Der nächste Botschaftsabschnitt, der erwartet wird, soll vom Typ 'typ' sein. Zulässige Typen sind int msg, ds msg oder int msg OR ds msg.
Bemerkung: Die leere Botschaft nil msg darf nicht als Botschaft erwartet werden. Der Empfang eines Botschaftsabschnitts von Typ string msg bedarf weiterer Parameter, da nicht feststeht, wohin die Bytesequenz geschrieben werden soll und wieviel Platz sie benötigen wird. Die grundsätzliche Bereitstellung von maxtextlength Bytes würde zu starken Ineffizienzen führen.

PROC invite msg (INT CONST typ, TEXT VAR string, INT CONST max length)

Wirkung: Der nächste Botschaftsabschnitt, der erwartet wird, soll vom Typ 'typ' sein. Zulässig sind alle Typen und Kombinatioenen.
Bemerkung: Da der interne Zähler für den Botschaftsvektor durch invite msg nur um 1 erhöht wird, muß der »Einladung für einen Text« ein invite msg (int msg) folgen, um im Botschaftsvektor die benötigten zwei Doppelworte Platz zu schaffen. Die maximale Länge einer Bytefolge, die in diesem Botschaftsabschnitt empfangen werden kann, ist durch die angegebene 'max length' bestimmt.

PROC invite msg (INT CONST typ, stringaddr, max length)

Wirkung: Der nächste Botschaftsabschnitt, der erwartet wird, soll vom Typ 'typ' sein. Zulässige Typen sind alle Typen und Kombinationen. Bei Empfang eines Botschaftsabschnitts vom Typ string msg wird dieser an der explizit angegebenen 'stringaddr' mit der Länge 'max length' geschrieben.
Bemerkung: Da der interne Zähler für den Botschaftsvektor durch invite msg nur um 1 erhöht wird, muß der »Einladung für einen Text« ein invite msg (int msg) folgen, um im Botschaftsvektor die benötigten zwei Doppelworte Platz zu schaffen. Die maximale Länge einer Bytefolge, die in diesem Botschaftsabschnitt empfangen werden kann, ist durch die vorgegebene 'max length' bestimmt.

ACHTUNG: 'stringaddr' muß im Standarddatenraum der Task liegen.

get msg

PROC get msg (INT VAR int)

Wirkung: Der nächste Botschaftsabschnitt wird in die INTEGER Variable 'int' kopiert.

PROC get msg (DINT VAR dint)

Wirkung: Die nächsten beiden Abschnitte werden in die DINT Variable 'dint' kopiert. Die beiden Botschaftsabschnitte müssen als int msg erwartet worden sein.

PROC get msg (BOOL VAR bool)

Wirkung: Der nächste Botschaftsabschnitt wird in die BOOLsche Variable 'bool' kopiert. Er muß als int msg erwartet worden sein.

PROC get msg (DATASPACE VAR ds)

Wirkung: Der nächste Botschaftsabschnitt wird in die DATASPACE Variable 'ds' kopiert. Er muß als ds msg erwartet worden sein.
Bemerkung: Falls das Senden eines Datenraums nicht erfolgreich war, muß mit dieser Prozedur wieder in die Datenraumvariable zurückgeschrieben werden.

PROC get msg (TEXT VAR string)

Wirkung: Die nächsten beiden Botschaftsabschnitte werden benutzt, um die Bytefolge, deren Adresse und Länge dort enthalten ist, in die Textvariable 'string' zu kopieren.
Bemerkung: Falls diesem Aufruf von get msg ein Aufruf von invite msg mit derselben Textvariablen 'string' voranging, muß der Text nicht noch einmal kopiert werden.

Fehler: Falls sehr lange Strings empfangen werden sollen, muß als Empfangspuffer die Zielvariable selbst verwendet werden:
TEXT VAR buffer ; 
new msg; 
invite msg (buffer, 32000); 
wait(...);
get msg (buffer);

Falls der empfangene String in einer anderen Variablen benötigt wird, muß anschließend kopiert werden.

Folgendes Vorgehen bietet nämlich eine wunderliche Fehlerquelle:

TEXT VAR buffer, tvar ; 
new msg; 
invite msg (buffer , 32000); 
wait (...);
get msg (tvar)   (* sehr fehleranfällig !! *)

Es kann bei diesem Vorgehen vorkommen, daß der Empfang in der Textvariablen 'tvar' eine Müllabfuhr auf dem Textheap des Standarddatenraums auslöst, die die Quelle 'buffer' verschiebt. In diesem Falle wird der String von einer falschen Anfangsadresse an kopiert.

Eine andere Möglichkeit, diese Fehlerquelle auszuschließen, besteht darin, als Empfangspuffer eine ROW 32000 BYTE zu definieren.

PROC get msg (INT VAR stringaddr, stringlength)

Wirkung: Die nächsten beiden Botschaftsabschnitte werden als Bytefolge interpretiert. Die Bytefolge wird dann ab der Adresse 'stringaddr' in der Länge 'stringlength' in den Standarddatenraum kopiert.

Beispiel:
(************************************************) 
(* Dieses Programm in Task "empfänger" starten  *) 
(************************************************) 
 
TASK VAR sender ; 
LET RBUFFER = ROW 100 BYTE ; 
RBUFFER VAR bufa, bufb, bufc; 
 
INT VAR res, intvar1, intvar2 , 
        in addr := ADDR bufa(1) , 
        in length := 100 ; 
           (* Hier kann man sich selbst umzingeln *) 
           (* Falls der Wert > Puffer ist, wird *) 
           (* hinter dem Puffer überschrieben *) 
new msg; 
invite msg (  string msg , in addr      , in length); 
           (* bytestring , Adr im Stdds , soviel darfs sein *) 
 
wait (50000 , sender , res); 
 
get msg (intvar1, intvar2) ; 
 
(***********************************************) 
(* Anschließend dieses in der sendenden Task   *) 
(***********************************************) 
 
TASK VAR partner := task ("empfänger") ; 
INT VAR res , i ; 
LET SBUFFER = ROW 100 BYTE ; 
SBUFFER VAR sbuf1, sbuf2, sbuf3; 
 
FOR i FROM 1 UPTO  100 
REP 
   sbuf1 [i] := byte (i ) 
PER; 
 
new msg; 
put msg (ADDR sbuf1 [1] , 300) ; 
send (partner, 1000 , res); 
IF res = communication ok THEN put ("OK") FI ;

Allgemein gilt: Falls bei einer get msg Operation keine Übereinstimmung des Typs des erwarteten und des gelieferten Abschnitts besteht, ist die Wirkung dieser und aller folgenden get msg Operationen undefiniert. Dieser Zustand wird erst durch Initialisierung des Botschaftsvektors mit new msg beendet.

msg type

INT PROC msg type

Wirkung: Liefert den Typ des nächsten zu empfangenden Botschaftsabschnitts.

Konstanten

Um bei Definition und Auswertung der erwarteten Botschaftsabschnitte mit sprechenden Namen arbeiten zu können, sind folgende Konstanten vordefiniert.

INT PROC ds msg

Wirkung: Liefert den Abschnittstyp Datenraum.

INT PROC int msg

Wirkung: Liefert den Abschnittstyp Integer.

INT PROC nil msg

Wirkung: Liefert den Abschnittstyp leere Botschaft.

INT PROC string msg

Wirkung: Liefert den Abschnittstyp Textstring.

INT PROC never

Wirkung: Liefert den Wert »kein Timeout« für Timeout Angaben bei Sende- und Empfangsoperationen.

Die Resultatkonstanten communication ok, task not existing, send timeout und receive timeout werden im Abschnitt über Sende- und Empfangsoperationen erläutert.

Zwischenspeichern

Um initialisierte Botschaftsvektoren vor Überschreiben zu schützen, können sie in einen Stack gebracht werden, der maximal 100 Vektoren aufnehmen kann. Dies kann insbesondere nötig werden, wenn vor dem Absenden oder Auswerten des Botschaftsvektors irgendwelche Ausgaben gemacht werden sollen.

pop msg

PROC pop msg

Wirkung: Das oberste Element des Stacks wird zum aktuellen Botschaftsvektor.
Fehler: "Unterlauf des Botschafts-Stack" Es ist kein Botschaftsvektor auf dem Stack.

push msg

PROC push msg

Wirkung: Der aktuelle Botschaftsvektor wird auf dem Stack abgelegt.
Fehler: "Überlauf des Botschafts-Stack" Der Stack ist bereits gefüllt. Er enthält 100 Botschaftsvektoren.

delete msg

PROC delete msg

Wirkung: Löscht das oberste Element im Stack.
Fehler: "Unterlauf des Botschafts-Stack" Es ist kein Botschaftsvektor auf dem Stack.

Senden und Empfangen

Der Botschaftstransfer, die Übermittlung des Inhalts des Botschaftsvektors der sendenden Task zum Botschaftsvektor der empfangenden Task kann stattfinden, wenn der Empfänger seine Empfangsbereitschaft hergestellt hat. Der Empfänger stellt durch wait oder receive seine Empfangsbereitschaft her und eine vom Sender durch send oder call abgeschickte Botschaft wird empfangen. Da die Kommunikation Unwägbarkeiten unterworfen ist (z.B. kann eine Task bereits von einem anderen Kommunikationspartner vereinnahmt sein), enthält jede der Prozeduren eine Variable, in der vom System das erzielte Ergebnis geliefert wird.

Alle Operationen können durch ein Timeout limitiert werden. Wenn nach Ablauf dieser in Millisekunden angegebenen Zeitspanne der avisierte Partner nicht entsprechend reagiert hat, so wird die Operation mit einer entsprechenden Meldung beendet.

Soll kein Abbruch durch Zeitüberschreitung möglich sein, muß never als Timeout gewählt werden.

Falls bei einer send oder call Operation, in der ein oder mehrere Datenräume verschickt werden sollten, ein send timeout auftrat, sollten die Datenraumbezeichner mit get msg aus dem Botschaftsvektor geholt und ggf. gelöscht werden. Andernfalls bliebe eine Datenraumleiche in der Task zurück.

call

PROC call (TASK CONST partner, INT CONST send timeout, receive timeout, INT VAR result)

Wirkung: Die vorher zusammengestellte Botschaft wird an die Task 'partner' geschickt und eine Botschaft von 'partner' erwartet. Die Prozedur hat somit zwei Phasen, die jedoch untrennbar miteinander verbunden sind. Die erfolgreiche Durchführung von call umfaßt die Sendung der Botschaft und den Empfang der (Quittungs) Botschaft von der Zieltask. Die maximale Wartezeit auf die Empfangsbereitschaft von 'partner' wird durch 'send timeout' bestimmt. Wenn diese Zeit abgelaufen ist, ohne daß die Zieltask empfangsbereit war, wird keine Botschaft geschickt und keine Botschaft empfangen. Die maximale Wartezeit auf eine Antwort wird durch 'receive timeout' vorgegeben. Wenn diese Zeit abgelaufen ist, wurde die Botschaft geschickt, jedoch keine Botschaft empfangen.

Bemerkung: Bei erfolgreicher Durchführung liefert send (..) ; receive (..) ein identisches Resultat. Es ist jedoch der Fall vorstellbar, daß die Zieltask die Antwort schickt, bevor die eigene Empfangsbereitschaft hergestellt werden kann. In diesem Fall würde eine im Grunde korrekt verlaufene Kommunikation nicht erkannt.

Parameter: 'result' liefert das Ergebnis der call Operation.

communication ok: eine Botschaft wurde geschickt und von 'partner' empfangen. Die Antwort von 'partner' wurde empfangen.

task not existing: die Task 'partner' gibt es nicht. Es wurde keine Botschaft geschickt und keine Antwort empfangen.

send timeout: bis zum Ablauf von send timeout war die Task 'partner' nicht empfangsbereit. Es wurde keine Botschaft geschickt und keine Antwort empfangen.

receive timeout: bis zum Ablauf von receive timeout wurde keine Antwort von 'partner' empfangen. Dieses Ergebnis wird auch geliefert, wenn 'partner' gelöscht wird, bevor sie die Antwort zurückschicken kann.

Beispiel:
PROC send one receive one (TASK CONST partner, 
              INT CONST code, DATASPACE VAR ds, 
              INT VAR reply, result): 
     disable stop; 
     new msg; 
     put msg (code);   (* Sendung aufbauen *) 
     put msg (ds); 
     invite msg (int msg); (* Antwort vorbereiten *) 
     invite msg (ds msg); 
        call (partner, never, never, result); 
        IF result = communication ok 
           THEN get msg (reply); 
                get msg (ds) 
        FI 
END PROC send one receive one;
receive

PROC receive (TASK CONST sender, INT CONST receive timeout, INT VAR result)

Wirkung: Geschlossenes Warten. Nach Definition der erwarteten Botschaft wartet die Task auf eine Botschaft der Task 'sender'. Für andere Tasks ist sie nicht empfangsbereit.
Parameter: 'result' liefert das Ergebnis der receive Operation:
communication ok:
eine Botschaft wurde von 'sender' empfangen.

task not existing:
die Task 'sender' gibt es nicht.

receive timeout:
bis zum Ablauf von receive timeout wurde keine Botschaft von 'sender' empfangen oder die Task wurde gelöscht.

Bemerkung: receive (niltask, timeout, result) ist erlaubt.

send

PROC send (TASK CONST partner, INT CONST send timeout, INT VAR result)

Wirkung: Die fertige Botschaft wird an die Task 'partner' geschickt, sofern 'partner' existiert und empfangsbereit ist.

Parameter: 'result' liefert das Ergebnis der send Operation:
communication ok:
eine Botschaft wurde geschickt und von 'partner' empfangen.
task not existing:
die Task 'partner' gibt es nicht. Es wurde keine Botschaft geschickt.
send timeout:
bis zum Ablauf von 'send timeout' war die Task 'partner' nicht empfangsbereit. Es wurde keine Botschaft geschickt.

wait

PROC wait (INT CONST receive timeout, TASK VAR sender, INT VAR result)

Wirkung: Offenes Warten. Nach Definition der erwarteten Botschaft wartet die Task auf eine Botschaft von irgendeiner Task.
Parameter: 'result' liefert das Ergebnis der wait Operation:

communication ok:
eine Botschaft wurde korrekt empfangen.

receive timeout:
bis zum Ablauf von 'receive timeout' wurde keine Botschaft von 'sender' empfangen.


next up previous contents index
Next: Managertasks Up: L3 Referenzhandbuch Previous: Ein-/Ausgabe auf dem Bildschirm

Michael Hohmuth
Sun Mar 31 04:49:53 MET DST 1996