XShutdown hat mich viele Stunden angestrengten Denkens gekostet, weil es wirklich nirgendwo dokumentiert ist, was während des normalen Systemabschlusses geschieht.

Normalerweise kennt OS/2 zwei verschieden Systemabschluß-APIs:

Das Problem ist, daß es keine Funktion "zwischen" diesen beiden gibt. Wenn Sie DosShutdown aufrufen, wird die WPS nicht gesichert, und bei WinShutdownSystem legt der normale Systemabschluß los, ohne daß man irgendeine Möglichkeit hätte, noch einzugreifen. Das bedeutete, daß ich quasi ein komplett neues WinShutdownSystem programmieren mußte, das hier jetzt erklärt wird. Dies war ziemlich schwierig, da IBM kaum irgendetwas darüber erklärt, was wirklich während WinShutdownSystem passiert.

Hinweis: In XFolder benutzen der "Erweiterte Systemabschluß" und "WPS neustarten" denselben Code; der einzige Unterschied sind die Aktionen, die nach dem Schließen aller Fenster ausgeführt werden. Deshalb werde ich den Begriff "XShutdown" in den folgenden Erklärungen für beide benutzen, wenn nicht anders angegeben.

XShutdown ist in die WPS integriert und ist sehr stark von den XFolder-Ersatzklassen abhängig. Bewußt habe ich den XShutdown-Code nicht einer separaten .EXE-Datei mitgeliefert: zum einen braucht XShutdown Zugriff auf WPS-interne Daten, die nur durch SOM erreichbar sind; zum zweiten will ich die Leute davor bewahren, XShutdown ohne installierte XFolder-Klassen zu starten, da dies die WPS beschädigen könnte. Genauer gesagt benötigt XShutdown die Klasse XFldObject und den XFolder-Worker-Thread, die die WPS-internen Daten zugänglich machen.

Um zu verstehen, was XShutdown tut, muß man wissen, wie die WPS ihre Objekte intern verwaltet. Jedes einzelne Objekt, das zu einem Zeitpunkt für die WPS relevant wird, sei es durch Bevölkern eines Ordners, durch Abfragen der Einstellungen oder durch Starten eines Programmes oder durch was auch immer, wird -- in WPS Terminologie -- vom System "aufgeweckt" ("awakened"); das bedeutet, daß es als SOM-Objekt im Speicher existiert.

Die WPS schläfert nur selten wache Objekte wieder ein, was die Freigabe des damit verbundenen Speichers und einer Sicherung der Daten des Objekts auf Festplatte zur Folge hätte. Das hat zwei Konsequenzen:

  1. Es gibt immer mehr "wache" Objekte auf Ihren System, als Sie in diesem Moment annehmen würden, da die meisten von ihnen gerade nicht sichtbar sind. Sogar wenn Sie einen Ordner geschlossen haben, bleiben die Objekte darin wach; das beschleunigt das Bevölkern des Ordners, wenn er zum zweiten Mal geöffnet wird. Das führt dazu, daß die WPS mit jedem Ordner, der geöffnet wird, immer mehr und mehr Speicher belegt. (Wenn Sie von XShutdown eine Logdatei erstellen lassen, können Sie sehen, wie viele wache Objekte von XShutdown gesichert werden; normalerweise sind das einige hundert Objekte, auch wenn XShutdown nicht alle Objekte sichert, sondern nur die Ableitungen von WPFolder und WPAbstract. Unter dem Reiter "Interna" im Einstellungsnotizbuch des Arbeitsoberfläche können Sie sehen, wie viele Objekte derzeit wach sind.)
  2. Eine Änderung der Objekt-Daten aktualisiert manchmal nur das SOM-Objekt im Speicher, wird aber nicht auf Festplatte oder in OS2.INI / OS2SYS.INI gespeichert. Darum gerät die WPS manchmal ins Schleudern, wenn Sie größere Änderungen durchgeführt haben, wie das Bewegen eines Ordners, der viele abstrakte Objekte enthält, und danach nicht richtig herunterfahren: die physikalischen Daten auf der Festplatte und die WPS-Einträge unterscheiden sich dann.
Dafür braucht XShutdown die Klasse XFldObject, die WPObject ersetzt. Jedes mal, wenn ein Objekt aufgeweckt wird, ruft die WPS diverse Methoden auf (darunter wpInitData und wpObjectReady). XFldObject ersetzt diese und übergibt die Speicheradresse des Objekts an den Worker-Thread, der dann die XFolder-interne Liste aller momentan wachen Objekte aktualisiert. Soweit ich weiß, gibt es keinen anderen Weg herauszufinden, welche Objekte gerade wach sind; auf jeden Fall gibt es auch keine dokumentierte API, die diese Objekte auflisten könnte.

Wenn XShutdown nun aufgerufen und bestätigt wird, startet es als erstes für die folgende Systemabschluß-Prozedur zwei neue Threads, die parallel zu den regulären WPS-Threads laufen; der Haupt-"Systemabschluß-Thread" mit der Nachrichtenschlange für das Status-Fenster, und der "Update-Thread", der die OS/2-Fensterliste überwacht und Nachrichten an den Hauptthread absetzt, wenn das Status-Fenster aktualisiert werden muß. Daher ist das Schließen aller momentan geöffneten Fenster ein kompliziertes Zusammenspiel dieser beiden Threads: Der Systemabschluß-Thread schließt ein Fenster und geht dann so lange in den Leerlauf, bis der Update-Thread eine Änderung in der Fensterliste meldet (was bedeutet, daß erfolgreich geschlossen wurde) und den Systemabschluß-Thread benachrichtigt, der dann wiederum das nächste Fenster schließt, bis kein Fenster mehr übrig ist.

Nachdem alle Fenster geschlossen worden sind, beendet sich der Update-Thread. Jetzt geht der Systemabschluß-Thread die Liste aller momentan wachen Objekt durch (s.o.) und zwingt sie durch den Aufruf der wpSaveImmediate-Methode, ihre Daten in die INI-Dateien oder auf Festplatte zu schreiben. Dies geschieht nur für die Ableitungen von WPAbstract und WPFolder, weil nach meiner Erfahrung alle anderen Klassen ihre Daten direkt speichern. (Ich habe einmal versucht, alle Ableitungen von WPFileSystem zu sichern, und dies verursachte jede Menge Erweiterter Attribute für jede einzelne Datei, die jemals von der WPS geweckt wurde. Abgesehen davon dauert der Systemabschluß dann ewig lange.)

Zuletzt, je nach dem welche Aktion gewünscht wird, führt der Systemabschluß-Thread folgendes aus: