Objekt C Programmierung (3)

Mit Erscheinen dieses Heftes ist die neue Version 2.5 von Object C ebenfalls kostenlos erhältlich. Die neue Version erlaubt jetzt noch weit schnellere Programme, was vor allem Besitzer von älteren ATARIs freuen dürfte. Zu den bisher unterstützten 11 Plattformen wie LINUX, MacOS, OS/2 und Windows 3.x/95/NT ist im letzten Monat noch FreeBSD hinzugekommen. Der vorliegende Artikel beschreibt unter anderem Objektlisten und den Object C Garbage Collector.

Object C 2.5

Object C 2.5 weist nur wenige Unterschiede zum Object C 2.1.8 B/2.3.3C auf. Der Compiler selbst erlaubt es jetzt, 100% generische Methoden (ohne $call(obj) Aufruf des klassenspezifischen Codes) in verkürzter Schreibweise darzustellen:

$meth PrintAlt(0bj obj)   
$support(Text, Picture, Circle);   
Obj o_device;   
OpenStdDevice(&o_device);   
PrintDevice(o_device,obj);   
CloseDevice(o_device);   
$class Text   
$class Picture   
$class Circle  
$  
$meth PrintNeu(Obj obj)   
$support(Text, Picture, Circle);   
Obj o_device;   
OpenStdDevice(&o_device);   
 DMPrintDevice(o_device,obj);  
CloseDevice(o_device);  
$

Die Laufzeitbibliothek bietet jetzt eine weitere Konfigurationskonstante OBJ_CONFIG_FASTMEM. Durch 'obj_config(OBJ_CONFIG_FASTMEM, 1L);' lässt sich nun vor dem 'obj_initall_();' auf den schnellen Zugriffsmode umschalten. Hierdurch werden alle Objekthandles gegen echte Zeiger ersetzt, womit sich Beschleunigungen bis zu Faktor 10 ergeben können. Weil der normale Modus hingegen ein paar weitere Laufzeitfehlererkennungen bietet, sollte man erst vor der Softwarefreigabe auf Fastmem umschalten. Objektlisten werden jetzt nach Object C Modulen getrennt verwaltet, was einerseits die Zahl gleichzeitig verwaltbarer Objektlisten von 16000 auf maximal 4 Millionen Listen erhöht, vor allem aber auch die Geschwindigkeit des Garbage Collectors stark erhöht.

Voraussichtlich wird in etwa einem Monat auch ein neuer GCC Compiler (v. 2.7) für Object C vorliegen, dem dann kurze Zeit später eine hiermit übersetzte 0bject C Laufzeitbibliothek folgt Über einen CompuServe-Zugang können Sie jetzt schon die Datei "oc250st.zip" (2,7 M BI) aus dem Forum CPROBJC (bzw. GERSOFT) laden. Hier ist nicht nur der 0bject C Compiler, sondern auch der GCC 1.5.4 (in Original-Version und angepaßter Version) und die komplette HTML- Dokumentation des kommerziellen 0bject C Multiplattform Entwicklungspaketes "OC2" enthalten. Das bedeutet, Sie erhalten nicht nur die allerneuste Object C Dokumentation, sondern ebenfalls die Dokumentation des Mangrove Managers ('ATARI-Inside' wird später darüber berichten) und der demnächst auf ATARI portierten Object C GUI Bibliothek 'OCC'. Das ist vor allem für Entwickler mit Zugang zu Macintosh- oder Windows-Rechnern interessant, denn OCC 1.5.1 und die Object C 2.3.3 Shareware für Windows und MacOS können nach wie vor von der CPR Homepage "http://ourworld.compuserve.com/Homepages/CPR-ObjectC" sowie dem Forum CPRO BJC geladen werden.

Sprachelemente: $classes,$dat,$new-clone-free

Objektorientierte Programmierung ist schon etwas Besonderes. Neben den neuen Vorteilen ergeben sich aber ebenso viele Gefahren. Nur wenn man weiß, welche Gefahren eine OOP Sprache mit sich bringt, wird man wirklich effizienter arbeiten und stabilere Programme erzeugen können. Besonders unangenehm wird es, wenn Fehler sich verstecken und ihre Folgen erst viel später a n anderen Programmstellen auftreten. Programme wie Lint, Bounds Checker und Debugger helfen zwar etwas, können aber nicht wissen, was der Entwickler mit dem Quellkode beabsichtigt.

Folglich muss eine gute Programmiersprache den Quellkode so übersichtlich wie irgendwie möglich präsentieren. Je einfacher die Struktur und Semantik der Sprache ist, desto eher ist der Entwickler dazu in der Lage, die oft sehr komplexen Abläufe des Programm es zu verstehen. Das Programm wird dadurch fehlerfreier (denn versteckt schlummernde Fehlerquellen werden oft schon beim normalen Entwicklungsablauf ohne Debugging entdeckt), das Programm kann besser von anderen Entwicklern verstanden werden, die Gefahr des Projektscheiterns ist verringert und die Produktivität steigt.

Bei der Entwicklung von Object C wurden diese Aspekte im Gegensatz zu C++ berücksichtigt (beim C++ Design standen hauptsächlich Ablaufgeschwindigkeit und Typsicherheit im Vordergrund), weshalb größere Projekte sich in 0bject C problemloser realisieren lassen als in C++. Betrachten wir nun zur Vertiefung an anderen Beispielen noch einmal einige der bereits vorgestellten Sprachelemente. In der nächsten Ausgabe werden wir dann noch einmal auf den Objektdatenzugriff und auf Methoden eingehen.

a) '$classes...$' dient zur Aufzählung aller Klassen eines Object C Modules und wird in der Regel a m Anfang einer '.i'-Datei (üblicherweise der Haupt-Includedatei des Modules) aufgeführt. Welche Separatoren zwischen den einzelnen Klassennamen verwendet werden (Komma, Semikolon, Zeilenwechsel) ist egal. Hinter jedem Klassennamen sollte ein erläuternder Kommentar stehen.

$classes  
MyClass1 /* Kommentar  */  
MyClass2  
...  
$

b) '$dat...$' beschreibt die Attribute einer Klasse und gibt an, welche Klassen geerbt werden. Beispiele:

/ * ein Attribut '..text' und '..value'  */   
$dat MyClass1  
char text[32];  
int value;  
$  
/* ein universeller Objekthandle und eine Objektliste */   
$dat MyClass2  
Obj o_myobj;  
List list;  
/* MyClass3 erbt MyClass2 */   
$dat MyClass3 : MyClass2;  
$  
/* MyClass4 erbt MyClass3 und MyClassl */   
$dat MyClass4: MyClass3, MyClass1;  
$

c) '$new Classname (...)...$clone...$free...$' bildet den Konstruktor, Cloning-Block und Destruktor einer Klasse. Als verstecktes Parameter wird jeweils der Objekthandle 'obj' und der Objektdatenzeiger 'objp' übergeben. Wie die meisten Object C Sprachkonstrukte wird auch dieses in einer Methodendatei '.m' abgelegt. Solange nur normal kopierbare Werte als Attribute verwendet werden, können die $clone und $free-Blöcke leer bleiben. Beispiel:

$new MyClassl (char* text,int value)  
strcpy(..text,text);  
...value = value;   
$clone   
$free  
$

Werden hingegen lokale Kopien von 0bjekten, 0bjektlisten oder geerbten Objekten (in Object C werden konkrete Objekte geerbt) benötigt, dann müssen diese Werte extra erzeugt bzw. zerstört werden. Dabei hängt es von den Programmanforderungen ab, ob dem Konstruktor einzelne Attribute zur Speicherung oder zum Kopieren zu übergeben sind oder ob Attribute im Konstruktor auf Standardwerte initialisiert werden (Beispiel MyClass2) und im Laufe des Programmes durch entsprechende Methoden verändert werden. In jedem Fall ergibt ein 'Obj o_new = $clone(o_old);' für 'o_old = noobj;' wieder ein 'o_new = noobj;'. Abfragen der Art 'if (o_old != noobj) o_new = $clone(o_old);' sind also unnötig.

$new MyClass2()  
..o_myobj=noobj;  
$newlist(&..list);   
$clone   
..o_myobj= $clone(..o_myobj);   
$clonelist(&..list);   
$free   
$free(..o_myobj);   
$freelist(..list);  
$

Der Zugriff auf Objekthandles geerbter Objekte (Parent-Objekte) erfolgt relativ zum aktuellen 'objp' durch @ParentClass.

$new MyClass3()  
@MyClass2 = $new(MyClass2);   
$clone    
@MyClass2 = $clone(@MyClass2);   
$free  
$free(@MyClass2);  
$

Als Faustregel kann gelten: Was im $clone-Block erzeugt wird, muss im $free-Block auch freigegeben werden.

Garbage Collection

Aufgrund seiner Sprachstruktur (Zeiger, Funktionsparameter, linkbare Bibliotheken etc.) ist C bzw. C++ nicht besonders gut zur Implementierung einer Garbage Collection geeignet. Zur Zeit ist sich die Informatik relativ einig, dass eine vollständige GC nicht ohne Änderung des C-Sprachsyntax möglich ist. Eine derart komplexe GC wäre auch sehr zeitaufwendig zu Parsen und würde aller Wahrscheinlichkeit nach recht langsame Programme hervorrufen, wie an Smalltalk oder Java zu sehen ist.

Object C verwendet deshalb keine vollständige Garbage Collection, sondern beschränkt sich darauf, Objektverweise auf zerstörte Objekte zu entfernen. Object C Programme sind jedoch trotz GC sehr kompakt (ohne OCC etwa 90 KB) und bei Beachtung einiger Richtlinien trotz GC recht schnell. Wegen der für GC Verhältnisse niedrigen Programmgrößen eignen sich Object C Programme durch minimale Ladezeiten u.a. für Netzwerkanwendungen. Der GC-Mechanismus wird durch OCC noch erweitert, doch zunächst zur normalen Object C GC.

Wird in einem Programm ein Objekt freigegeben, so dürfen nach der Zerstörung des Objektes keine weiteren Zugriffe auf den alten Speicherbereich erfolgen. Was zunächst so trivial klingt, wird jedoch zum Problem, sobald Objektverweise in anderen Objekten oder lokalen bzw. globalen Variablen gespeichert wurden. Object C bietet daher den Typ "List" zur Speicherung von Objekthandles an.

Alle verwendeten Listen werden bei der Freigabe eines Objektes überprüft. Das wäre sehr langsam, wenn man bei der Entwicklung von Object C nicht ein paar Tricks angewandt hätte. Legt der Programmierer nämlich nur Objekte einer Klasse in einer Liste ab, so wird diese Liste von der GC ignoriert, falls das freizugebende Objekt nicht dieser Klasse angehört. Ebenso führt die Freigabe nicht in Listen gepeicherter Objekte ebenfalls zu keiner Listenprüfung. Modellieren wir einen Betrieb mit Anestellten:

$dat Person   
char nachname[32];   
char vorname[32];  
$  
$dat Angestellter: Person   
int gehalt;  
$dat Betrieb   
List angestellte;  
$

Wir können nun durch Konstruktoren und geeignete Methoden Arbeiter einstellen oder entlassen. Bei der Entlassung müssen Angestellte aus der Liste "Betrieb.angestellte" entfernt werden - und eben das nimmt uns die GC ab. Der folgende Abschnitt betrachtet die Objektlisten näher.

Objektlisten

Für Objektlisten stehen uns u.a. folgende Befehle zur Verfügung:

List list; $newlist(&list); / * neue Liste erzeugen */ $clonelist(&list); / * $newlist + ObjHdl kopieren */ $freelist(list); / * Liste entfernen */ $clrlist(list); / * Liste entleeren */ $catlist(dlist, slist); / * Handles anfügen */ $app(list, obj); / * obj an Liste anfügen */ $del(list, obj); / * obj aus Liste entfernen */

Im Konstruktor für "Betrieb" würden wir also die Liste der Angestellten erzeugen:

$new Betrieb() $newlist(&..angestelite); $clone $clonelist(&..angestellte); $free $freelist(..angestellte); $

Weil die Befehle $clonelist bzw. $freelist nur Handles kopieren bzw. die Liste entfernen, benötigen wir oft auch die Befehle:

$cloneobjs(list, &clonelst); / * Objekte klonen */  
$freeobjs(list); /* alle Objekte freigeben */

Einen Arbeiter könnten wir also wie folgt erzeugen und an die Liste der Angestellten anfügen:

Obj person = $new(Person,"Twain", "Mark");  
Obj arbeiter = $new(Arbeiter, person, 2470);  
$app(..angestellte, arbeiter);

Würde der Angestellte später entlassen, d.h. das Objekt freigegeben, so "verschwindet" er automatisch aus allen Listen:

$free(arbeiter);

Dieses listenbasierte GC-Verfahren stellt zwar nur eine sehr eingeschränkte Form einer GC zur Verfügung, jedoch "verschwinden" ObjektHandles nicht irgendwo, sondern nur an definierten Orten, nämlich den Listen. Der GC bietet uns zusätzlich eine an tomatische Korrektur von Listen-Zugriffspositionen. Man stelle sich vor, während der Abarbeitung einer Liste werden durch den Aufruf einer Methode Objekte zerstört, die in eben dieser Liste enthalten sind. Würden Objekte, die vor oder auf der aktuellen Leseposition liegen, gelöscht werden, so wäre ohne diesen Automatismus ein Chaos vorprogrammiert. In der Tat kann eine Liste recht einfach bearbeitet werden (direkt unterhalb des $begfor können wie bei vielen Object C Konstrukten üblich wieder Variablen definiert werden ohne { verwenden zu müssen):

$begfor(mylist, o_myobj)  
draw(o_myobj,i);   
$endfor(mylist)</b></p>

Die Schleife stellt den Objekthandle "o_myobj" zur Verfügung. Selbstverständlich sind solche Schleifen schachtelbar. Der vorzeitige Schleifenabbruch muss durch "break;" erfolgen.


Andreas Guthke
Aus: ST-Computer 10 / 1997, Seite 44

Links

Copyright-Bestimmungen: siehe Über diese Seite