Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Lock/Unlock-Mechanismus ohne Bezug auf Multithreading? (https://www.delphipraxis.net/201482-lock-unlock-mechanismus-ohne-bezug-auf-multithreading.html)

Der schöne Günther 25. Jul 2019 12:24

Delphi-Version: 10 Seattle

Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Ich suche etwas wo man Zugriff auf eine geschützte Resource anfordern kann, und wenn man Zugriff bekommt danach die Sperre wieder frei machen muss.

Alles was ich finde (kritische Abschnitte, Semaphore, Monitor, …) liegt in System oder System.SyncObjs, bezieht sich aber auf Threads. Bei all diesen Implementationen meint er es gut einen Deadlock zu verhindern indem man problemlos sagen kann:

Delphi-Quellcode:
someMutex.Acquire();
someMutex.Acquire();
ShowMessage('Das hier sollte nie zu sehen sein');
Ich suche etwas wo ich sagen kann "TryLock" und er sagt mir "ja/nein". Und dass er mir bitte "Nein" sagt wenn ich im gleichen Thread schon einmal gelocked habe.

Gibt es da etwas in der Standard-Bibliothek? Ich finde nichts.

Uwe Raabe 25. Jul 2019 12:44

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Das ist jetzt vermutlich zu trivial:
Delphi-Quellcode:
type
  TLock = record
  private
    FLocked: Boolean;
    class function Create: TLock; static;
  public
    function TryLock: Boolean;
    procedure Unlock;
    property Locked: Boolean read FLocked;
  end;

class function TLock.Create: TLock;
begin
  Result.FLocked := False;
end;

function TLock.TryLock: Boolean;
begin
  Result := not FLocked;
  FLocked := True;
end;

procedure TLock.Unlock;
begin
  FLocked := False;
end;

Der schöne Günther 25. Jul 2019 12:56

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Ja schon ein bisschen 😉
Das ist ja im Endeffekt wie eine globale Boolean-Variable an die jeder dran darf. Ich hätte mir schon vorgestellt dass man es nur unlocken kann wenn man es selbst vorher gelocked hat.

Wenn es nichts gibt bastele ich mir etwas und frage nach Feedback sobald ich fertig bin. Auf die Schnelle kenne ich in den Bibliotheken anderer Sprachen auch nichts...

Neutral General 25. Jul 2019 13:01

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1437632)
Ich hätte mir schon vorgestellt dass man es nur unlocken kann wenn man es selbst vorher gelocked hat.

Wenn sich alles in einem Thread abspielt ist alles/jeder "man selbst". Wie definierst du dieses "selbst"?
Im Prinzip müsstest du dem Lock() einen (zufälligen?) Wert übergeben den nur die Methode die das Lock() aufgerufen hat lokal kennt und der dann quasi als eine Art "Password" für das Unlock() fungiert.

Also Uwe's Klasse erweitert:
Delphi-Quellcode:
type
  TLock = record
  private
    FLocked: Boolean;
    FPW: Integer;
    class function Create: TLock; static;
  public
    function TryLock(APW: Integer): Boolean;
    function Unlock(APW: Integer): Boolean;
    property Locked: Boolean read FLocked;
  end;

class function TLock.Create: TLock;
begin
  Result.FLocked := False;
end;

function TLock.TryLock(APW: Integer): Boolean;
begin
  Result := not FLocked;
  if (Result) then
  begin
    FLocked := True;
    FPW := APW;
  end;
end;

procedure TLock.Unlock(APW: Integer);
begin
  Result := APW = FPW;
  if Result then
    FLocked := False;
end;
Edit: Uwe's Erweiterung unten ist sogar noch einen Tick eleganter
V
V

Uwe Raabe 25. Jul 2019 13:12

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1437632)
dass man es nur unlocken kann wenn man es selbst vorher gelocked hat.

Wer ist denn selbst bzw. wie identifiziert sich dieses selbst? Man kann sich natürlich beim Lock auch einen Syhlüssel zum Unlock geben lassen:
Delphi-Quellcode:
  TLock = record
  private
    FLocked: TGUID;
    class function Create: TLock; static;
    function GetLocked: Boolean;
  public
    function TryLock(var Key: TGUID): Boolean;
    function Unlock(const Key: TGUID): Boolean;
    property Locked: Boolean read GetLocked;
  end;

class function TLock.Create: TLock;
begin
  Result.FLocked := TGUID.Empty;
end;

function TLock.GetLocked: Boolean;
begin
  Result := (FLocked <> TGUID.Empty);
end;

function TLock.Unlock(const Key: TGUID): Boolean;
begin
  Result := False;
  if Key = FLocked then begin
    FLocked := TGUID.Empty;
    Result := True;
  end;
