![]() |
Delphi-Version: XE7
Weak-TList ?
Tachchen.
Delphi-Quellcode:
Die Variable wäre jetzt ohne Referenzzählung, im NextGen-Compiler,
var
[Weak] Variable: IInterface; [Weak] Liste: TList<IInterface>; Liste: TList<[Weak] IInterface>; // geht nicht - Error-Insight und Compiler sagen nein aber wie definiert man eigentlich eine Liste mit Weak-Referenzen? Bei
Delphi-Quellcode:
ist natürlich (nur?) die Liste-Variable ohne Referenzzählung, aber nicht der Listeninhalt. So würde ich die OH verstehen tun.
[Weak] Liste: TList<IInterface>;
Kann es leider nicht ausprobieren und die Compiler sind diesbezüglich echt doof und geben keinerlei Meldungen/Fehlermeldungen, ob Attribute richtig sind oder ob sie es nicht sind. Nichtmal bei Denen, die den Compiler und den erzeugten Code/Typen/RTTI selber betreffen. :wall: Die Hilfe sagt natürlich rein garnichts, zu [Weak] bei Typen. Und in der Hilfe zum WeakAttribute steht wirklich GARNICHTS (nur der bekannte nichtssagende Schrott).
Delphi-Quellcode:
type
IWeakInterface = [Weak] IInterface; // Hier sträubt sich das Error-Insight und der Compiler. [Weak] IWeakInterface = IInterface; // Geht das? [Weak] IWeakInterface = type IInterface; // Und ist das richtig? var Liste: TList<IWeakInterface>; |
AW: Weak-TList ?
Zitat:
|
AW: Weak-TList ?
Delphi-Quellcode:
program WeakRefListTests;
uses TestFramework, TestInsight.DUnit, Spring, Spring.Collections; type TWeakRefListTest = class(TTestCase) published procedure ListDoesNotKeepStrongReference; end; IRefCounted = interface function GetRefCount: Integer; property RefCount: Integer read GetRefCount; end; TRefCounted = class(TInterfacedObject, IRefCounted); procedure TWeakRefListTest.ListDoesNotKeepStrongReference; var sut: IList<WeakReference<IRefCounted>>; ref: IRefCounted; begin sut := TCollections.CreateList<WeakReference<IRefCounted>>; ref := TRefCounted.Create; sut.Add(ref); CheckEquals(1, ref.RefCount); ref := nil; CheckFalse(sut[0].IsAlive); ref := sut[0]; CheckNull(ref); end; begin RegisterTest(TWeakRefListTest.Suite); RunRegisteredTests(); end. |
AW: Weak-TList ?
Nja, dachte daß Delphi sowas auch selber kann. :roll:
Die [Weak]-Referenzen werden doch auch nicht auf nil gesetzt, sondern sind dann einfach nur "ungültige" Zeiger. Aber das Problem gibt es nicht, da sich die Interfaces selber überall raus löschen, wenn sie freigegeben werden. (die kennen die Gegenseite, da sie selber eine gezählte Referenz besitzen, oder sie kennen wen, der den kennt) Nur dürfen diese Referenzen halt nicht gezählt werden, damit sie sich freigeben können. Für einzelne Variablen und Felder geht das Einfach, aber wie man das für Listen/Arrays deklariert, ist nirgendwo beschrieben, obwohl es irgendwie gehen soll. |
AW: Weak-TList ?
Zitat:
|
AW: Weak-TList ?
|
AW: Weak-TList ?
Im ARC wollte ich mal versuchen das möglichst alles "nativ" zu belassen. :stupid:
|
AW: Weak-TList ?
Zitat:
Hier mal ein Beispiel, wo so eine WeakRef-Record für ARC sinnvoll verwendet werden kann:
Delphi-Quellcode:
Du erzeugst also einen Task, der irgendwann gestartet werden soll. Die übergebene Bitmap kann aber bis zum echten Start schon wieder verschwunden sein. Ist die Bitmap beim Starten aber nicht verschwunden, dann wird im Task wieder eine Strong-Ref auf Bitmap gemacht und schon lebt die Referenz bis zum Ende des Tasks.
function Foo( const ABitmap : TBitmap ):ITask;
var LBitmapRef: WeakRef<TBitmap>; begin // WeakRef auf Bitmap LBitmapRef := ABitmap; Result := TTask.Create( procedure var LBitmap : TBitmap; begin // StrongRef auf Bitmap, damit die bis zum Ende des Tasks überlebt, wenn es die noch gibt :o) LBitmap := LBitmapRef; // Wenn Bitmap schon weg ist, dann raus hier if not Assigned( LBitmap ) then Exit; // Now work on Bitmap end ); end; |
AW: Weak-TList ?
Mit "nativ" meinte ich "Nur mit den Mitteln dessen, was Delphi selber kann", also ohne Fremdkomponenten und möglichst ohne viel selbst zu basteln.
Die ersten Beiden sollten schon funktionieren (zumindestens im NextGen/WEAKINTREF),
Delphi-Quellcode:
type
TParent = class(TInterfacedObject, IParent) FChild: IChild; end; TChild = class(TInterfacedObject, IChild) [Weak] FParent: IParent; end;
Delphi-Quellcode:
aber hier hängt es, also wie man das genau "definiert".
type
TParent = class(TInterfacedObject, IParent) FChilds: TList<IChild>; end; TChild = class(TInterfacedObject, IChild) [Weak] FParent: IParent; end;
Delphi-Quellcode:
Wenn Delphi das dann in den nächsten 20 Jahren endlich mal in allen Compileren richtig drin hat,
type
TParent = class(TInterfacedObject, IParent) FLink: ILink; end; TLink = class(TInterfacedObject, ILink) FParents: TList<[Weak] IParent>; end; (k.A. warum man [Weak] für Interfaces nicht überall eingebaut hat :wall:) dann wäre jetzt kein weiterer Code mehr nötig. |
AW: Weak-TList ?
Ich hatte nun 'ne ganze Weile versucht damit einen "ordentlichen" Code hinzubekommen, welcher auf allen Platformen richtig funktioniert.
Also mit den aktuellen/alten Möglichkeiten der Delphi-Compiler
Delphi-Quellcode:
,
[Weak]
Delphi-Quellcode:
,
[Unsafe]
Delphi-Quellcode:
und
[Ref]
Delphi-Quellcode:
.
[Volatile]
Den Blick in OH/Dokwiki könnt ihr vergessen, denn bei den Attributen ist nichts zu finden, aber es gibt einen anderen etwas versteckteren Hilfe-Eintrag dazu. (verlinken können die sowas natürlich nicht) Fazit: Alles Mist und ich caste die Rückreferenzen nun überall nur noch selbst als Pointer. Für "einfache" 1:1-Kreuzverlinkungen mit einfachen Variablen ist
Delphi-Quellcode:
und
[Weak]
Delphi-Quellcode:
im ARC allerdings ganz praktisch, auch wenn es keine richtig nicht-referenzgezählten Variablen gibt, wo es absolut keine Behandlung von Referenzen gibt.
[Unsafe]
Aber sobald Listen oder kompliziertere n:n-Verlinkungen ins Spiel kommen, ist es nahezu unmöglich einen "nativen" Code zu schreiben, der wirklich überall läuft und das auch nur mit ausreichenden IFDEFs oder über Fremdkomponenten. Wenn ich bissl aufgeräumt und alles nochmal durchgelesen hab, dann werde ich demnächst mal meine Testanwendung/Testcode/Artikel für diese beiden "schwachen Referenzen" hochladen. Leider gibt es
Delphi-Quellcode:
,
[Weak]
Delphi-Quellcode:
und
[Unsave]
Delphi-Quellcode:
nicht in allen Platformen.
[NoRefCount]
![]() Im Grunde ist das der Grund, warum ich einige Komponenten nun komplett und umständlich (da doppelte Deklarationen usw.) auf Interfaces umstelle, damit sie überall funktionieren und überall gleich benutzbar sind. Grade bei den Interfaces gibt es nun, dank
Delphi-Quellcode:
und AutoRefCount (für interne Objekte), dennoch standardmäßig kein gleiches Verhalten, außer man sorgt selber auf brutalste Weise dafür. :wall:
[Weak]
(nur Interfaces ohne irgendwelche Objektreferenzen und ohne schwachen Referenzen arbeiten wirklich überall gleich) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:25 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