Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Implementierung TSingleton für thread-safety (z.B. Spring4D) (https://www.delphipraxis.net/203952-implementierung-tsingleton-fuer-thread-safety-z-b-spring4d.html)

Rollo62 9. Apr 2020 12:20

Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Hallo zusammen,

ich beschäftige mich gerade mit Singletons, und es wird üblicherweise das Erzeugen mit CS abgesichert,
so wie hier in Spring4D

Delphi-Quellcode:
class function TSingleton.GetInstance<T>: T;
begin
  if not Assigned(TSingleton<T>.fInstance) then
  begin
    fCriticalSection.Enter;
    try
      if not Assigned(TSingleton<T>.fInstance) then
        TSingleton<T>.fInstance := T.Create;
    finally
      fCriticalSection.Leave;
    end;
  end;
  Result := TSingleton<T>.fInstance;
end;
Die eigentliche zu kapselnde Klasse <T> muss aber auch threadsicher sein, wenn da mehrere Threads global drauf zugreifen können.

Ich frage mich ob man dafür in einfachen Fällen nicht die bereits bestehende Instanz von fCriticalSection nehmen könnte / sollte.

So sparte man zumindest unnötige CS-Ressourcen in der zu kapselnden Klasse ein.
Das entspräche womöglich nicht einer optimalen Trennung der "Concerns", aber
könnte doch die Ressourcen und Performance optimieren.

Die zu kapselnde Klasse könnte für den Fall von einer speziellen Klasse abgeleitet sein,
z.B. type T = class; für alle nicht sicheren Fälle wie bisher, type T = class(TSingletonThreadsafe);

Abhängig von dem Type der Klasse könnte dann die CS im Create( FCriticalSection ); übergeben werden.

Oder spricht etwas Grundsätzliches dagegen, und es gäbe es sinnvollere Möglichkeiten
das Konstrukt threadsafe zu machen ?

Mavarik 10. Apr 2020 12:55

AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Vielleicht verstehe ich Deine Frage nicht richtig, aber
Die Klasse die Erzeugt wir muss nicht threadsicher sein, sondern nur die Create Methode Reentrant.

Also "nur" erzeugen und initialisieren und nix weiter im Create machen.

Dann nutze ich
Delphi-Quellcode:
TInterlocked.CompareExchange<T>
um die neue Instance der eigentlichen zuzuweisen.

So mache ich es jedenfalls in allen Threads des FDK. Hatte hiermit noch nie ein Problem.

Grüsse und schönes Ostern

Mavarik :coder:

himitsu 10. Apr 2020 13:07

AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Früher gab es MSDN-Library durchsuchenInterlockedCompareExchange bzw. MSDN-Library durchsuchenInterlockedCompareExchangePtr,
das kapselte Delphi dann mal als Delphi-Referenz durchsuchenTInterlocked,
aber man darf auch gern das neuere multi-platforme Delphi-Referenz durchsuchenAtomicCmpExchange der System-Unit verwenden, mit bissl compilermagic bei der Typenbehandlung

Jo, schauen ob leer,
wenn ja, dann erstellen,
die Referenz threadsicher eintragen/austauschen, was mit einer atomaren Operation am Einfachsten geht (Interlocked, Atomic oder LOCK im Assembler)
und wenn nicht erfolgreich, dann die Instanz wieder freigeben. (falls ein anderer Thread das gleichzeitig gemacht hatte und schneller war)

Delphi-Quellcode:
if not Assigned(XXX) then begin
  NEW := TIrgendwas.Create;
  if AtomicCmpExchange(XXX, NEW, nil) <> nil then
    NEW.Free;
end;
XXX.DoSomething;

Rollo62 12. Apr 2020 18:58

AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Ja genau, für das eigentliche Erzeugen der Instanz gibt es diese Methoden.
Was ich meine ist aber, das die erzeugte Klasse im Singleton auch ThreadSicher sein muss.
Je nachdem hat diese ja noch globale Felder zu verwalten.
TSingleton<TKlasse>

Um diese abzusichern könnte man doch das globale CS des TSingletons wieder-verwenden,
und an die erzeugte Instanz im Create der TKlasse übergeben.
Macht das Sinn, oder sollte TSingleton und TKlasse jeweils ihr eigenes CS haben und verwalten ?

Ich weiss das man generell besser die Klassen trennen sollte,
Aber in diesem Fall macht TKlasse ja nur im TSingleton Sinn.
Also könnten hier Ressorcen optimiert werden, weil TKlasse nie allein verwendet wird.

TiGü 12. Apr 2020 20:08

AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Zitat:

Zitat von Rollo62 (Beitrag 1461871)
Um diese abzusichern könnte man doch das globale CS des TSingletons wieder-verwenden,
und an die erzeugte Instanz im Create der TKlasse übergeben.

Warum, wo siehst du hiervon den Mehrwert?
Ob ich ein ode zwei Mutexe, Kritische Abschnitte oder Monitore benutze ist doch nun wirklich zu vernachlässigen.

Rollo62 14. Apr 2020 07:52

AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
 
Der Mehrwert wäre das die TKlasse eine CS per DI übergeben bekäme, und sich nicht selber drum kümmern muss.
Allerdings ist TKlasse ja selber ein Singleton, insofern hast du Recht.
Deshalb frage ich mich was hier wohl der bessere Weg wäre.


Alle Zeitangaben in WEZ +2. Es ist jetzt 16:25 Uhr.

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