Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#79

Re: Unbegrenzt viele Nachkommastellen

  Alt 21. Okt 2004, 11:36
Hi Dano,

das war im Grunde alles korrekt, und ein Kompliment von mir weil dues ziemlich schnell erfasst hast.
Es gibt aber vielleicht noch einige kleinere Richtigstellungen:

1.) Delphi implementiert bei Interface Variablen ausschließlich das korrekte Initialisieren mit NIL und das korrekte Finalisieren mit NIL, mehr nicht. Diese beiden Aufgaben macht Delphi in geschützten Codeblöcken, also unsichtbaren try finally end; Blöcken.
Werden mehrere Interface-Variablen in einer Procedure benutzt so gruppiert der Compiler diese Variablen im Stack immer als Array[] of IInterface. Deren Initialisierung und Finalisierung mit NIL wird dann durch Funktionen der RTL erledigt die ganz Arrays of IInterface auf NIL setzen.
Das "auf NIL" setzen bedeutet das die RTL erstmal überprüft ob die Variable <> nil ist, wenn ja wird Valiable._Release; aufgerufen und Variable := nil; gesetzt.

2.) Interfaces können, müssen aber nicht das Reference Counting implementieren. Wenn sie es tuen dann nur aus dem Grunde um sich selber korrekt zerstören zu können. D.h. die Implementierung der Allokation + Deallokation der Interfaces wird nur durch die Interfaces erledigt.

Dies beiden Punkte stellen das "Garbarge Collection" Feature dar.

3.) Die proceduralen Schnittstellen im DECMath -> math. Funktionen, rufen intern bei nicht-readonly Variablen immer eine Funkton auf. Diese Funktion hat drei Aufgaben, a.) Überprüfung ob Variable ein nil Interface enthält und falls ja ein neues IInteger Intrface allozieren, und wenn nein b.) Variable enthält ein Interface also Überprüfung ob .RefCount > 1 ist, wenn ja neues IInteger Interface allozieren und Inhalt aus dem alten ind das neue kopieren. Der Kopierschritt wird aber durch einen Parameter gesteuert. c.) am Schluß gibt die Funktion einen Zeiger auf einen Record zurück -> sozusagen wndelt sie den Datentyp Pointer(IInteger) in PIIntegerRecord(IInteger) um.

Diese Funktion stellt also das "Copy on Write Demand" und "Autoallokation" Feature zur Verfügung.
In den meisten Fällen sieht das so aus:

Delphi-Quellcode:
procedure NInc(var A: IInteger; B: Integer);
begin
  with NAllocCopy(A)^ do
 .....
end;
NAllocCopy() ruft intern NAlloc(A, True) auf, und diese Funktion führt obigen Punkt 3. aus.
Durch die Deklaration mit "var A: IInteger" haben wir ja eine "by Reference" Aufrufkonvention, wir bekommen den Zeiger auf die Zeigervariable in der das IInteger steht, und somit können wir diesen Variablen neue IInteger Interfaces zuweisen. Es dürfte aber klar sein das solche Funktionen möglichst hochoptimiert sind. Im Falle von NAlloc() wird intern in den meisten Fällen nur 3 Assembler Instruktionen ausgeführt. Leider kennt Delphi keinen Precompiler und somit keine Makros.
Man sollte also wenn man mit Interfaces arbeitet immer die Aufrufkonventionen "var" oder "const" benutzen, dies ist wichtig.

4.) Interfaces sind keine Zeiger auf VMT's !! Sie sind Zeiger auf einen Speicherbereich in dem die ersten 4 Bytes == Pointer ein Zeiger gespeichert wurde der der Zeiger auf eine VMT ist. Nach diesem Pointer kommen noch eventuell Daten, die verschiedenen Felder/Member des allozierten Interface Objectes. Im Falle von IInteger also ein Zeiger auf ein Array[]of Cardinal, eine Count, Size Variable und Negative um das Vorzeichen zu speichern.
IInteger Interface Variablen könnte man also direkt zu einem Record casten und somit auf die internen Daten zugreifen. Man sollte das aber nicht machen

So, und alle diese Features waren noch vor dem ersten eingetippten Source ein zu erreichendes Ziel, d.h. ich habe mich nur deshalb für Interfaces und prozeduraler Schnittstelle entschieden da das die einzigste Möglichkeit im Delphi seinerzeit war.

Gruß hagen
  Mit Zitat antworten Zitat