![]() |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
Ein Interface entspräche in etwa nur dem, was man in C++ darunter versteht. Da ist ein Interface nur eine Basisklasse, die nur abstrakte Funktionen enthält. Da es in C++ Mehrfachvererbung gibt, kann eine Klasse so auch beliebig viele Interfaces implementieren. Technisch ist so ein Interface nur eine Tabelle von Funktionszeigern. |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Ich frage hier nochmals nach:
Wenn man also Objektreferenzen verwendet, die automatisch genullt werden, wenn das referenzierte Objekt freigegeben wird, wie sieht dann so ein Programm aus? Wie sichert man sich gegen spontan auftretende Nil-Referenzen ab? Kann jemand hier mal ein Beispiel nennen? |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
@Furtbichler:
Ich habe doch oben ein Besipiel beschrieben (wenngleich ich inzwischen ja auch einen anderen Ansatz wählen würde): Eine Person wird von mehreren Spielerobjekten referenziert (damit alle die selben Daten verwenden bzw. anzeigen). Wird die Person freigegeben, sollen alle Spielerobjekte erkennen, dass das Personenobjekt nicht mehr existiert (indem sie das Feld auf nil prüfen). Natürlich sollte vermieden werden, dass das referenzierte Objekt nach dem Prüfen auf nil aufgelöst wird. Aber das ist ja sowiso klar. Natürlich kann man das anders (besser) regeln, aber WENN man rein mit direkt referenzierten Objekten arbeitet, sollte der Wunsch doch nachvollziehbar sein. DataSource informiert ja auch DBGrids, über seine Auflösung (über Observer-Pattern). Im Sinne einer einfachen Programmierung und aus Rücksicht auf OOP-Anfänger wäre es nur ganz schön, wenn es dafür einen Automatismus gäbe. Ich sehe ein, dass das vielleicht nicht ganz einfach zu realisieren ist, aber Deine Nachfrage verstehe ich nicht. MyDBGrid.DataSource wird ja auch nicht spontan auf nil gesetzt, sondern nur wenn die gebundene DataSource aufgelöst wird. @Robotiker: Corba sieht wirklich interessant aus. ![]() ![]() Aber es ist halt wie immer. Ich verstehe das nur zum (Bruch-)Teil. :-( |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
Aber Absichern vor spontanen Verschwinden bei Zugriff durch mehrere Threads schreit nach Synchronisation, sollte eigentlich mit einer beliebigen Lösung des Reader-Writer-Problems behandelt werden können. |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
Zitat:
Zitat:
Ich kann die Motivation von Stahli verstehen, auch der Lösungsansatz bzw. die Idee dahinter von Thom verstehe ich.. Aber notwendig und dann wirklich sauber ist das eben nicht. Ich würde nie im Leben mit einem System arbeiten, das mir die Immanzenz meiner Objekte nicht sicherstellt. Und genau das wird hier gemacht. Ich muss immer und jederzeit damit rechnen, das mir eine Objektreferenz geklaut wird. Grauselig. Aber ich schreibe auch keine heterarchischen Systeme wie Stahli. Vermutlich werde ich ähnliche Gehirnakrobatiken anstellen müssen und dann dankbar diesen Thread lesen, wenn ich das mal mache. Oder ich schreibe keine Heterarchien, stattdessen aber ein Spielermanagement, das mir meine Spieler verwaltet. |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
Da ich nicht mit Threads gearbeitet habe und alle Datenobjekte im Speicher verwaltet werden können, funktioniert das letztlich doch zuverlässig. Inzwischen erkenne ich auch, dass es bessere und vor allem flexiblere Verfahrensweisen gibt. Allerdings bringen die natürlich auch einigen Aufwand und Abstraktion mit sich, so dass man sich "im ersten Moment" eher für einen naheliegenderen Ansatz entscheiden wird. Jedenfalls, wenn man mit diesem noch nicht an bestimmte Grenzen gekommen ist und keine Ausbildung als Programmierer genossen hat. Zitat:
Es wäre wohl gut, wenn sich endlich mal ein entsprechendes Konzept durchsetzen würde, mit dem auch Nicht-Profis mit Delphi arbeiten können. Was soll denn jetzt "in" sein? DataSnap? Zitat:
Wie gesagt, ich habe mit meinen Fähigkeiten (ohne Threads) mein Projekt immer weiter ausgebaut und diverse Wege bestritten. Mit den Objekten konnte ich am flexibelsten arbeiten. Die Klassen habe ich mir teilweise durch einen Experten automatisch erzeugen lassen. In einem Framework binde ich die Objekte automatisiert an die GUI. Dabei ist es hilfreich, wenn die Objekte dauerhaft im Speicher vorliegen. Das funktioniert eigentlich wunderbar und mit rel. geringem Aufwand (als das Framework funktionierte). Da ich verschiedene Turniersysteme parallel verwalte und die Spieler/Personen in allen Turniersystemen eingesetzt werden können, wird es inzwischen aber dennoch sehr unübersichtlich. Außerdem möchte ich künftig eine Datenbank oder sogar Client/Server einsetzen. Dann funktioniert es natürlich nicht mehr auf dem bisherigen Weg. Deshalb plane ich eine Änderung des gesamten Konzeptes, muss damit aber natürlich auch erst meine Erfahrungen machen. Man geht halt erst einmal den einfachen Weg, bis man erkennt, dass es so nicht weiter geht... |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
![]() Ein weak_ptr hat z.B. eine Memberfunktion expired() mit der man prüfen kann, ob er noch gültig ist. Greift man auf einen ungültigen Pointer zu gilt Zitat:
Zitat:
Zitat:
![]() Zitat:
Corba ist in der Versenkung verschwunden, die Smartpointer sind heute ISO-Standard. |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Vielen Dank für alle Beiträge! Ich muß zugeben: Jeder hat in etwa das geschrieben, was ich von ihm erwartet habe. :-D
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:
können also gar nicht auftreten. Auch alle asynchronen JScript-Callbacks laufen im Context des Hauptthreads.
if assigned(FMyMarker) then
begin //<- ist hier plötzlich weg FMyMarker. ...; end; 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:
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.
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; 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? |
AW: Intelligente Objekte - automatische Freigabe von Referenzen
Zitat:
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:
Wäre interessant wenn Du die Referenzen etwas weiter weg verteilst.
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; (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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:41 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