4.10 Die Speicherverwaltung in Lingo

Wer Director als reines Animationswerkzeug benutzt, muss sich selten um die Verwaltung von Speicherressourcen kümmern; die Laufzeitumgebung nimmt dem Autor die meiste Arbeit ab. Ähnlich verhält es sich bei der Speicherverwaltung innerhalb Lingos. Wie Java setzt Director dabei auf eine automatische Garbage Collection, allerdings kommt dabei ein einfacher Referenzzähler-Algorithmus zum Einsatz.

Jedesmal, wenn eine neue Referenz auf ein Objekt erzeugt wird, setzt Lingo den Referenzzähler des Objektes um 1 herauf. Bei einem neuen Objekt ist dieser Referenzzähler auf 2 gesetzt, da Lingo intern eine weitere Referenz auf ein Objekt behält:

objekt1 = script("TestObjekt").new()
put objekt1
-- <offspring "TestObjekt" 2 1120e34>

Wird diese Referenz in einer weiteren Variablen gespeichert, erhöht sich der Referenzzähler:

objekt2 = objekt1
put objekt1
-- <offspring "TestObjekt" 3 1120e34>

Wird eine Referenz aufgelöst, zum Beispiel durch das Setzen der Referenzvariablen auf 0, verringert sich der Wert des Zählers wieder:

objekt1 = 0
put objekt2
-- <offspring "TestObjekt" 2 1120e34>

Lingo behält die Instanz so lange im Speicher, bis keine Variable mehr auf sie verweist. Die Instanz kann nicht mehr angesprochen werden und der Garbage Collector gibt den belegten Speicher wieder automatisch frei:

objekt2 = 0

Der Speicherplatz ist nun wieder freigegeben.


Achtung
Wenn Objekte sich gegenseitig referenzieren, kann Lingo den Speicher unter Umständen nicht mehr freigeben.


objekt1 = script("TestObjekt").new()
objekt2 = script("TestObjekt").new()
objekt1.mReferenz = objekt2
objekt2.mReferenz = objekt1

Auf jedes der beiden Objektinstanzen objekt1 und objekt2 bestehen jetzt zwei Referenzen (die Lingo-interne nicht mitgezählt). Werden die Referenzen in den Variablen auf 0 gesetzt:

objekt1 = 0
objekt2 = 0

wird der Garbage Collector den Speicher nicht freigeben, da jeweils noch eine Referenz auf die Instanzen gezählt wird. Andererseits hat der Programmierer keinen Zugriff mehr auf die Referenzen, so dass der Speicher für diesen Programmdurchlauf unwiederbringlich verloren ist. Kommt dies öfter vor, kann das dazu führen, dass der Speicher langsam vollläuft und das Programm mit einer Fehlermeldung abbricht. Aus diesem Grund sind solche zirkulären Verweise zu vermeiden oder explizit aufzulösen:

objekt1.mReferenz = 0 -- Kreisreferenz aufgebrochen
objekt1 = 0
objekt2 = 0


Übrigens benötigt eine neue Objektinstanz nur den Speicherplatz, den seine Eigenschaften belegen. Die Skripte werden nur einmal im Speicher gehalten und von allen Objekten genutzt. Redundanzen und verschwendeter Speicherplatz werden dadurch vermieden. Es ist also nicht uneffizient, ein umfangreiches Skriptobjekt mehrmals zu instantiieren, sofern dessen Eigenschaften nicht viel Platz belegen.

4.9 Beispiel 3: Der Objekt-Browser 4.11 Vererbung mit the ancestor