![]() |
ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Ist irgendjemandem bewusst gewesen, dass dieses Konstrukt sich auf ARC und Nicht-ARC anders verhält
Delphi-Quellcode:
Unter Nicht-ARC erhält man die Ausgabe
type
TForm1 = class( TForm ) Button1: TButton; Label1: TLabel; Button2: TButton; procedure Button1Click( Sender: TObject ); private FRealInstance: TObject; [weak] FWeakInstance: TObject; public end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.Button1Click( Sender: TObject ); begin if Assigned( FRealInstance ) then FreeAndNil( FRealInstance ) else begin FRealInstance := TObject.Create; FWeakInstance := FRealInstance; end; Label1.Text := Format( {} 'RealInstance %x' + sLineBreak + {} 'WeakInstance1 %x', {} [ {0} NativeUInt( FRealInstance ), {1} NativeUInt( FWeakInstance )] ); end;
Code:
Unter ARC erhält man im Gegensatz dazu folgendes
1. Klick
RealInstance XXXXXXX WeakInstance XXXXXXX 2. Klick RealInstance 0 WeakInstance XXXXXXX
Code:
Da wird also der Wert der Weak-Referenz auf
1. Klick
RealInstance XXXXXXX WeakInstance XXXXXXX 2. Klick RealInstance 0 WeakInstance 0
Delphi-Quellcode:
gesetzt, wenn die Instanz aus dem Speicher fliegt.
nil
Finde ich ja grundsätzlich nicht schlecht, erschwert aber das Programmieren für beide Plattformen ... wäre ja schön gewesen, wenn da beide gleich reagieren würden (gerne mit dem automatischen Setzen auf
Delphi-Quellcode:
:stupid:)
nil
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Dass ARC Weak-Referenzen auf NIL setzt, sobald das referenzierte Objekt zerstört wird, ist meines Wissens sogar dokumentiert.
Weak-Pointer kennen nur zwei Zustände: Gültige Referenz und NIL. |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Der blöde Compiler gibt dir nichtmal eine Warnmeldung, wenn er das
Delphi-Quellcode:
einfach mal so ignoriert. :wall:
[Weak]
Delphi-Quellcode:
{$IFDEF WEAKREF} // Allgemein
{$IFDEF WEAKINSTREF} // Object {$IFDEF WEAKINTREF} // Interface |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
Mavarik |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Weak-Referenzen gibt es dort (noch) nicht.
Für Interfaces würde ich wir wünschen, daß die es endlich mal einbauen (die Unterscheidung von WEAKINSTREF und WEAKINTREF lässt mir noch Hoffnung, daß es "bald" kommt) und ob ARC nicht irgendwann auch in anderen Plattformen Einzug findet, ist nicht klar. Also machen kann man nichts, aber man würde wenigstens sofort erkennen, daß
Delphi-Quellcode:
dort keine Funktion hat.
[Weak]
Aber so merkt man es erst zur Laufzeit, wenn es knallt und raucht. Für Interfaces kann man Weak-Referenzen auch nachbauen, was ich für mich bereits gemacht hab, dank der Operatoren. |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Für normale Instanzen kann man WeakReference auch nachbauen. Bei der Umsetzung dessen bin ich auf dieses Verhalten erst gestossen. Gut für Nicht-ARC ist es schon ganz schöner Schweinecode, aber funktioniert zuverlässig und auf beiden Architekturen.
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
![]() |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
![]() Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Also die Delphi-WeakReferences kann ich gar nicht gebrauchen, weil das für jede Instanz egal von welcher Klasse benötige (z.B. für ein
Delphi-Quellcode:
und da kann ich eben nicht mal so eben ein zusätzliches Interface dranklatschen, ohne wilde Schreiborgie).
TBitmap
Ja, den Spring-Stevie-Weg habe ich auch gewählt (anders beschritten, aber auch über die Virtuellen Klassen) das geht dann einfach so mit jeder Klasse :) Aber der Spring springt mir zu sehr in meine eigene Bibliotheken rein (gleiche Funktionalitäten haben gleiche Namen) und da habe ich keine Lust ständig auf den Namespace zu achten. BTW: Bei mir schalte ich den gesamten VirtualClass-Kram unter ARC komplett ab, denn da geht das ja von Haus aus |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Die Spring-WeakReference funktioniert genau wie meine mit jeder Instanz egal von welcher Klasse.
Ich kann nur das gesamte Spring nicht gebrauchen ;) |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
Einfach nur die Referenzzählung deaktiviert, aber nichts mit automatischem nil.
Delphi-Quellcode:
Nix Großes ... im Grunde einfach nur die manuellen Casts im Generic verpackt. :stupid:
type
TWeakRef<Obj: class> = record private //FReference: {$IFDEF WEAKINSTREF}Obj{$ELSE}Pointer{$ENDIF}; {$IFDEF WEAKINSTREF} FReference: Obj; {$ELSE} FReference: Pointer; {$ENDIF} public class operator Implicit(const Value: Obj): TWeakRef<Obj>; inline; class operator Implicit(const Value: TWeakRef<Obj>): Obj; inline; end; TWeakIntf<Intf: IInterface> = record private //FReference: {$IFDEF WEAKINTREF}Intf{$ELSE}Pointer{$ENDIF}; {$IFDEF WEAKINTREF} FReference: Intf; {$ELSE} FReference: Pointer; {$ENDIF} public type PIntf = ^Intf; public class operator Implicit(const Value: Intf): TWeakIntf<Intf>; inline; class operator Implicit(const Value: TWeakIntf<Intf>): Intf; inline; end; { TWeakRef<Ref> } class operator TWeakRef<Obj>.Implicit(const Value: Obj): TWeakRef<Obj>; begin //Result.FReference := {$IFDEF WEAKINSTREF}Value{$ELSE}Pointer(Value){$ENDIF}; {$IFDEF WEAKINSTREF} Result.FReference := Value; {$ELSE} Result.FReference := Pointer(Value); {$ENDIF} end; class operator TWeakRef<Obj>.Implicit(const Value: TWeakRef<Obj>): Obj; begin //Result := {$IFDEF WEAKINSTREF}Value.FReference{$ELSE}Obj(Value.FReference){$ENDIF}; {$IFDEF WEAKINSTREF} Result := Value.FReference; {$ELSE} Result := Obj(Value.FReference); {$ENDIF} end; { TWeakIntf<Intf> } class operator TWeakIntf<Intf>.Implicit(const Value: Intf): TWeakIntf<Intf>; begin //Result.FReference := {$IFDEF WEAKINTREF}Value{$ELSE}PPointer(@Value)^{$ENDIF}; {$IFDEF WEAKINTREF} Result.FReference := Value; {$ELSE} Result.FReference := PPointer(@Value)^; {$ENDIF} end; class operator TWeakIntf<Intf>.Implicit(const Value: TWeakIntf<Intf>): Intf; begin //Result := {$IFDEF WEAKINTREF}Value.FReference{$ELSE}PIntf(@Value.FReference)^{$ENDIF}; {$IFDEF WEAKINTREF} Result := Value.FReference; {$ELSE} Result := PIntf(@Value.FReference)^; {$ENDIF} end; Generics und unterschiedliche DEFINEs funktioniert nicht. :cry: Außerdem erlauben Generics nur UND-Einschränkungen. (Object ODER Interface) Auch wenn WEAKINTREF und WEAKINSTREF bisher scheinbar immer gleich eingestellt sind, weiß ich nicht was in Zukunft passiert. Sonst hätte eine einzige Klasse gereicht. (per Code zur Laufzeit den Typ zu prüfen wollte ich nicht) Und nicht über die Kommentare wundern, aber die Parser von Error-Insight und Docu-Insight sind sowas von schrottig, daß ich den Originalcode aufteilen musste. :wall: [add] Ein Code ala
Delphi-Quellcode:
wäre cooler gewesen. :cry:
type
TWeak<Ref: class, interface> = record private FReference: {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass) or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}Obj{$ELSE}Pointer{$IFEND}; public class operator Implicit(const Value: Ref): TWeak<Ref>; inline; class operator Implicit(const Value: TWeak<Ref>): Ref; inline; end; { TWeak<Ref> } class operator TWeak<Ref>.Implicit(const Value: Ref): TWeak<Ref>; begin Result.FReference := {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass) or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}Value{$ELSE}Pointer(Value){$IFEND}; end; class operator TWeak<Ref>.Implicit(const Value: TWeak<Ref>): Ref; begin Result := {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass) or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}Value.FReference{$ELSE}Ref(Value.FReference){$IFEND}; end; Ab TComponent lässt sich ein schön kleiner Code für eine selbst-auf-nil-setzende Objektvariable realisieren. (ansonsten isses nur ein bissl umständlicher) |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
Zitat:
Wegen ARC. Joa, ist ja auch noch im Branch und mit den ARC Platformen selber mach ich nicht so viel, daher ist da noch nix zurecht geschneidertifdeft worden für. Zitat:
Aber die ganzen Sachen aus dem dynamicproxy Branch werden noch interessant. (hat da hinten nen Java developer gegähnt und irgendwas von "...vor 10 Jahren schon..." gesagt?) |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Also nix gegen das Spring4D Framework...Gute Arbeit.
Aber es ist mir einfach zu dick... Mavarik PS.: Gibt es nicht die Möglichkeit das [WEAK] tag über die RTTI aus zu lesen und entsprechend zu reagieren? |
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
|
AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:57 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