AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Intelligente Objekte - automatische Freigabe von Referenzen
Thema durchsuchen
Ansicht
Themen-Optionen

Intelligente Objekte - automatische Freigabe von Referenzen

Ein Thema von Thom · begonnen am 5. Mär 2012 · letzter Beitrag vom 7. Mär 2012
Antwort Antwort
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

AW: Intelligente Objekte - automatische Freigabe von Referenzen

  Alt 5. Mär 2012, 07:47
In Delphi haben wir ja auch sowas wie einen GC und das nennt sich Interface (String und dyn. Array gehört auch mit dazu).
Interfaces und andere managed data types sind referenzgezählt. Da ist noch ein himmelweiter Unterschied zu einem GC.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#2

AW: Intelligente Objekte - automatische Freigabe von Referenzen

  Alt 6. Mär 2012, 10:49
Vielen Dank für alle Beiträge! Ich muß zugeben: Jeder hat in etwa das geschrieben, was ich von ihm erwartet habe.

Zuerst muß ich Stevie Recht geben: Diese Probleme entstehen, wenn man eine untypisierte GC Sprache nach Delphi umsetzen möchte... Aber bei diesem Ansatz will ich bleiben und deshalb soll und muß aller Verwaltungsaufwand für den Anwender (des Frameworks) hinter den Kulissen bleiben. Der Programmierer soll sich voll und ganz auf die Umsetzung seiner Ideen konzentrieren können. Deshalb sollen auch keine zusätzlichen Aufrufe notwendig sein.


@Furtbichler:

Vielen Dank für Deine Antwort!
Deine Sorge besteht darin, daß irgendwelche fremden Programmteile Deinem eigenen Code "dazwischen pfuschen". Dieses Gefühl ist bei Multithreadanwendungen vollkommen berechtigt. Leider zeugt das aber auch davon, daß Du Dich - höchstwahrscheinlich - kein einziges mal mit dem von mir angesprochenen Framework beschäftigt hat. Das soll kein Vorwurf sein - schließlich ist das auch keine Pflicht. Hättest Du das aber gemacht, wüßtest Du, das es gar nicht threadsave sein muß, da die JScript-Engine von Microsoft nicht multithreadsicher ist.
Spontan auftretende nil-Zeiger der Art
Delphi-Quellcode:
if assigned(FMyMarker) then
begin
  //<- ist hier plötzlich weg
  FMyMarker. ...;
end;
können also gar nicht auftreten. Auch alle asynchronen JScript-Callbacks laufen im Context des Hauptthreads.

Wie threadsicher ein Interface ist, hängt von seiner Implementation ab, nicht von seiner Definition. Wie das INotify.Free umgesetzt wird - ob als direkte, unmittelbare Freigabe in Singlethread-Anwendungen oder "angemeldet" und zeitlich verzögert-, hängt ganz von den Erfordernissen ab.
Ich gebe Dir aber vollkommen Recht: In Multithreadanwendungen muß ein höherer Verwaltungsaufwand betrieben werden, als in einem Programm, in dem nur ein Thread (in der Regel der Hauptthread) auf den Datenbestand zugreift. Das vorgestelle Interface wurde von mir primär für das Framework entworfen, um die automatisch Speicherverwaltung von Delphi über Referenzzähler nutzen zu können ohne die Nachteile eines TInterfacedObject's. Für eine darüber hinausgehende Anwendung sind ganz bestimmt noch weitere Aspekte zu berücksichtigen.


@himitsu:

Das vorgestellte Interface ist von IInterface abgeleitet. Deshalb beinhaltet das implementierende Objekt INotifyObjekt auch eine Referenzzählung mit _AddRef und _Release. Mir geht es aber darum, ein referenzgezähltes Objekt explizit freigeben zu können, ohne daß es zu Zugriffsverletzungen über andere, parallel existierende Referenzen kommt.
Die Registrierung/Deregistrierung lokaler (Interface-)Variablen auf dem Stack erfolgt automatisch. Das bedeutet, daß nach Verlassen der Methode die Referenz wieder entfernt wird. Es kann also nicht vorkommen,
Delphi-Quellcode:
type
  TForm1 = class([...])
    [...]
  private
    FMyNotify: INotify;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  o: INotify;
begin
  o:=TNotifyObject.Create;
  FMyNotify:=o;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FMyNotify:=nil;
end;
daß jetzt, bei Freigabe des Objektes in Button2Click, die (Stack-)Variable "o" auf nil gesetzt wird. "o" wird bei der Zuweisung in Button1Click registriert und nach Beendigung der Methode vom Compiler auf nil gesetzt sowie über INotify.RemoveRef(o) abgemeldet. Alles ganz einfach und vollautomatisch. Ich will das mal "managed Reference" nennen.
Anders sieht es natürlich bei einer expliziten Registrierung einer Variablen über AddRef() aus - also einer "unmanaged Reference". Hier muß natürlich dafür gesorgt werden, daß es nicht zu Zugriffsverletzungen kommt. Ich würde es einmal vergleichen mit dem Aufruf eines xxx.Lock: Wird anschließend das xxx.Unlock vergessen, gibt es logischerweise Probleme. Das hat aber nichts mit Fehlern im Konzept, sondern mit der Vergeßlichkeit des Programmieres zu tun. Das von mir vorgestelle Interface kann die Arbeit wesentlich erleichtern - ist aber keine Lizenz zum Abschalten des eigenen Gehirns.

Meine Umsetztung funktioniert in den bisherigen Tests sehr zuverlässig.


@Patito:

Hast Du auch irgend etwas Sachliches zu dem Thema beitragen oder beschränkst Du Dich immer auf platte Statements?
Thomas Nitzschke
Google Maps mit Delphi
  Mit Zitat antworten Zitat
Patito

Registriert seit: 8. Sep 2006
108 Beiträge
 
#3

AW: Intelligente Objekte - automatische Freigabe von Referenzen

  Alt 7. Mär 2012, 12:32

Meine Umsetztung funktioniert in den bisherigen Tests sehr zuverlässig.

@Patito:

Hast Du auch irgend etwas Sachliches zu dem Thema beitragen oder beschränkst Du Dich immer auf platte Statements?
Meine Aussagen sind folgende:
1. Dass es zumindest fragwürdig ist Dinge auf Design-Fehlern aufzubauen.
2. Dass Interfaces nicht für das Ref-Counting da sind. (Interfaces sind Schnittstellen)

Mag sein, dass Dir das nicht gefällt. Insgesamt hat es mit Deiner Situation aber nur insofern zu
tun, dass ich Deinen Tricks erst mal wenig vertraue.

Ich glaube nicht, dass Du das ganze richtig anpackst. Per Observer ein paar Referenzen zu eleminieren ist zwar
gute Technik, aber in einer Anwendung verteilte Referenzen im User-Code lassen sich nicht so einfach alle auf nil setzen.
Ich vermute mal, dass Du da in Deinen Tests einem Trick des Optimizers aufgesessen bist...

Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var
  o1, o2: INotifyObject;
begin
  o1:=TNotifyObject.Create;
  o2:=o1;
  o1.Free;
  //sowohl o1 als auch o2 sind jetzt nil!!!
end;
Wäre interessant wenn Du die Referenzen etwas weiter weg verteilst.
(Feld in irgendeiner Klasse, auf dem Stack als Rückgabewert einer Funktion, ...).
Ich glaube, dass Du niemals alle auf nil gesetzt bekommen wirst.

So ein zwischen-Interface bringt reichlich wenig. Anstatt auf Interface-Referenzen aufpassen zu müssen
muss man jetzt eben genauso auf die Referenzen auf die INotifyObject-Interfaces aufpassen - damit hat man
praktisch nichts gewonnen.

Das ganze geht mit Objekt-Handles wesentlich einfacher und ohne 360-Grad Pirouette.

Geändert von Patito ( 7. Mär 2012 um 12:44 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz