⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtcsyncobjs.pas

📁 Delphi快速开发Web Server
💻 PAS
字号:
{
  "SyncObjcs" - Copyright (c) Danijel Tkalcec
  @exclude
}
unit rtcSyncObjs;

interface

{$INCLUDE rtcDefs.inc}

uses
{$IFDEF CLR}
  System.Threading;
{$ELSE}
  SyncObjs,
  Windows;
{$ENDIF}

type
  TRtcWaitResult = (wr_Signaled, wr_Timeout, wr_Abandoned, wr_Error);

  TRtcCritSec=class
  private
    {$IFDEF CLR}
    CS:System.Threading.Mutex;
    {$ELSE}
    CS:TRTLCriticalSection;
    {$ENDIF}
  public
    constructor Create; virtual;
    destructor Destroy; override;

    procedure Enter;
    procedure Leave;
    end;

  TRtcRWSec=class
  private
    WriteSec:TEvent;
    {$IFDEF CLR}
    PassSec,ReadSec:System.Threading.Mutex;
    {$ELSE}
    PassSec,ReadSec:TRTLCriticalSection;
    {$ENDIF}
    Cnt,Cnt3:longint;
  public
    constructor Create;
    destructor Destroy; override;

    procedure EnterRead;  // Normal reader, no hurry.
    procedure LeaveRead;

    procedure ForceWrite;  // Need to write as fast as possible, force readers to stop reading.
    procedure EnterWrite;  // Normal writer, no hurry.
    procedure LeaveWrite;

    procedure ForceRead;  // Need to read as fast as possible, ignore waiting writers.
    procedure DoneRead;  // Done reading.
  end;

  TRtcEvent=class
  private
    CS:TEvent;
  public
    constructor Create(ManualReset,InitialState:boolean);
    destructor Destroy; override;

    function WaitFor(Timeout: LongWord): TRtcWaitResult;
    procedure SetEvent;
    procedure ResetEvent;
    end;

implementation

{ TRtcCritSec }

constructor TRtcCritSec.Create;
  begin
  inherited;
  {$IFDEF CLR}
  CS:=System.Threading.Mutex.Create;
  {$ELSE}
  InitializeCriticalSection(CS);
  {$ENDIF}
  end;

destructor TRtcCritSec.Destroy;
  begin
  {$IFDEF CLR}
  CS.Free;
  {$ELSE}
  DeleteCriticalSection(CS);
  {$ENDIF}
  inherited;
  end;

procedure TRtcCritSec.Enter;
  begin
  {$IFDEF CLR}
  CS.WaitOne;
  {$ELSE}
  EnterCriticalSection(CS);
  {$ENDIF}
  end;

procedure TRtcCritSec.Leave;
  begin
  {$IFDEF CLR}
  CS.ReleaseMutex;
  {$ELSE}
  LeaveCriticalSection(CS);
  {$ENDIF}
  end;

{ TRtcEvent }

constructor TRtcEvent.Create(ManualReset, InitialState: boolean);
  begin
  inherited Create;
  CS:=TEvent.Create(nil,ManualReset,InitialState,'');
  end;

destructor TRtcEvent.Destroy;
  begin
  CS.Free;
  inherited;
  end;

procedure TRtcEvent.ResetEvent;
  begin
  CS.ResetEvent;
  end;

procedure TRtcEvent.SetEvent;
  begin
  CS.SetEvent;
  end;

function TRtcEvent.WaitFor(Timeout: LongWord): TRtcWaitResult;
  begin
  case CS.WaitFor(Timeout) of
    wrSignaled: Result:=wr_Signaled;
    wrTimeout:  Result:=wr_Timeout;
    wrAbandoned:Result:=wr_Abandoned;
    else        Result:=wr_Error;
    end;
  end;

{ TRtcRWSec }

constructor TRtcRWSec.Create;
  begin
  inherited;
  Cnt:=0;Cnt3:=0;
  {$IFDEF CLR}
  PassSec:=System.Threading.Mutex.Create;
  ReadSec:=System.Threading.Mutex.Create;
  {$ELSE}
  InitializeCriticalSection(PassSec);
  InitializeCriticalSection(ReadSec);
  {$ENDIF}
  WriteSec:=TEvent.Create(nil,False,True,'');  // Auto-reset
  end;

