Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Delphi ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC (https://www.delphipraxis.net/183253-arc-weak-referenzen-mit-unterschiedlichem-verhalten-bei-arc-und-nicht-arc.html)

Sir Rufo 23. Dez 2014 14:54


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:
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;
Unter Nicht-ARC erhält man die Ausgabe
Code:
1. Klick
RealInstance XXXXXXX
WeakInstance XXXXXXX
2. Klick
RealInstance 0
WeakInstance XXXXXXX
Unter ARC erhält man im Gegensatz dazu folgendes
Code:
1. Klick
RealInstance XXXXXXX
WeakInstance XXXXXXX
2. Klick
RealInstance 0
WeakInstance 0
Da wird also der Wert der Weak-Referenz auf
Delphi-Quellcode:
nil
gesetzt, wenn die Instanz aus dem Speicher fliegt.

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:
nil
:stupid:)

Daniel 23. Dez 2014 15:04

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.

Stevie 23. Dez 2014 15:10

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284557)
Ist irgendjemandem bewusst gewesen, dass dieses Konstrukt sich auf ARC und Nicht-ARC anders verhält

Logisch, Nicht-ARC = nix weak. Ergo ist auf Nicht-ARC FWeakInstance auch keine Weakreference, weswegen sie auch nicht angefasst wird.

himitsu 23. Dez 2014 15:15

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:
[Weak]
einfach mal so ignoriert. :wall:

Delphi-Quellcode:
{$IFDEF WEAKREF} // Allgemein
{$IFDEF WEAKINSTREF} // Object
{$IFDEF WEAKINTREF} // Interface

Daniel 23. Dez 2014 15:25

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von himitsu (Beitrag 1284562)
Der blöde Compiler gibt dir nichtmal eine Warnmeldung, wenn er das
Delphi-Quellcode:
[Weak]
einfach mal so ignoriert. :wall:

Was würdest Du denn als Reaktion auf so eine Warnung tun wollen? Wie Stevie schon schrieb, gibt es unter den klassischen Compilern kein ARC und damit auch kein Weak.

Mavarik 23. Dez 2014 15:28

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Daniel (Beitrag 1284564)
Zitat:

Zitat von himitsu (Beitrag 1284562)
Der blöde Compiler gibt dir nichtmal eine Warnmeldung, wenn er das
Delphi-Quellcode:
[Weak]
einfach mal so ignoriert. :wall:

Was würdest Du denn als Reaktion auf so eine Warnung tun wollen? Wie Stevie schon schrieb, gibt es unter den klassischen Compilern kein ARC und damit auch kein Weak.

Merken, dass "mein" Sourcecode nicht Plattformübergreifend funktioniert und ein IFDEF einfügen...

Mavarik

himitsu 23. Dez 2014 16:37

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:
[Weak]
dort keine Funktion hat.
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.

Der schöne Günther 23. Dez 2014 16:43

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von himitsu (Beitrag 1284571)
Für Interfaces kann man Weak-Referenzen auch nachbauen, was ich für mich bereits gemacht hab, dank der Operatoren.

Das möchtest du bestimmt einmal zeigen. :wink:

Sir Rufo 23. Dez 2014 17:14

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.

Stevie 23. Dez 2014 17:44

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284577)
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.

Spar dir die Arbeit, hab ich schon fertig :stupid:

alda 23. Dez 2014 18:03

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Stevie (Beitrag 1284582)
Zitat:

Zitat von Sir Rufo (Beitrag 1284577)
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.

Spar dir die Arbeit, hab ich schon fertig :stupid:

Oder alternativ hier: Delphi-WeakReferences :)

Zitat:

Zitat von Der schöne Günther (Beitrag 1284574)
Zitat:

Zitat von himitsu (Beitrag 1284571)
Für Interfaces kann man Weak-Referenzen auch nachbauen, was ich für mich bereits gemacht hab, dank der Operatoren.

Das möchtest du bestimmt einmal zeigen. :wink:

Letztendlich ist es "einfach" ein Pointer auf das Interface, da Pointer von Haus aus weak sind (z.B TAggregatedObject).

Sir Rufo 23. Dez 2014 18:28

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:
TBitmap
und da kann ich eben nicht mal so eben ein zusätzliches Interface dranklatschen, ohne wilde Schreiborgie).

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

alda 23. Dez 2014 18:42

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284589)
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:
TBitmap
und da kann ich eben nicht mal so eben ein zusätzliches Interface dranklatschen, ohne wilde Schreiborgie).

Das ist korrekt, wollte es auch einfach nur mit einwerfen (ohne Wertung) ;-) Hatte die Spring-WeakReference auch bisher noch nicht genutzt, aber da scheint Stefan mal wieder super Arbeit geleistet zu haben ;-)

Zitat:

Zitat von Sir Rufo (Beitrag 1284589)
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 :)

Wo funktioniert die Spring-WeakReference denn nicht?

Sir Rufo 23. Dez 2014 18:45

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 ;)

himitsu 23. Dez 2014 19:22

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1284574)
Das möchtest du bestimmt einmal zeigen. :wink:

War eine Designstudie, war noch nie im realen Einsatz und ich hoffe ich hab auf die Schnelle auch die richtige Version erwischt. :oops:
Einfach nur die Referenzzählung deaktiviert, aber nichts mit automatischem nil.

Delphi-Quellcode:
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;
Nix Großes ... im Grunde einfach nur die manuellen Casts im Generic verpackt. :stupid:


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:
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;
wäre cooler gewesen. :cry:


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)

Stevie 23. Dez 2014 21:25

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von alda (Beitrag 1284587)
Oder alternativ hier: Delphi-WeakReferences :)

Die machen das nur für Interfaces, mööp :stupid:

Zitat:

Zitat von Sir Rufo (Beitrag 1284589)
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

Eventuell magst du mir mal ne PM oder email schreiben, was da kollidiert. Eventuell findet sich ja ein Weg, das kompatibel zu machen.
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:

Zitat von alda (Beitrag 1284592)
Hatte die Spring-WeakReference auch bisher noch nicht genutzt, aber da scheint Stefan mal wieder super Arbeit geleistet zu haben ;-)

Wird sich zeigen, ist letzlich so ähnlich implementiert, wie die weak references in der RTL (ob das gut oder schlecht ist, lass ich nun so stehen :stupid:)
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?)

Mavarik 26. Dez 2014 13:07

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?

alda 26. Dez 2014 15:40

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von Mavarik (Beitrag 1284716)
Also nix gegen das Spring4D Framework...Gute Arbeit.
Aber es ist mir einfach zu dick...

Es zwingt Dich ja keiner das ganze Framework einzubinden, wenn Du nur Funktionalität X benötigst. ;>

Stevie 26. Dez 2014 18:12

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC
 
Zitat:

Zitat von alda (Beitrag 1284733)
Es zwingt Dich ja keiner das ganze Framework einzubinden, wenn Du nur Funktionalität X benötigst. ;>

Mit genau dieser Zielsetzung sind auch die meisten grundlegenden Datentypen und Funktionalitäten aufgebaut. Für vieles davon bindest nur die Spring.pas ein und hast, was du brauchst. Um den Rest aus der Unit, den du nicht benutzt, kümmert sich der Smartlinker.


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