![]() |
AW: class operator OnesComplement ? o.O
Nur mal kurz zusammengeschludert:
Delphi-Quellcode:
program RecordFinalizer;
{$APPTYPE CONSOLE} {$R *.res} uses Generics.Collections, SysUtils, TypInfo, DDetours; type TFinalizer = procedure (Self: Pointer); TCopyOperator = procedure (Dest, Source: Pointer); var Finalizers: TDictionary<PTypeInfo,TFinalizer>; CopyOperators: TDictionary<PTypeInfo,TCopyOperator>; type TMyRecord = record private s: string; public procedure Destroy; class procedure Copy(var dest, source: TMyRecord); static; end; { TMyRecord } class procedure TMyRecord.Copy(var dest, source: TMyRecord); begin dest.s := 'Copy: ' + source.s; end; procedure TMyRecord.Destroy; begin Writeln(s); Writeln('TMyRecord.Destroy'); end; procedure Main; var r, r2: TMyRecord; begin r.s := 'Hello World'; r2 := r; end; function GetFinalizeRecord: Pointer; asm mov @Result, offset System.@FinalizeRecord end; function GetCopyRecord: Pointer; asm mov @Result, offset System.@CopyRecord end; var FinalizeRecord: function(p: Pointer; typeInfo: Pointer): Pointer; CopyRecord: procedure (Dest, Source, TypeInfo: Pointer); function FinalizeRecordHook(p: Pointer; typeInfo: Pointer): Pointer; var finalizer: TFinalizer; begin if Finalizers.TryGetValue(typeInfo, finalizer) then finalizer(p); if Assigned(FinalizeRecord) then Result := FinalizeRecord(p, typeInfo); end; procedure CopyRecordHook(Dest, Source, TypeInfo: Pointer); var copyOperator: TCopyOperator; begin if CopyOperators.TryGetValue(TypeInfo, copyOperator) then copyOperator(Dest, Source) else CopyRecord(Dest, Source, TypeInfo); end; begin Finalizers := TDictionary<PTypeInfo,TFinalizer>.Create; Finalizers.Add(TypeInfo(TMyRecord), @TMyRecord.Destroy); CopyOperators := TDictionary<PTypeInfo,TCopyOperator>.Create; CopyOperators.Add(TypeInfo(TMyRecord), @TMyRecord.Copy); FinalizeRecord := InterceptCreate(GetFinalizeRecord, @FinalizeRecordHook); CopyRecord := InterceptCreate(GetCopyRecord, @CopyRecordHook); try Main; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; ReportMemoryLeaksOnShutdown := True; InterceptRemove(@FinalizeRecord); InterceptRemove(@CopyRecord); Finalizers.Free; CopyOperators.Free; end. |
AW: class operator OnesComplement ? o.O
Zitat:
Immer wenn ich "Deinen" Sourcecode lese, habe ich das Gefühl ich habe keine Ahnung von Delphi... :stupid: Bedeutet das ich kann doch den RecordCopy "überladen"? Problem ist:
Delphi-Quellcode:
Leider ist Foo[3] danach mit 'Soll nicht geändert werden' belegt, da "nur" die Referenzen Kopiert werden.
type
TFoo = record A : Array of String; end; Var Foo : TFoo; Procedure MachNixMitFoo; var Merk : TFoo; begin Merk := Foo; Foo[3] := 'Soll nicht geändert werden'; Machwas(Foo); Foo := Merk; end; Bietet "Deine" Routine da einen Lösung? Mavarik |
AW: class operator OnesComplement ? o.O
Das ist das eines der Probleme, die ich damit lösen wollte.
Für dynamische Arrays gibt es kein CopyOnWrite, wenn man schreibend auf ein Feld des dynamischen Arrays zugreift. Bei Strings (die intern auch nur aufgemotzte dynamische Arrays sind) wird vor jedem Schreibzugriff auf ein Char (da ja
Delphi-Quellcode:
) sichergestellt, daß RefCount auch 1 ist.
array[1..length] of char
(durch Aufruf von ![]() |
AW: class operator OnesComplement ? o.O
Zitat:
D.h. bei allen vom Compiler generierten CopyRecord aufrufen in deiner gesamten Anwendung läuft der extra Dictionary Lookup. Ich bin ja schon recht großzügig, Code nicht als Hack sondern als "geschickte Ausnutzung der Mechanik" zu bezeichnen, aber das ist definitiv ein Hack - und zwar ein gewaltiger - da muss man schon wissen, was man damit anstellt :) Zitat:
Delphi-Quellcode:
Jo, müsste gehen.
class procedure TFoo.Copy(var dest, source: TFoo);
begin dest.a := System.Copy(source.a); end; Gibt allerdings noch eine andere Möglichkeit, die genauso funktioniert, wie bei Strings:
Delphi-Quellcode:
type
TFoo = record private a: array of string; function GetItem(i: Integer): string; inline; procedure SetItem(i: Integer; const Value: string); inline; public property Items[i: Integer]: string read GetItem write SetItem; default; end; function GetArrayRef(A: Pointer): Integer; inline; type // geliehen aus der System.pas PDynArrayRec = ^TDynArrayRec; TDynArrayRec = packed record {$IFDEF CPUX64} _Padding: LongInt; {$ENDIF} RefCnt: LongInt; Length: NativeInt; end; begin Result := NativeInt(A); if Result <> 0 then Result := PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt; end; function TFoo.GetItem(i: Integer): string; begin Result := a[i]; end; procedure TFoo.SetItem(i: Integer; const Value: string); begin if GetArrayRef(a) > 1 then a := System.Copy(a); a[i] := Value; end; |
AW: class operator OnesComplement ? o.O
Am schönsten wäre es ja, wenn man auf sowas wie deim GetArrayRef verzichten könnte.
Für Strings hat man das ja inzwischen auch eingebaut. ![]() Copy(arr) ruft System.DynArrayCopy auf, aber du kannst stattdessen, und ohne RefCount vorher zu prüfen, System.DynArrayUnique ausrufen (prüft selbst intern das RefCount) Aber am "optimalsten" wäre es halt, wenn Emba solche Methoden in der RTTI aufnimmt, also direkt als Flag/Referenz, so wie z.B. beim [Weak]-Status, und dann in den originalen Funktionen ganz schnell zu schauen, ob es was zum Aufrufen gibt, welches per Class-Operator dort eingetragen wurde. |
AW: class operator OnesComplement ? o.O
Zitat:
Ich suche eher eine Lösung für den Umstiegt von Short auf Long und Array[L..H] nach Array of... Beispiel:
Delphi-Quellcode:
Der "Rest" der Software hat keine Ahnung von der Umstellung... Abgesehen von den entsprechenden SetLength.
type
TFooOld = Record Bla : Integer; Blub : Array[0..10] of Shortstring; end; TFooNeu = Record Bla : Integer; Blub : Array of String; // Oder auch TStringDynArray end; So ALLE
Delphi-Quellcode:
müssen sich genau verhalten wie vorher... Ohne
var
A,B : TFooNeu; begin ... A := B; end;
Delphi-Quellcode:
aufrufen zu müssen....
A := B.Clone
Mavarik |
AW: class operator OnesComplement ? o.O
Blub als Array-Property deklarieren und dort im Setter ein UniqueArray.
|
AW: class operator OnesComplement ? o.O
Zitat:
Einfach Zähne zusammen beißen, die Record Types vernünftig kapseln und dann is gut. |
AW: class operator OnesComplement ? o.O
Zitat:
Gab es das schon in D2007? Momentan mach ich immer ein Copy im Setter... |
AW: class operator OnesComplement ? o.O
k.A.
In XE(1) hab ich es nicht gefunden ... dachte aber das gibt's schon viel länger. Vielleicht unter einem anderem Name, aber auch da fand ich auf die Schnelle nix. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:36 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