10. Parallele Prozesse
 
zurück
10.9 Umgang mit Objekten und Typen von Prozessen und geschützen Einheiten


In diesem Kapitel wird der Umgang mit Prozeßobjekten und -typen vorgestellt.

Eine Typdefinition für einen Prozeß ist implizit eine limitierte private Typvereinbarung ("limited private"). Daher ist es nur möglich, Objekte dieses Typs anzulegen. Keine Operationen sind für solche Objekte zugelassen, auch nicht die Zuweisung oder der Vergleich, die auf private Typen noch angewendet werden dürfen.

Ein Prozeßobjekt kann an Funktionen oder an Prozeduren im Modus "IN" oder "IN OUT" übergeben werden, aber weder von Funktionen als Rückgabewert noch von Prozeduren im Modus "OUT" zurückgegeben werden, da die Zuweisung nicht erlaubt ist.


Beispiel:

with text_io;
procedure zeiger1 is
   -- Spezifikation eines Prozesses mit Diskriminante.
   task type prozess( i : integer := 0 ) is
      entry start;
      entry ende;
   end prozess;
   -- Implementierung des Prozesses.
   task body prozess( i : integer := 0 ) is
      id : integer := i;
   begin
      accept start;
      accept ende;
      text_io.put_line( "prozess " & integer'image( id ) & " ist ausgefuehrt" );
   end prozess;
   --
   function f( p : in prozess ) return boolean is
   begin
      p.start;
      return true;
   end f;
   --
   procedure p( p : in out prozess ) is
   begin
      p.ende;
   end p;
   --
   ein_prozess : prozess( 1 );
begin
   -- Start des impliziten Prozesses.
   if f( ein_prozess ) then
      text_io.put_line( "f ist OK" );
   else
      text_io.put_line( "f ist nicht OK" );
   end if;
   p( ein_prozess );
end zeiger1;


"ein_prozess" wird an "f" übergeben, dort wird der Eingang "start" aufgerufen. Danach wird "ein_prozess" an "p" übergeben und dort der Eingang "ende" aufgerufen. Damit kann sich "ein_prozess" beenden.

"f" und "p" kapseln die Eingangsaufrufe des Prozesses und erhöhen damit die Portabilität, weil nun der Funktionsumfang so in ein Paket gefaßt werden kann, daß nur "f" und "p" in der Spezifikation sichtbar sind. Dadurch bleibt dem Anwender des Paketes verborgen, ob der Rumpf "normal" oder als Prozeß implementiert ist.

Zeiger auf Prozeßtypen unterscheiden sich nicht von anderen Zeigern und unterteilen sich ebenso in typisierte und allgemeine Zeiger. Entsprechend kann kein solcher Zeiger auf ein Objekt verweisen, das nicht auf seiner Zugriffsebene liegt.

with text_io;
procedure zeiger2 is
   -- Spezifikation eines Prozesses.
   task type prozess( i : integer := 0 ) is
      entry start;
      entry ende;
    end prozess;
    --
    type prozess_zeiger is access all prozess;
    -- Implementierung des Prozesses.
    task body prozess is
       id : integer := i;
    begin
       accept start;
       accept ende;
       text_io.put_line( "prozess " & integer'image( id ) & " ist ausgefuehrt" );
    end prozess;
    --
    function f( p : in prozess_zeiger ) return prozess_zeiger is
    begin
       p.start;
       return p;
    end f;
    --
    der_prozess : aliased prozess( 1 ); -- (A)
    --
    ein_prozess : prozess_zeiger := der_prozess'access; -- (A)
   -- ein_prozess : prozess_zeiger := new prozess( 1 ); -- (B)
--
begin
   -- Start des impliziten Prozesses.
   ein_prozess := f( ein_prozess );
   ein_prozess.ende;
   if ein_prozess'terminated then
      text_io.put_line( "ein_prozess ist beendet" );
   else
      text_io.put_line( "ein_prozess ist nicht beendet" );
   end if;
end zeiger2;


Die mit (A) bzw. (B) markierten Zeilen sind gegeneinander austauschbar, ohne daß sich der Ablauf des Ada-Programms ändert.

"ein_prozess" wird an die Funktion "f" übergeben, diese ruft den Eingang "start" auf und gibt den Prozeß, den sie erhalten hat, an "ein_prozess" zurück. Dann wird der Eingang "ende" aufgerufen. Damit kann sich der Prozeß, auf den "ein_prozess" verweist, beenden. Als letztes wird abgefragt, ob sich "ein_prozess" beendet hat.

Zeiger auf Prozeßtypen können, obwohl sie auf limitierte private Objekte verweisen, wie jeder andere Zugriffstyp in beliebigem Modus an Unterprogramme oder Eingänge von Prozessen übergeben werden. Ebenso können sie Rückgabewert von Funktionen sein.

Zeiger auf geschützte Objekte unterscheiden sich nicht von anderen Zeigern und unterteilen sich ebenso in typisierte und allgemeine Zeiger. Entsprechend kann kein solcher Zeiger auf ein Objekt verweisen, das nicht auf seiner Zugriffsebene liegt.

Geschützte Typen lassen sich ganz normal wie andere Datenstrukturen (z. B. skalare Typen, Reihungen oder Verbunde) als benannte Objekte anlegen oder als Typen deklarieren. Sie unterscheiden sich darin nicht von anderen Zugriffstypen. Ebenso einfach lassen sie sich allozieren und deallozieren.

Es gibt nur eine Ausnahme. Sind Eingangsaufrufe für ein alloziertes Objekt vom Typ eines geschützten Typs in der Warteschlange zu einem Eingang aufgereiht und wird dieses Objekt an die Speicherplatzverwaltung zurückgegeben, dann wird für alle Prozesse, die Eingänge dieses geschützten Objekts aufgerufen haben, die Ausnahme "program_error" ausgelöst.

Im Gegensatz hierzu ist das Verhalten beim Beenden eines laufenden Prozesses nicht definiert.


 
zurück
 Index   Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.