destructor TRtcRWSec.Destroy;
  begin
  {$IFDEF CLR}
  PassSec.Free;
  ReadSec.Free;
  {$ELSE}
  DeleteCriticalSection(PassSec);
  DeleteCriticalSection(ReadSec);
  {$ENDIF}
  WriteSec.Free;
  inherited;
  end;

procedure TRtcRWSec.EnterRead;
  begin
  {$IFDEF CLR}
  PassSec.WaitOne;
  PassSec.ReleaseMutex;
  {$ELSE}
  EnterCriticalSection(PassSec);
  LeaveCriticalSection(PassSec);
  {$ENDIF}

  {$IFDEF CLR}
  ReadSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(ReadSec);
  {$ENDIF}
  try
    if (Cnt=0) and (Cnt3=0) then // There are no readers inside
      WriteSec.WaitFor(INFINITE);  // Block all writers, this is the first reader.
    Inc(Cnt);
  finally
    {$IFDEF CLR}
    ReadSec.ReleaseMutex;
    {$ELSE}
    LeaveCriticalSection(ReadSec);
    {$ENDIF}
    end;
  end;

procedure TRtcRWSec.ForceRead;
  var
    OK:boolean;
  begin
  OK:=False;
  {$IFDEF CLR}
  ReadSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(ReadSec);
  {$ENDIF}
  try
    if Cnt>0 then // There are normal readers inside, writers are blocked.
      begin
      Inc(Cnt3);
      OK:=True;
      end;
  finally
    {$IFDEF CLR}
    ReadSec.ReleaseMutex;
    {$ELSE}
    LeaveCriticalSection(ReadSec);
    {$ENDIF}
    end;

  if not OK then
    begin
    {$IFDEF CLR}
    PassSec.WaitOne;
    PassSec.ReleaseMutex;
    {$ELSE}
    EnterCriticalSection(PassSec);
    LeaveCriticalSection(PassSec);
    {$ENDIF}

    {$IFDEF CLR}
    ReadSec.WaitOne;
    {$ELSE}
    EnterCriticalSection(ReadSec);
    {$ENDIF}
    try
      if (Cnt=0) and (Cnt3=0) then // There are no readers inside
        WriteSec.WaitFor(INFINITE);  // Block all writers
      Inc(Cnt3);
    finally
      {$IFDEF CLR}
      ReadSec.ReleaseMutex;
      {$ELSE}
      LeaveCriticalSection(ReadSec);
      {$ENDIF}
      end;
    end;
  end;

procedure TRtcRWSec.LeaveRead;
  begin
  {$IFDEF CLR}
  ReadSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(ReadSec);
  {$ENDIF}
  try
    Dec(Cnt);
    if (Cnt=0) and (Cnt3=0) then
      WriteSec.SetEvent;  // Un-block writers
  finally
    {$IFDEF CLR}
    ReadSec.ReleaseMutex;
    {$ELSE}
    LeaveCriticalSection(ReadSec);
    {$ENDIF}
    end;
  end;

procedure TRtcRWSec.DoneRead;
  begin
  {$IFDEF CLR}
  ReadSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(ReadSec);
  {$ENDIF}
  try
    Dec(Cnt3);
    if (Cnt=0) and (Cnt3=0) then
      WriteSec.SetEvent;  // Un-block writers
  finally
    {$IFDEF CLR}
    ReadSec.ReleaseMutex;
    {$ELSE}
    LeaveCriticalSection(ReadSec);
    {$ENDIF}
    end;
  end;

procedure TRtcRWSec.EnterWrite;
  begin
  {$IFDEF CLR}
  PassSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(PassSec);
  {$ENDIF}

  WriteSec.WaitFor(INFINITE);
  end;

procedure TRtcRWSec.ForceWrite;
  begin
  {$IFDEF CLR}
  PassSec.WaitOne;
  {$ELSE}
  EnterCriticalSection(PassSec);
  {$ENDIF}

  WriteSec.WaitFor(INFINITE);
  end;

procedure TRtcRWSec.LeaveWrite;
  begin
  WriteSec.SetEvent;

  {$IFDEF CLR}
  PassSec.ReleaseMutex;
  {$ELSE}
  LeaveCriticalSection(PassSec);
  {$ENDIF}
  end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -