Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Critical Sections (https://www.delphipraxis.net/106212-critical-sections.html)

Sämy 7. Jan 2008 13:50


Critical Sections
 
Ich hab nur ne kurze Frage:

Wieso endet dies in einer Endlosschleife:

Delphi-Quellcode:

FCs := TCriticalSection.Create;

procedure test;
begin
  FCs.Enter;
  test;
  FCS.Leave;
end;
Meiner Meinung nach sollte dies ein Dead-Lock ergeben. Oder habe ich da was falsch verstanden?

Muetze1 7. Jan 2008 13:54

Re: Critical Sections
 
1. Endlosschleife: weil du dich immer wieder selber aufrufst
2. kein dead lock, da es die selber Critical Section ist. So oft wie du sie betrittst musst du sie auch wieder verlassen. Es ist keine neue critical section sondern die gleiche...

Sämy 7. Jan 2008 13:57

Re: Critical Sections
 
Ok, dann blockiert eine Criticalsection also nur andere Prozesse, während dessen der, der die Criticalsection als erstes betritt, diese noch weitere Male betreten kann?

Dh. der folgende Code ist Threadsafe?

Delphi-Quellcode:

destructor Destroy;
begin
  FCs.Enter;

  if FDestroying then
    Exit;

  FDestroying := true;
 
  [...] (<-- Hier drin wird diese Destroymethode abermals aufgerufen)

  inherited;

  FCS.Leave;
end;

Muetze1 7. Jan 2008 14:40

Re: Critical Sections
 
Zitat:

Zitat von Sämy
Ok, dann blockiert eine Criticalsection also nur andere Prozesse, während dessen der, der die Criticalsection als erstes betritt, diese noch weitere Male betreten kann?

Es geht nicht um den Aufrufer sondern um die Critical Section. Lege jedesmal in deinem ersten Beispiel eine neue Instanz an und du bekommst den Dead Lock.

Ich kapiere grundsätzlich nicht, warum man einen Destruktor mehrfach aufrufen sollte. Der Destruktor ist genauso wieder Konstruktor eine spezielle Methode und von daher solltest du deine Critical Sections und Sicherheiten nicht im Destruktor bauen sondern ausserhalb in einer Methode und dann entsprechend der Bedingungen einmalig den Destruktor aufrufen.

Du kannst mit einem Exit einen aufgerufenen Destruktor schlecht rückgängig machen bzw. abbrechen. Das ist in so fern schon eine schlechte Wahl der Programmierung. Bau dir eine Methode (nenne sie z.B. FreeInstance) und baua dort deine Critical Sections und wenn die Instanz dann wirklich weg kann/soll, dann rufe dort den Destruktor auf.

SirThornberry 7. Jan 2008 14:52

Re: Critical Sections
 
eine CriticalSection sorgt dafür das ein THREAD am CriticalSection.Enter so lange wartet bis kein anderer Thread mehr in der CriticalSection ist (andere Threads also mit CriticalSection.Leave die CriticalSection verlassen haben)

Sämy 7. Jan 2008 15:28

Re: Critical Sections
 
Delphi-Quellcode:

So: ?

procedure test;
begin
  FCs := TCriticalSection.Create;
  FCs.Enter;
  test;
  FCS.Leave;
end;
[/delphi]
Dies Funktioniert nicht (kein Deadlock)

Das mit dem Doppel-destroy seh ich ein. Gibt Probleme, wenn jemand diese Methode überschreiben will...

Muetze1 7. Jan 2008 15:44

Re: Critical Sections
 
Zitat:

Zitat von Sämy
Dies Funktioniert nicht (kein Deadlock)

Ja, da habe ich Müll erzählt - wie SirThornberry schon richtig erwähnte, orientiert sich die Critical Section an dem aktuellen Thread anstatt der Instanz.

SirThornberry 7. Jan 2008 15:48

Re: Critical Sections
 
ergibt das aber nicht eine Endloserekursion bis hinn zum Stacküberlauf wenn Test immer wieder sich selbst aufruft? :shock:

Sämy 7. Jan 2008 16:25

Re: Critical Sections
 
Dies war auch nur ein Test-Case. Ich dachte, dass eine Critical-Section absolut gesperrt wird. Sprich wenn sich die Funktion selbst aufruft, sollte ein Deadlock resultieren und keine Endlosschleife. (Meine Frage war, wieso dies nicht funtioniert)

Noch mals zu meinem Handling in der Destroy-Methode. Wie soll ich dies lösen?

Szenario:
Eine Objekt registriert sich in einer Liste.
Wenn es zerstört wird, so trägt es sich wieder aus der Liste aus.
Es werden jedoch alle Objekte in der Liste, wenn sie sich austragen, gelöscht. (-> Erneutes Aufrufen der Destroy-Methode)
Jetzt müsste ich, wenn ich das Handling des Zerstörens an einem anderen Ort als in der Destroy-Methode machen würde, von jedem Objekt, welches sich in der Liste registriert, eine bestimmte Funktion voraussetzen. Das will ich jedoch nicht.

noidic 7. Jan 2008 16:31

Re: Critical Sections
 
Sind all diese Objekte in einer Liste? Dann nimm das entfernen aus der Liste aus dem Destructor heraus und rufe nie destroy auf, sondern gehe immer den Weg über das entfernen aus der Liste.

Sämy 7. Jan 2008 16:43

Re: Critical Sections
 
Manchmal sieht man den Wald vor lauter Bäumen nicht... ;)

Funktioniert für mich so.

Besten Dank allen!

Muetze1 7. Jan 2008 17:40

Re: Critical Sections
 
Wenn es um eine TObjectList geht, dann in den Elementen einfach ein
Delphi-Quellcode:
fList.Extract(self);
in den Destruktor schreiben. Die TObjectList kommt damit ohne Probleme klar, da sie erst das Element aus der Liste rausholt und entfernt und dann erst freigibt. Dadurch läuft beim freigeben der ObjectList die Extract Methode ins Leere. Klappt somit einwandfrei...

Sämy 7. Jan 2008 17:55

Re: Critical Sections
 
hmmm... Funktioniert dies wirklich?

Wenn dies in der Destroy-Methode aufgerufen wird, so entfernt die Liste das Objekt und gibt es danach frei. Dann wird mein Destruktor doch auch 2 Mal aufgerufen. Nicht? Falsch verstanden?

Muetze1 7. Jan 2008 18:08

Re: Critical Sections
 
Zitat:

Zitat von Sämy
hmmm... Funktioniert dies wirklich?

Definitiv - tausendfach eingesetzt.

Zitat:

Zitat von Sämy
Nicht? Falsch verstanden?

Jupp. Delphi-Referenz durchsuchenExtract() <> Delphi-Referenz durchsuchenRemove() bzw. Delphi-Referenz durchsuchenDelete()


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 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