|
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.340 Beiträge Delphi 12 Athens |
#1
Einige kennen doch bestimmt das Problem, daß wenn sich Interfaces gegenseitig referenzieren,
daß diese, selbst bei Freigabe aller externen Referenzen, sich dennoch nicht freigeben, da sie sich ja gegenseitig halten.
Delphi-Quellcode:
Nja, da ich hiermit immer mal wieder Probleme hatte und deswegen oftmals sogar auf Interfaces verzichtete,
type
TObjektMaster = Class(InterfacedObject); FSlave: IInterface; End; TObjektSlave = Class(InterfacedObject); FMaster: IInterface; End; wollte ich endlich mal dafür eine befriedigende Lösung finden. Erstmal 2 "einfache" Varianten, bei welchen man Referenzen registrieren kann, welche praktisch nicht gezählt werden sollen.
Delphi-Quellcode:
type
IXRefInterface = Interface // register after set to the reference variable // unregister before free the reference variable Procedure RegisterXRef; Function UnregisterXRef: Boolean; // FALSE if the object was destroyed End; TXRefInterfacedObject = Class(TObject, IInterface, IXRefInterface) Protected {IInterface} Function QueryInterface(Const IID: TGUID; Out Obj): HResult; StdCall; Function _AddRef: Integer; StdCall; Function _Release: Integer; StdCall; Protected {IXRefInterface} FRefCount, FXRefs: Integer; Procedure RegisterXRef; Function UnregisterXRef: Boolean; // FALSE if the object was destroyed Procedure DoFreeXRefs; Virtual; Public Procedure AfterConstruction; Override; Procedure BeforeDestruction; Override; Class Function NewInstance: TObject; Override; Property RefCount: Integer Read FRefCount; End; Function TXRefInterfacedObject.QueryInterface(Const IID: TGUID; Out Obj): HResult; Begin If GetInterface(IID, Obj) Then Result := S_OK Else Result := E_NOINTERFACE; End; Function TXRefInterfacedObject._AddRef: Integer; Begin Result := InterlockedIncrement(FRefCount); End; Function TXRefInterfacedObject._Release: Integer; Begin Result := InterlockedDecrement(FRefCount); If Result = FXRefs Then Destroy; End; Procedure TXRefInterfacedObject.RegisterXRef; Begin InterlockedIncrement(FXRefs); End; Function TXRefInterfacedObject.UnregisterXRef: Boolean; Begin InterlockedDecrement(FXRefs); Result := FRefCount <> FXRefs; If not Result Then Destroy; End; Procedure TXRefInterfacedObject.DoFreeXRefs; Begin // do nothing End; Procedure TXRefInterfacedObject.AfterConstruction; Begin // release the constructor's implicit refcount InterlockedDecrement(FRefCount); End; Procedure TXRefInterfacedObject.BeforeDestruction; Begin If FRefCount <> FXRefs Then Error(reInvalidPtr); DoFreeXRefs; If FRefCount <> 0 Then Error(reInvalidPtr); End; Class Function TXRefInterfacedObject.NewInstance: TObject; Begin Result := Inherited NewInstance; TInterfacedObject(Result).FRefCount := 1; End;
Delphi-Quellcode:
type
IXRefInterface = Interface // release before free the reference variable Function GetNonCounteredReference: IInterface; Procedure ReleaseNonCounteredReference; End; TXRefInterfacedObject = Class(TObject, IInterface, IXRefInterface) Protected {IInterface} Function QueryInterface(Const IID: TGUID; Out Obj): HResult; StdCall; Function _AddRef: Integer; StdCall; Function _Release: Integer; StdCall; Protected {IXRefInterface} FRefCount, FXRefs: Integer; Function GetNonCounteredReference: IInterface; Procedure ReleaseNonCounteredReference; Procedure DoFreeXRefs; Virtual; Public Procedure AfterConstruction; Override; Procedure BeforeDestruction; Override; Class Function NewInstance: TObject; Override; Property RefCount: Integer Read FRefCount; End; Function TXRefInterfacedObject.QueryInterface(Const IID: TGUID; Out Obj): HResult; Begin If GetInterface(IID, Obj) Then Result := S_OK Else Result := E_NOINTERFACE; End; Function TXRefInterfacedObject._AddRef: Integer; Begin Result := InterlockedIncrement(FRefCount); End; Function TXRefInterfacedObject._Release: Integer; Begin Result := InterlockedDecrement(FRefCount); If Result = FXRefs Then Destroy; End; Function GetNonCounteredReference: IInterface; Begin InterlockedIncrement(FXRefs); Result := Self; End; Procedure ReleaseNonCounteredReference; Begin InterlockedDecrement(FXRefs); //If FRefCount = FXRefs Then Destroy; End; Procedure TXRefInterfacedObject.DoFreeXRefs; Begin // do nothing End; Procedure TXRefInterfacedObject.AfterConstruction; Begin // release the constructor's implicit refcount InterlockedDecrement(FRefCount); End; Procedure TXRefInterfacedObject.BeforeDestruction; Begin If FRefCount <> FXRefs Then Error(reInvalidPtr); DoFreeXRefs; If FRefCount <> 0 Then Error(reInvalidPtr); End; Class Function TXRefInterfacedObject.NewInstance: TObject; Begin Result := Inherited NewInstance; TInterfacedObject(Result).FRefCount := 1; End; Und dann noch eine Variante, bei welcher jeweils erneut durchgezählt wird, was wirklich frei ist.
Delphi-Quellcode:
type
TXRefInterfacedObject = Class(TObject, IInterface) Protected {IInterface} Function QueryInterface(Const IID: TGUID; Out Obj): HResult; StdCall; Function _AddRef: Integer; StdCall; Function _Release: Integer; StdCall; Protected FRefCount: Integer; Procedure DoCountingXRefs(Var Count: Integer); Virtual; Procedure DoFreeXRefs; Virtual; Public Procedure AfterConstruction; Override; Procedure BeforeDestruction; Override; Class Function NewInstance: TObject; Override; Property RefCount: Integer Read FRefCount; End; Function TXRefInterfacedObject.QueryInterface(Const IID: TGUID; Out Obj): HResult; Begin If GetInterface(IID, Obj) Then Result := S_OK Else Result := E_NOINTERFACE; End; Function TXRefInterfacedObject._AddRef: Integer; Begin Result := InterlockedIncrement(FRefCount); End; Function TXRefInterfacedObject._Release: Integer; Var XRefs: Integer; Begin XRefs := 0; DoCountingXRefs(XRefs); Result := InterlockedDecrement(FRefCount); If Result = XRefs Then Destroy; End; Procedure TXRefInterfacedObject.DoCountingXRefs(Var Count: Integer); Begin // do nothing End; Procedure TXRefInterfacedObject.DoFreeXRefs; Begin // do nothing End; Procedure TXRefInterfacedObject.AfterConstruction; Begin // release the constructor's implicit refcount InterlockedDecrement(FRefCount); End; Procedure TXRefInterfacedObject.BeforeDestruction; Var XRefs: Integer; Begin XRefs := 0; DoCountingXRefs(XRefs); If FRefCount <> XRefs Then Error(reInvalidPtr); DoFreeXRefs; If FRefCount <> 0 Then Error(reInvalidPtr); End; Class Function TXRefInterfacedObject.NewInstance: TObject; Begin Result := Inherited NewInstance; TInterfacedObject(Result).FRefCount := 1; End;
So, nun seid ihr gefragt. Wie würdet oder wie habt ihr solche Probleme gelöst, bzw. welche Variante (kann auch eine ganz Andere sein) würdet ihr bevorzugen und wo würdet ihr euer Pro und Contra setzen?
Ein Therapeut entspricht 1024 Gigapeut.
|
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |