Parallelrechner ATARI ST?

Sicherlich nicht. Aber mit der Programmiersprache Modula ist es möglich, aus ihm so etwas wie einen Quasi-Parallelrechner zu machen. Zwei scheinbar wenig benutzte Routinen aus dem Sprachumfang von Modula 2 sind nötig, um mehrere Dinge gleichzeitig, oder - um es genauer zu sagen - quasigleichzeitig ablaufen zu lassen.

Dabei ist dieses Konzept der quasigleichzeitig ablaufenden Programme auf dem ST schon längst verwirklicht, zumal bis zu sechs Accessories und ein beliebiges weiteres Programm quasigleichzeitig ablaufen können. Wartet eines der sieben Programme auf einen Event, so dürfen die anderen währenddessen weiterarbeiten.

Quasigleichzeitig arbeitende Routinen in einem einzigen Programm hingegen findet man kaum. 1st Word Plus ist ein Beispiel für diese wenigen Programme. Der Druck- und Ediervorgang laufen getrennt nebeneinander ab.

Wenden wir uns wieder Modula 2 zu. Wie schon erwähnt, ist es möglich, mit zwei Standardroutinen quasigleichzeitige Prozesse oder Coroutinen einzurichten. Dies ist einerseits Newprocess und andererseits Transfer.

Newprocess dient zur Einrichtung von Coroutinen, Transfer zum Umschalten zwischen der Coroutinen.

Newprocess werden als Parameter eine parameterlose Prozedur, eine Adresse für die lokalen Variablen der Coroutine und die Länge dieses Speicherplatzes übergeben. Zurückgegeben wird die Adresse der neuen Coroutine. Transfer übergibt man die Adresse der Quell- und der Zielroutine. Damit wären schon beide Routinen eingeführt.

Grundsätzlich werden die folgenden Schritte ausgeführt:

  1. Einrichten der neuen Coroutinen,
  2. Start der Coroutine mittels Transfer (ein anderer Start ist nicht möglich!) und
  3. Umschalten zwischen den Coroutinen.

Das Programmbeispiel verdeutlicht die Wirkung der Coroutinen. Der Bildschirm wird in zwei Hälften unterteilt. Für die linke Hälfte ist die Prozedur Proc1 und für die rechte Proc2 zuständig. Nach dem Start des Beispielprogrammes werden beide Hälften des Bildschirms quasigleichzeitig benutzt. Es entstehen fast gleichzeitig beide Linienmuster! Daß dieses nur fast gleichzeitig abläuft, kann man höchstens daran merken, daß der Musteraufbau geringfügig langsamer abläuft als bei einer einzelnen Routine.

Neben der Umschalterei zwischen den Coroutinen wurden noch zwei weitere Variablen eingeführt: Status1 und Status2. Sie sollen den Status der beiden Routinen beinhalten. Ist ein Status wert TRUE, bedeutet das, daß die entsprechende Coroutine noch ausgeführt werden kann. Somit kann es nicht zu Fehlern bei einem unnötigen Aufruf der anderen Coroutine kommen, denn Coroutinen können grundsätzlich nur mit Transfer gestartet und auch wieder verlassen werden!

Noch ein Hinweis zu eigenen Projekten. Ein Austausch von Werten zwischen den Coroutinen ist beispielsweise über globale Variablen möglich. Dabei ist aber unbedingt darauf zu achten, daß nicht eine Coroutine einen globalen Wert verändert, den die andere noch in seinem Ursprungszustand benötigt.

Literatur:

Niklaus Wirth, Programmieren in Modula-2, Springer 1985

(* Modul zur Demonstration der Routinen NEWPROCESS und TRANSFER *)
(* Geschrieben mit Megamax Modula 2.                         dr *)
MODULE NewProcessExp;

FROM GrafBase       IMPORT Pnt;
FROM GEMEnv         IMPORT InitGem,ExitGem,RC, CurrGemHandle, DeviceHandle,GemHandle; 
FROM VDIControls    IMPORT ClearWorkstation;
FROM VDIOutputs     IMPORT Line;
FROM SYSTEM         IMPORT NEWPROCESS,TRANSFER,ADR,ADDRESS;

TYPE Buffer = ARRAY [0..1023] OF CHAR; (* Puffer für lok. Var. *)

VAR BufferProc1,BufferProc2     : Buffer;  (* Puffer *) 
    Process0,Process1,Process2  : ADDRESS; (* Process-Adresse *) 
    StatusProc1,StatusProc2,               (* Status aktiv/passiv *) 
    success                     : BOOLEAN;
    Device                      : DeviceHandle;
    gemHandle                   : GemHandle;

(* Procedure 1 *)
PROCEDURE Proc1;

    VAR j : CARDINAL;

    BEGIN
        j:=0;                              (* Linienmuster *)
        REPEAT
            Line(Device,Pnt(0,0),Pnt(319,j));
            IF StatusProc2 THEN 
                TRANSFER(Process1,Process2) (* -> anderer Process *)
            END;
            INC(j, 2)
        UNTIL j>399;
        j:=0;                              (* Linienmuster *)
        REPEAT
            Line(Device,Pnt(319,399),Pnt(0,399-j));
            IF StatusProc2 THEN 
                TRANSFER(Process1,Process2) (* -> anderer Process *)
            END;
            INC(j,2)
        UNTIL j>3 99;
        StatusProc1:=FALSE;                (* Proc1 passiv *)
        TRANSFER(Process1,Process0)        (* -> zurück *) 
    END Proc;

(* Procedure 2 *)
PROCEDURE Proc2;

    VAR i : CARDINAL;

    BEGIN
        i:=0;                              (* Linienmuster *)
        REPEAT
            Line(Device,Pnt(320+i,0),Pnt(639-i, 399) ) ;
            IF StatusProc1 THEN 
                TRANSFER(Process2,Process1) (* -> anderer Process *)
            END;
            INC(i,2)
        UNTIL i>319;
        i:=0;                              (* Linienmuster *)
        REPEAT
            Line(Device,Pnt(320,i),Pnt(639,399-i));
            IF StatusProc1 THEN 
                TRANSFER(Process2,Process1) (* -> anderer Process *)
            END;
            INC (i,2)
        UNTIL i>399;
        StatusProc2:=FALSE;     (* Proc2 passiv *)
        TRANSFER(Process2,Process1)        (* -> zurück *) 
    END Proc2;

BEGIN
    InitGem(RC,Device,success); (* Initialisierung *) 
    IF success THEN 
        gemHandle:=CurrGemHandle();

        (* neue Coroutinen einrichten *)
        NEWPROCESS(Proc1,ADR(BufferProc1),SIZE(BufferProc1),Process1); 
        NEWPROCESS(Proc2,ADR(BufferProc2),SIZE(BufferProc1),Process2);

        ClearWorkstation(Device); (* Bildschirm löschen *)
        Process0   :=NIL;       (* Coroutine0 = NIL *)
        StatusProc1:=TRUE;      (* Status Process1 aktiv *)
        StatusProc2:=TRUE;      (* Status Process2 aktiv *)
        TRANSFER(Process0,Process1); (* Process1 starten *)
        ExitGem(gemHandle)      (* Ende *)
    END
END NewProcessExp.

Dietmar Rabich
Aus: ST-Computer 06 / 1989, Seite 85

Links

Copyright-Bestimmungen: siehe Über diese Seite