AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

InterfacedObject freigeben

Ein Thema von tigerman33 · begonnen am 24. Nov 2005 · letzter Beitrag vom 5. Dez 2005
Antwort Antwort
tigerman33

Registriert seit: 30. Jul 2005
Ort: München
423 Beiträge
 
Delphi 2005 Professional
 
#1

InterfacedObject freigeben

  Alt 24. Nov 2005, 12:39
Hallo,

Ich habe Objekte, welche mittels eines Interfaces bestimmte Vorkomnisse an die sie beinhaltende Liste senden.

Im Konstruktor der Liste (das natürlich dieses Interface implementiert) habe ich den Referenzzähler manuell um eins erhöht (damit wenn das letzte Listenelement freigegeben wird nicht automatisch auch die Liste freigegeben wird).
Nun habe ich die Methode BeforeDestruction überschrieben und dort diese eine "zusätzliche" Referenz wieder entfernt, um die Liste ohne Exception freigeben zu können.

Beim _Releasen dieser Referenz wird aber natürlich jetzt wieder der Destruktor aufgerufen, mit allen dazugehörigen Folgen (u.a. auch Aufruf von BeforeDestruction, erneutes _Release etc). Das halte ich für ziemlich unschön. Auf Anhieb sind mir dazu zwei Lösungswege eingefallen:

1. Setzen eines zusätzlichen Boolean-Feldes auf true und dann Abfrage im BeforeDestruction ob nicht gerade schon freigegeben wird (quasi wie das csDestroying von Komponenten)
2. Re-implementieren der _Release-Methode von TInterfacedObject, um damit die "Auto-Zerstörung" bei Referenzzähler=0 zu unterbinden.

Sind aber beides nicht so richtig "schöne" Lösungen, finde ich. Hat noch jemand eine bessere Idee?

Mfg
Christian
Christian
Der Computer hilft mir, Probleme zu lösen, die ich ohne Computer nicht hätte.
  Mit Zitat antworten Zitat
BaumWollSchaf

Registriert seit: 20. Jan 2005
7 Beiträge
 
Delphi 2005 Professional
 
#2

Re: InterfacedObject freigeben

  Alt 24. Nov 2005, 13:37
Hallöle.

Ein kleines auf das Grundproblem reduziertes Codebeispiel wäre sicher hilfreich.

Grundsätzlich kann man sagen, daß eine manuelle Veränderung des RefCounts so gut wie immer vermieden werden sollte.
Bei Kreuzbezügen kannst du die Interfaceeigenschaft als Pointer definieren und bei Verwendung casten. Auch nicht ganz schön, aber später immer noch übersichtlicher, als die Suche nach dem AddRef im Code.

Böööh!
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#3

Re: InterfacedObject freigeben

  Alt 24. Nov 2005, 13:54
Hallo,

ich habe das bei meinen Objekten folgendermaßen gelöst: Ich habe eine Variable FDestroying eingeführt und setze diese im Destructor. Zusätzlich habe ich _Release wie folgt abgewandelt:
Delphi-Quellcode:
function TInterfacedObject._Release: Integer;
begin
  if FDestroying then
  begin
    Result := FRefCount;
    Exit;
  end;
  Result := InterlockedDecrement(FRefCount);
  if (Result = 0) and not FDestroying then
  begin
    FDestroying := True;
    Destroy;
  end;
end;
Damit bist Du immer auf der sicheren Seite.

Zusätzlich solltest Du gegebenenfalls _AddRef anpassen. Falls Du nämlich in Destroy auf das Objekt zugreifst wird der Zähler wieder erhöht .
Delphi-Quellcode:
function TInterfacedObject._AddRef: Integer;
begin
  if FDestroying then
    Result := FRefCount
  else
    Result := inherited _AddRef;
end;
Gruß
xaromz
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#4

Re: InterfacedObject freigeben

  Alt 24. Nov 2005, 15:21
Wenn ich das richtig sehe besteht das problem nur weil du ein intergefacestes objekt normal als klassen referens speicherst, denn anderenfalls wäre der refCount ja eins und das object würde bleiben, wenn das letzte element aus der liste entfernt würd. Richtig?

Ich mache das immer so, daß ich meiner klasse eine methode Release (die intern _Release aufruft) und free oder destroy garnicht direkt aufrufe, somit stimmt dann der refCount auch für deine klassen referenz.
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
tigerman33

Registriert seit: 30. Jul 2005
Ort: München
423 Beiträge
 
Delphi 2005 Professional
 
#5

Re: InterfacedObject freigeben

  Alt 25. Nov 2005, 09:12
Danke für eure schnellen Antworten.

@xaromz:
Ja, das mit dem fDestroying hatte ich mir auch überlegt. Ich dachte nur, vielleicht gibt es eine noch etwas elegantere Methode. Werd's aber jetzt wohl einfach so machen.

@maximov:
Sorry, aber ich verstehe nicht so ganz, was du mir sagen willst. Dass ich die Liste von vornherein nur als Interface speichern soll? Bin ich ehrlich gesagt nicht so versessen drauf. Und das mit dem zu niedrigen Referenzzähler hab ich ja umgangen indem ich im Konstruktor einfach die Referenz erhöht hab.

Das Problem ist ja eher folgendes (ich male mal so eine Art "Aufrufdiagramm"):

Liste.Free -> Liste.Destroy -> Liste.BeforeDestruction -> Interface._Release -> Liste.Destroy -> Liste.BeforeDestruction -> Interface._Release
etc etc

Diesen doppelten Aufruf des Destruktors wollte ich umgehen. Aber wie es scheint geht das tatsächlich nur indem ich ein neues Feld einführe.
Christian
Der Computer hilft mir, Probleme zu lösen, die ich ohne Computer nicht hätte.
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#6

Re: InterfacedObject freigeben

  Alt 5. Dez 2005, 10:51
Zitat von tigerman33:
...
@maximov:
Sorry, aber ich verstehe nicht so ganz, was du mir sagen willst. Dass ich die Liste von vornherein nur als Interface speichern soll? Bin ich ehrlich gesagt nicht so versessen drauf. Und das mit dem zu niedrigen Referenzzähler hab ich ja umgangen indem ich im Konstruktor einfach die Referenz erhöht hab.

Das Problem ist ja eher folgendes (ich male mal so eine Art "Aufrufdiagramm"):

Liste.Free -> Liste.Destroy -> Liste.BeforeDestruction -> Interface._Release -> Liste.Destroy -> Liste.BeforeDestruction -> Interface._Release
etc etc

Diesen doppelten Aufruf des Destruktors wollte ich umgehen. Aber wie es scheint geht das tatsächlich nur indem ich ein neues Feld einführe.
Das ist schon alles richtig, nur das freigeben würde ich nicht direkt über free machen. Ich dachte das eigentlich so: list.Release (free nicht direkt aufrufen) -> List._Release -> RefCount wird 0 -> Liste.Destroy -> fertig!

Das funktioniert dann auch wenn andere interface-referenzen auf die liste zeigen sollten.
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
tigerman33

Registriert seit: 30. Jul 2005
Ort: München
423 Beiträge
 
Delphi 2005 Professional
 
#7

Re: InterfacedObject freigeben

  Alt 5. Dez 2005, 12:31
Vielen Dank an alle, das Problem hat sich mittlerweile erübrigt. Hab's so gemacht wie von xaromz vorgeschlagen.
Dank an alle die mir geholfen haben.
Christian
Der Computer hilft mir, Probleme zu lösen, die ich ohne Computer nicht hätte.
  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 07:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz