Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Properties, ihre Getter und Setter und Thread-Safety (https://www.delphipraxis.net/173775-properties-ihre-getter-und-setter-und-thread-safety.html)

Der schöne Günther 15. Mär 2013 13:38

Delphi-Version: XE2

Properties, ihre Getter und Setter und Thread-Safety
 
Die von Ärzten empfohlene tägliche Dosis von Themen zu Threads ist bereits überschritten, ich weiß :oops:

Aber bislang sind (auch in anderen Sprachen und Umgebungen) viele Dinge (darunter auch Properties überhaupt) an mir vorbeigezogen, deshalb die Frage.

Sachstand:
  • Ich habe eine Klasse mit ein paar Membern (sowohl PODs als auch Strings und andere Klassen)
  • Diese Klasse hat auch einen
    Delphi-Quellcode:
    TThread
    (als innere Klasse) der ab und zu die Member der äußeren Klasse aktualisiert


Problem/Frage:
  1. Ich habe nicht wirklich Lust, für alle jetzigen und noch kommenden Member manuell eigene
    Delphi-Quellcode:
    TCriticalSection
    s zu definieren.
  2. Selbst wenn ich eine
    Delphi-Quellcode:
    TCriticalSection
    für alle Member recycle, müsste ich doch immer noch für jeden Member eine Property mit eigenem Getter und Setter bauen in der dann ständig der kritische Abschnitt betreten und verlassen wird. Selbst wenn ich (sinnvollerweise) stattdessen einen
    Delphi-Quellcode:
    TMultiReadExclusiveWriteSynchronizer
    (den ich mir noch nicht angesehen habe) benutzen würde - Das Gefummel mit den Properties bliebe wohl.


Was soll ich tun? Kann mir irgendeine geheime Property-Magie helfen? :|

Sir Rufo 15. Mär 2013 14:05

AW: Properties, ihre Getter und Setter und Thread-Safety
 
Also für Faule gibt es z.B. folgende Lösung
Delphi-Quellcode:
unit CSLazy;

interface

uses
  SyncObjs;

type
  ICS = interface
    ['{C1D6A40D-14CA-4E33-8FF7-CD0A01385343}']
    procedure Enter;
    function TryEnter : Boolean;
    procedure Leave;
  end;

function CS( ACS : TCriticalSection ) : ICS;

implementation

type
  TCS = class( TInterfacedObject, ICS )
  private
    FCS :     TCriticalSection;
    FEntered : Boolean;
  protected
    procedure Enter;
    function TryEnter : Boolean;
    procedure Leave;
  public
    constructor Create( ACS : TCriticalSection );
    destructor Destroy; override;
  end;

function CS( ACS : TCriticalSection ) : ICS;
begin
  if Assigned( ACS )
  then
    Result := TCS.Create( ACS )
  else
    Result := nil;
end;

{ TCS }

constructor TCS.Create( ACS : TCriticalSection );
begin
  inherited Create;
  FCS := ACS;
end;

destructor TCS.Destroy;
begin
  if FEntered
  then
    FCS.Leave;

  inherited;
end;

procedure TCS.Enter;
begin
  FCS.Enter;
  FEntered := True;
end;

procedure TCS.Leave;
begin
  FCS.Leave;
  FEntered := False;
end;

function TCS.TryEnter : Boolean;
begin
  Result  := FCS.TryEnter;
  FEntered := Result;
end;

end.
Benutzung:
Delphi-Quellcode:
type
  TMyThread = class( TThread )
  private
    FCS : TCriticalSection;
    FValue : string;
    function GetValue : string;
    procedure SetValue( const Value : string );
  public
    property Value : string read GetValue write SetValue;
  end;

function TMyThread.GetValue : string;
begin
  CS( FCS ).Enter;
  Result := FValue;
end;

procedure TMyThread.SetValue( const Value : string );
begin
  CS( FCS ).Enter;
  FValue := Value;
end;
UPDATE

Du könntest auch über indizierte Properties gehen, dann hast du nur einen Getter/Setter für alle (gut der Typ muss gleich sein, wobei ja auch z.B. Delphi-Referenz durchsuchenTValue oder Delphi-Referenz durchsuchenVariant als Typ möglich wären).

Der schöne Günther 15. Mär 2013 14:22

AW: Properties, ihre Getter und Setter und Thread-Safety
 
Das ist aber gewitzt :-D - Einfach mal so ein Objekt erzeugen dass im Konstruktor den kritischen Abschnitt betritt um dann mit seinem Destruktor wieder herauszuhüpfen. Da das auch das einzige ist was hier im Getter/Setter der Property passiert wird der ja auch fix wieder aufgerufen.

Das ist schonmal ein echter Zaubertrick, Danke dafür!

Was mich nach wie vor etwas unbefriedigt zurücklässt ist die Tatsache, dass ich nicht einmal deb "Einer erschlägt alles" Getter/Setter schreiben kann - Für eine zweite Instanzvariable neben FValue (z.B. vom Typ Single) wären nach wie vor wieder ein Getter und Setter fällig. Da liegt der Hund begraben!

Edit
Und
Delphi-Quellcode:
TValue
scheint auf den ersten Blick dann auch dafür die Lösung zu sein - Anscheinend der void-Datentyp Delphis :-D

Sir Rufo 15. Mär 2013 14:26

AW: Properties, ihre Getter und Setter und Thread-Safety
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1207571)
Das ist aber gewitzt :-D - Einfach mal so ein Objekt erzeugen dass im Konstruktor den kritischen Abschnitt betritt um dann mit seinem Destruktor wieder herauszuhüpfen. Da das auch das einzige ist was hier im Getter/Setter der Property passiert wird der ja auch fix wieder aufgerufen.

Das macht meine Klasse jetzt ja so nicht, aber wäre auch möglich :)
Zitat:

Zitat von Der schöne Günther (Beitrag 1207571)
Das ist schonmal ein echter Zaubertrick, Danke dafür!

Das sind halt Interfaces :) - Da erledigt sich auch sofort das lästige
Delphi-Quellcode:
try finally
Zitat:

Zitat von Der schöne Günther (Beitrag 1207571)
Was mich nach wie vor etwas unbefriedigt zurücklässt ist die Tatsache, dass ich nicht einmal deb "Einer erschlägt alles" Getter/Setter schreiben kann - Für eine zweite Instanzvariable neben FValue (z.B. vom Typ Single) wären nach wie vor wieder ein Getter und Setter fällig. Da liegt der Hund begraben!

Dazu schau dir mal mein Update an

Der schöne Günther 15. Mär 2013 14:55

AW: Properties, ihre Getter und Setter und Thread-Safety
 
Ich habe es bis gerade noch auf Biegen und Brechen (z.B. über generische Methoden als Property-Getter/Setter) versucht, aber er lässt mich noch nicht einmal eine Property vom Typ
Delphi-Quellcode:
Single
mit einem auf
Delphi-Quellcode:
TValue
typisierten Getter/Setter verkuppeln.

Bliebe nur der langsame Weg über RTTI oder indizierte Properties welcher meiner Meinung nach absolut hässlich sind. Wenn ich mal ohne die Properties direkt auf die Felder zugreifen möchte muss ich mir entweder mühsam einzelne Zahlen aus der Klassendeklaration buddeln oder hoffen, dass man hier mit Enumerationstypen die Indizes wenigstens etwas aufhübschen kann. Großer Gott... :pale:

Aber darauf wird es im Endeffekt wohl hinauslaufen, vielen Dank für die Hilfe!


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz