Двойная проверка блокировки Delphi Singleton - PullRequest
0 голосов
/ 08 января 2019

Я хочу реализовать одноэлементную критическую секцию для защиты некоторого кода в нескольких классах (не спрашивайте дальше ...). Я видел Delphi Singleton Pattern и Aquire Singleton class Instance Multithread , но они используют глобальную функцию для возврата синглтона, и я этого не хочу. Итак, я реализовал свою собственную версию:

unit SynchronizationHandler;

interface

uses
  SyncObjs;

type
  TSynchronizationHandler = class
  strict private
    FCriticalSection: TCriticalSection;
  private
    class var FSingletonCriticalSection: TCriticalSection;
    class var FInstance: TSynchronizationHandler;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Lock;
    procedure Release;
    class function Instance: TSynchronizationHandler;
  end;

implementation

{ TSynchronizationHandler }

constructor TSynchronizationHandler.Create;
begin
  FCriticalSection := TCriticalSection.Create;
end;

destructor TSynchronizationHandler.Destroy;
begin
  FCriticalSection.Destroy;
end;

{Doublec check locking for this singletone}
class function TSynchronizationHandler.Instance: TSynchronizationHandler;
begin
  if not Assigned(FInstance) then
   begin
    FSingletonCriticalSection.Acquire;
    try
      if not Assigned(FInstance) then
        FInstance := TSynchronizationHandler.Create;
    finally
      FSingletonCriticalSection.Release;
    end;
  end;

  Result := FInstance;
end;

procedure TSynchronizationHandler.Lock;
begin
  FCriticalSection.Acquire;
end;

procedure TSynchronizationHandler.Release;
begin
  FCriticalSection.Release;
end;

initialization
  TSynchronizationHandler.FSingletonCriticalSection := TCriticalSection.Create;

finalization
  if Assigned(TSynchronizationHandler.FInstance) then
    TSynchronizationHandler.Instance.Free;

  TSynchronizationHandler.FSingletonCriticalSection.Free;

end.

Это работает, но мне не нравится часть инициализации \ финализации. Есть ли другой способ сделать это без использования глобальных переменных, функций?

1 Ответ

0 голосов
/ 08 января 2019

Если вы хотите инкапсулировать весь необходимый код в пространство имен класса, вы можете заменить секции initialization и finalization на конструктор класса и деструктор класса соответственно. Они будут вызываться неявно из процедур initialization и finalization.

...