end;

function TLock.TryLock(var Key: TGUID): Boolean;
begin
  Result := False;
  if not Locked then begin
    Key := TGUID.NewGuid;
    FLocked := Key;
    Result := True;
  end;
end;
Das scheint aber schon eine sehr spezielle Anforderung zu sein, die du da umsetzen willst.

Ich sehe gerade, da hat das schon jemand aufgegriffen. :thumb:

Der schöne Günther 25. Jul 2019 13:15

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Zitat:

Zitat von Neutral General (Beitrag 1437634)
Wenn sich alles in einem Thread abspielt

Das habe ich nicht gesagt. Multithreading-fähig muss das natürlich schon sein.

Zitat:

Zitat von Neutral General (Beitrag 1437634)
Im Prinzip müsstest du dem Lock() einen (zufälligen?) Wert übergeben den nur die Methode die das Lock() aufgerufen hat lokal kennt und der dann quasi als eine Art "Password" für das Unlock() fungiert.

Zitat:

Zitat von Uwe Raabe (Beitrag 1437637)
Man kann sich natürlich beim Lock auch einen Syhlüssel zum Unlock geben lassen

Richtig, nur dass ich keine GUID oder Integer nehmen würde sondern eine Interface-basierte Referenz die dafür sorgt dass spätestens dann Unlock() gemacht wird wenn man die Referenz wegwirft und man vergessen hat aufzuschließen.


Ich denke im Groben habe ich jetzt auch etwas, das Interface ist ungefähr so:

Delphi-Quellcode:
   ELockException = class(Exception);
   ELockNotHeldException = class(ELockException);

   ILock = interface
   ['{57CCCDE4-63F8-41F6-A6F0-39B4159B06FF}']
      /// <exception cref="ELockNotHeldException" />
      procedure UnLock();
   end;

   ILockableResource = interface
   ['{88085418-BD27-4B5D-AD00-B456C8E017A7}']
      function TryLock(
         out lock: ILock;
         const timeout: TTimeSpan
      ): Boolean; overload;
      function TryLock(out lock: ILock): Boolean; overload;
   end;

Uwe Raabe 25. Jul 2019 13:21

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1437619)
Ich suche etwas wo man Zugriff auf eine geschützte Resource anfordern kann, und wenn man Zugriff bekommt danach die Sperre wieder frei machen muss.

Zitat:

Zitat von Der schöne Günther (Beitrag 1437619)
Ich suche etwas wo ich sagen kann "TryLock" und er sagt mir "ja/nein". Und dass er mir bitte "Nein" sagt wenn ich im gleichen Thread schon einmal gelocked habe.

Zitat:

Zitat von Der schöne Günther (Beitrag 1437632)
Ich hätte mir schon vorgestellt dass man es nur unlocken kann wenn man es selbst vorher gelocked hat.

Zitat:

Zitat von Der schöne Günther (Beitrag 1437638)
Multithreading-fähig muss das natürlich schon sein.

Zitat:

Zitat von Der schöne Günther (Beitrag 1437638)
die dafür sorgt dass spätestens dann Unlock() gemacht wird wenn man die Referenz wegwirft und man vergessen hat aufzuschließen.

Deine Spezifikationen vermehren sich mit jedem Post :-D

Der schöne Günther 25. Jul 2019 13:33

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Stimmt :oops:

Ich glaube es ist Zeit für eine Pause 🏖 🍧

einbeliebigername 25. Jul 2019 13:58

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Hallo,

bevor du was selbst programmierst, erkläre noch mal an einem Beispile was du brauchst. Denn wenn du in einem Thread
Delphi-Quellcode:
  x.Acquire;
  try
    x.Acquire;
    try
      Do;
    finally
      x.Release;
    end;
  finally
    x.Release;
  end;
hast, kann er doch nur entweder das
Delphi-Quellcode:
Do
ausführen oder den Thread für immer blockieren.

Es gibt bei einigen noch ein
Delphi-Quellcode:
function TryEnter: Boolean
. Vieleicht hilft das.

Uwe Raabe 25. Jul 2019 15:05

AW: Lock/Unlock-Mechanismus ohne Bezug auf Multithreading?
 
Zitat:

Zitat von einbeliebigername (Beitrag 1437643)
Es gibt bei einigen noch ein
Delphi-Quellcode:
function TryEnter: Boolean
. Vieleicht hilft das.

Das TryEnter läuft aber positiv durch, wenn es mehrfach im selben Thread aufgerufen wird. Das widerspricht einer Anforderung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:54 Uhr.
Seite 1 von 2  1 2      

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