GEM-Verkehrsplanung: Aktion sauberer Bildschirm

Obwohl die GEM-Funktion »wind_update()« seit Jahren dokumentiert ist, benutzen sie immer noch viel zu viele Programme falsch oder gar nicht. Dabei geht's doch ganz einfach!

Das mangelnde Wissen um »wind_update()« ist kein Wunder: ungenügende Dokumentationen sind der Grund. Die DRI-GEM-Dokumentation verliert, ebenso wie das Atari ST Profibuch [1] oder das Geiß-Buch [2], kaum einen verständlichen Satz über diese Funktion. Deshalb beschäftigen wir uns einmal ausführlich damit.

Zunächst einmal muß gesagt sein, daß jedes »saubere« GEM-Programm vor jeder Ausgabe auf den Bildschirm die Funktion »wind_update()« aufrufen muß. Das umfaßt sowohl Veränderungen in geöffneten Dialogboxen, beispielsweise per »objc_change()«, als auch den Aufbau einer Menüleiste oder das Schließen eines Fensters. Um es noch einmal ganz deutlich zu sagen: Vor jedweder Bildschirmveränderung muß ein

wind_update (BEG_UPDATE);

Aufruf getätigt werden. Sobald der Bildschirm dann komplett aufgebaut ist, teilen Sie dies dem Betriebssystem per

 wind_update(END_UPDATE);

mit.

Was bewirken nun diese beiden Aufrufe? Sobald ein Programm oder Accessory die Funktion mit dem Parameter »BEG_UPDATE« aufruft, führt GEM erst einmal alle laufenden Grafikoperationen der anderen aktiven Programme zu Ende. Anschließend prüft das Betriebssystem (OS), ob auch andere im System befindliche Programme gerade den Bildschirm aufbauen. Dazu sieht es in einer internen Liste nach, ob irgendein anderes Programm bereits seinerseits per »wind_update« eine Bildschirmmanipulation angekündigt hat. Wenn ja, so wartet GEM erst einmal darauf, daß das gerade ausgebende Programm seine Bildschirmoperation abschließt und dies dem OS wiederum mit dem Parameter »END_UPDATE« mitteilt. Solange ein anderes Programm also ausgibt, bleibt »unser« Programm gesperrt. Sobald das Betriebssystem kein Programm mehr als »gerade mit dem Bildaufbau beschäftigt« erkennt, kann unser Programm seinerseits mit der Bildschirmausgabe beginnen und alle anderen Ausgaben sperren. Um es also noch einmal deutlich zu sagen:

»wind_update()« beendet mitnichten grundsätzlich die Bearbeitung anderer, parallel laufender Prozesse, sondern bremst diese erst dann, wenn sie eine Bildschirmveränderung ankündigen. Damit ist der reibungslose Ablauf der Ausgabe auf eine einzige virtuelle Workstation perfekt gewährleistet.

Wenn sich ein Programm dieser GEM-Vorschrift widersetzt, riskiert es, unter Umständen gleichzeitig mit einem anderen Programm oder Accessory den Bildschirm zu beschreiben: Bildstörung!

Noch etwas anderes sollten Sie bedenken: Auch der Screenmanager, der im ST beispielsweise für die Darstellung von Menübäumen verantwortlich ist, reagiert ebenfalls auf die »wind_update()«-Funktion. So verhindern Sie beispielsweise das Herunterklappen von DropDown-Menüs während des Bildaufbaus. Wer das nicht tut, zerstört einen Teil des Bildaufbaus allein schon dadurch, daß er mit der Maus in die Menüleiste fährt.

So bleibt es abschließend an uns, Sie noch einmal ausdrücklich auf ihre »Pflicht als anständiger Programmierer« hinzuweisen, die »wind_update()«-Funktion im Sinne einer ungestörten Bildschirmausgabe zu benutzen, egal, ob Sie per VDI zeichnen oder die AES-Routinen zur Darstellung von Ressourcen (»objc_draw()« etc.) benutzen.

Nun geht es an die selten verwendeten Aufrufe »wind_update (BEG_MCTRL)« und »wind_update (END_MCTRL)«.

Beim Eintreffen der »wind_update()«-Meldung mit dem Parameter »BEG_MCTRL« deklariert GEM den gesamten Inhalt der virtuellen Workstation als Fenster der aufrufenden Applikation. Damit muß die aufrufende Applikation ab sofort sämtliche Ereignisse selbst auswerten; DropDown-Menüs klappen beispielsweise nicht mehr automatisch herunter.

In der Regel finden diese Aufrufe kaum Verwendung, entscheidend wird ihre Bedeutung allerdings bei der Konstruktion eigener »form_do()«-Routinen:

Der Screenmanager sendet Tastatur-Events nämlich grundsätzlich nur an die Applikation mit dem aktuellen Fenster. Unter Umständen ist es aber notwendig, daß die eigene Applikation, also der gerade aktive Prozeß und keinesfalls irgendein anderer, alle Tastaturereignisse mitgeteilt bekommt - beispielsweise bei Accessories, die eigene Dialogboxen verwenden und darin auch auf »Shortcuts«, also Tastaturkürzel reagieren sollen. Diese Accessories bekommen nämlich normalerweise (weil Sie gar kein Fenster geöffnet haben) niemals Tastatur-Events gemeldet.

Der kleine Aufruf

wind_update (BEG_MCTRL);

beseitigt dieses Problem. In den normalen Modus, also die altbekannte Event-Steuerung, gelangen Sie wie folgt zurück:

wind_update (END_MCTRL);

Accessories haben mitunter erhebliche Probleme, benötigten Speicher anzufordern und zu behalten. Es ist jedoch durchaus auch möglich, Speicher für Accessories anzufordern, den diese auch auf Dauer behalten: Sobald nämlich ein Accessory Speicher mittels »Malloc()« anfordert, wird ein entsprechend großer Speicherblock vom GEMDOS lokalisiert und in eine interne Liste, die »allocated list« eingetragen. Dabei ist ein Accessory für GEMDOS immer Teil der aktuellen Applikation. Als Eigner (»Parent«) des Speicherblocks trägt GEMDOS folglich die Identifizierungsnummer des aktuellen Hauptprogramms ein. So lange das Hauptprogramm im Speicher liegt, existiert auch ein MD (»memory descriptor«) desjenigen Speicherblocks, den das Accessory angefordert hat. Die kritische Phase wird jedoch bei Beendigung des Hauptprogramms erreicht: Mit seinem Verschwinden erlöschen all seine reservierten Speicherblöcke und folglich auch die des Accessories. So kann es geschehen, daß sicher geglaubte Speicherblöcke von einem Moment auf den anderen aus dem Speicher verschwinden, ohne daß sich dem Accessory irgendein Ansatzpunkt bietet, wie die Daten wiederzuerlangen seien. Allenfalls eine »AC_CLOSE«-Meldung teilt dem Accessory den Exitus mit.

Das »Atari ST Profibuch« [1] rät für diesen Fall, alle Speicherblöcke freiwillig freizugeben, da das Accessory nicht eigenständig feststellen kann, ob seine Speicherblöcke ohnehin gerade verlorengegangen sind (dann waren sie für GEMDOS Bestandteil des gerade beendeten Programms) oder ob sie vielleicht doch noch erhalten sind.

Es muß also eine Methode gefunden werden, nach der Accessories wirklich sicher sein können, daß GEMDOS ihre Speicherblöcke beim Verlassen des Hauptprogramms nicht freigibt. Und die gibt es: Der GEM-Desktop ist für GEM auch nichts anderes als ein Hauptprogramm, von dem aus andere Programme gestartet werden. Mit einem entscheidenden Unterschied: Er wird nahezu nie verlassen! Und wenn er einmal verlassen wird, dann bedeutet das das Ende des GEM-Systems und damit auch das Ende der Accessories.

Somit sind wir der Lösung des Problems ein gutes Stück näher gekommen: Solange das Accessory Speicher anfordert, wenn noch gar kein Hauptprogramm außer dem Desktop gestartet worden ist, sind seine Speicherblöcke sicher: Beim Verlassen einer später gestarteten Applikation gibt GEMDOS nur genau die Speicherblöcke zurück, die während der Ausführung des Hauptprogramms angefordert worden sind. Und da unser Accessory schon vor deren Start seine Speicherblöcke angefordert hat, werden diese vom GEMDOS auch nicht berührt.

Aber: Wie stellen wir sicher, daß auch noch kein Hauptprogramm gestartet wurde, wenn unser Accessory Speicher anfordert? TOS 1.04 und spätere Versionen gestatten es, gleich beim Booten automatisch eine GEM-Applikation zu laden, ohne daß der Anwender den Desktop benutzt. Woher soll ein Accessory nun erfahren, ob ein anderes Programm als der Desktop arbeitet?

Auch diese Frage läßt sich beantworten: Mit »wind_update()«. Der GEM-Desktop ist nämlich, obwohl der Anwender davon nichts mitbekommt, für eine kurze Zeit aktiv, um einige Initialisierungen vorzunehmen, beispielsweise Accessories Zeit zu lassen, sich per »menu_register()« anzumelden. Erst nach einigen Zyklen der Prozeßumschaltung startet der Desktop die Autostart-Applikation. Die kurze Zeitspanne, die Ihrem Accessory bleibt, läßt sich nicht nur exakt treffen, sondern auch beliebig verlängern:

Sie teilen dem Desktop einfach mit, daß Ihr Accessory beabsichtigt, den Bildschirm zu verändern:

wind_update (BEG_UPDATE);

Nun muß der Desktop warten, bis Sie ihm mitteilen, der Bildaufbau sei beendet. Und als sauberes GEM-Programm tut er das auch. Dabei ist es GEM vollkommen egal, ob Sie in der nun frei dosierbaren Zeit, die vor dem Laden der Autostart-Applikation vergeht, auch wirklich den Bildschirm verändern, wie Sie es angekündigt haben.

Wir nutzen die Zeit, um die Resource-Datei nachzuladen und den benötigten Speicher zu reservieren. Nach den notwendigen Initialisierungen geben wir dem Desktop die Kontrolle über die virtuelle Workstation zurück und haben unsere Schäfchen im trockenen, respektive die Speicherblöcke sicher verwahrt.

(uw)

Quelleverweise:

[1] H.-D. Jankowski, J. E. Reschke, D. Rabich, »Atari ST Profibuch«, Sybex Verlag, ISBN 388745-563-0.
[2] J. Geiß, D. Geiß, »Softwareentwicklung auf dem Atari ST«, Hüthig Verlag, ISBN 3-77851533-0

Hier einmal schematisch der Ablauf der ersten Aufrufe:

Jetzt lädt der Desktop unter Umständen die Autostart-Applikation.

Ansonsten kann ganz normal verfahren werden:
- auf irgendeinen Event warten: evnt_multi()
- Reaktion auf das Ereignis
- Rücksprung in die Warteschleife


Laurenz Prüßner
Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]