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

📄 xpwinsync.pas

📁 类似于Java JUnit的单元测试
💻 PAS
📖 第 1 页 / 共 3 页
字号:
unit XPWinSync;

{
 $Source: /cvsroot/dunit/dunit/Contrib/DUnitWizard/Source/Common/XPWinSync.pas,v $
 $Revision: 1.1 $
 $Date: 2004/05/03 15:07:15 $
 Last amended by $Author: pvspain $
 $State: Exp $

 XPWinSync:
 Interfaces and implementing classes which wrap Windows
 synchronisation mechanisms:
 Events (AutoReset and Manual)
 Mutexes
 Semaphores
 CriticalSections
 SharedCounters
 RWSynchronisers

 Copyright (c) 2001 by The Excellent Programming Company Pty Ltd
 (Australia) (ABN 27 005 394 918).

 Contact Paul Spain via email: paul@xpro.com.au

 This unit is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This unit is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this unit; if not, the license can be viewed at:
 http://www.gnu.org/copyleft/lesser.html
 or write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 Boston, MA  02111-1307  USA
 }

interface

uses
  XPWinBase,
  XPRestore,            // IXPRestore, TXPRestore
  XPSyncRW,             // IXPSyncRW
  Windows,              // THandle,  CreateXXX(), OpenXXX
  SysUtils;             // Exception, Trim(), FmtStr(), AnsiPos(),
                        // AnsiLowerCase()

type

{$IFDEF XPW32E}
  EXPWin32Event = class (EXPWin32) end;

  EXPWin32Synchro = class (EXPWin32) end;
    EXPWin32Mutex = class (EXPWin32Synchro) end;
    EXPWin32Semaphore = class (EXPWin32Synchro) end;

  EXPWin32SharedCounter = class (EXPWin32) end;
  EXPWin32SerialAccess = class (EXPWin32) end;
{$ENDIF}

//////////////////////////////////////////////////////////////////////////////
///   IXPWinXXXEvent
//////////////////////////////////////////////////////////////////////////////

  IXPWinEvent = interface(IXPWinNamedKernelObject)
    ['{832555D0-0C82-11D5-A261-00608CF441D9}']
    // Behaviour of Signal is the prime difference between Auto and Manual
    // events. For Auto events, Signal will signal (only) the first waiting
    // thread and reset itself. For Manual events, Signal will stay signalled
    // until Reset is called
    procedure Signal;
    end;

  IXPWinAutoEvent = interface(IXPWinEvent)
    ['{7F4EBC21-16E6-11D5-A271-00608CF441D9}']
    end;

  IXPWinManualEvent = interface(IXPWinEvent)
    ['{88C4F111-1500-11D5-A26D-00608CF441D9}']
    procedure Reset;
    // Pulse behaves like Signal for an Auto event, except that it signals
    // _all_ waiting threads (not just the first thread) before resetting
    // itself.
    procedure Pulse;
    end;

//////////////////////////////////////////////////////////////////////////////
///   IXPSynchro: Mutexes, semaphores and critical sections
//////////////////////////////////////////////////////////////////////////////

  IXPWinSynchro = interface(IXPWinError)
    ['{7F4EBC22-16E6-11D5-A271-00608CF441D9}']
    function Enter: boolean;
    function Leave: boolean;
    end;

  TXPWinSerialAccess = class(TXPWinError, IXPRestore)
    private

    FSync: IXPWinSynchro;

    public

    constructor Create(const ASync: IXPWinSynchro);
    destructor Destroy; override;
    end;

//////////////////////////////////////////////////////////////////////////////
///   IXPWinMutex
//////////////////////////////////////////////////////////////////////////////

  IXPWinMutex = interface(IXPWinNamedKernelObject)
    ['{BC7BDA82-4151-11D5-A2C1-00608CF441D9}']
    end;

//////////////////////////////////////////////////////////////////////////////
///   IXPWinXXXSemaphore
//////////////////////////////////////////////////////////////////////////////

  IXPWinSemaphore = interface(IXPWinNamedKernelObject)
    ['{F65C8F71-1700-11D5-A271-00608CF441D9}']
    // Count is number of free entries, not occupied entries
    //
    // There are some caveats on usage of GetCount, as Windows does
    // not provide the facility to retrieve the current count value. The
    // previous Count value can be retrieved via successful calls to
    // Windows.ReleaseSemaphore()
    // Caveats:
    // GetCount is always accurate for a single-handle semaphore kernel object
    // ie a semaphore which has (only) been created, not opened (see
    // IXPWinNamedKernelObject.Instance) and which has been manipulated only
    // by the interface methods, not via Windows API calls on the handle.
    // If the semaphore has more than one handle opened, the count value is only
    // guaranteed correct immediately following IXPSynchro.Leave and
    // IXPWinSemaphore.Release calls.
    // Note that this and the following interface are thread-safe, so the
    // interfaces can be passed among threads rather than creating new handles
    // via calls to GetSemaphore().
    function GetCount: integer;
    function Acquire: boolean;
    procedure Release;
    property Count: integer read GetCount;
    end;

  // This interface can be used when the semaphore has been created rather than
  // opened, ie when Instance = koCreated (IXPWinNamedKernelObject.Instance)
  IXPWinCreatedSemaphore = interface(IXPWinSemaphore)
    ['{64F2B390-26F8-11D5-8CAD-0080ADB62643}']
    function GetCapacity: integer;
    // Use Open as the first call on a new interface which has been created via
    // GetSemaphore() with the CreateOpen parameter as false. This scenario is
    // useful to initialize resources upon creation, before releasing them for
    // use.
    function Open: boolean;
    property Capacity: integer read GetCapacity;
    end;

//////////////////////////////////////////////////////////////////////////////
///   IXPSharedCounter
//////////////////////////////////////////////////////////////////////////////

const
  XPCounterError = System.Low(integer);

type

  IXPSharedCounter = interface
    ['{BC7BDA81-4151-11D5-A2C1-00608CF441D9}']
    function GetValue: integer;
    procedure SetValue(const Value: integer);
    function Inc(const Delta: integer = 1): integer;
    function Dec(const Delta: integer = 1): integer;

    property Value: integer read GetValue write SetValue;
    end;

//////////////////////////////////////////////////////////////////////////////
///   Creator functions: unit entry points
//////////////////////////////////////////////////////////////////////////////

function GetAutoEvent(const CreateAsSignaled: boolean = false;
  const AName: string = '';
  const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPWinAutoEvent;

function GetManualEvent(const CreateAsSignaled: boolean = false;
  const AName: string = '';
  const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPWinManualEvent;

{ Mutexes and Semaphores must be instantiated  at a scope which is *local* to
  each interested thread. The common Name value ensures we are connecting
  with the same kernel object. }

function GetMutex(const AName: string = ''; const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPWinMutex;

function GetSemaphore(const Capacity: integer; const AName: string = '';
  const CreateOpen: boolean = true; const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPWinSemaphore;

{ Critical sections must be instantiated at a scope which is common to all
  interested threads, ie at process *global* scope. }

function CreateCriticalSection: IXPWinSynchro;

function GetSharedCounter(const InitialValue: integer = 0;
  const AName: string = ''; const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPSharedCounter;

{ CreateThreadIXPSyncRW creates an interface for intra-process thread
 synchronisation. }
function CreateThreadRWSynchroniser(
  const SyncPriority: TXPSyncPriority = spReaders): IXPSyncRW;

{ CreateProcessIXPSyncRW creates an interface for inter-process thread
 synchronisation. }
function GetProcessRWSynchroniser(const Name: string = '';
  const SyncPriority: TXPSyncPriority = spReaders;
  const Inheritable: boolean = true;
  const SecurityDescriptor: Pointer = nil): IXPSyncRW;

implementation

const CVSID: string = '$Header: /cvsroot/dunit/dunit/Contrib/DUnitWizard/Source/Common/XPWinSync.pas,v 1.1 2004/05/03 15:07:15 pvspain Exp $';

///////////////////////////////////////////////////////////////////////////////
///     TXPSerialAccess implementation
///////////////////////////////////////////////////////////////////////////////

constructor TXPWinSerialAccess.Create(const ASync: IXPWinSynchro);
  begin
{$IFDEF XPW32E}
  inherited Create(EXPWin32SerialAccess);
{$ELSE}
  inherited Create;
{$ENDIF}
  FSync := ASync;

  if not FSync.Enter then
    Error('TXPSerialAccess.Create');

  end;

destructor TXPWinSerialAccess.Destroy;
  begin

  if not FSync.Leave then
    Error('TXPSerialAccess.Destroy');

  inherited;
  end;

///////////////////////////////////////////////////////////////////////////////
///     IXPWinXXXEvent implementation
///////////////////////////////////////////////////////////////////////////////

type

  TXPWinEvent = class(TXPWinNamedKernelObject, IXPWinEvent)
    private

    //
    // IXPWinEvent implementation
    //

    procedure Signal;

    public

    constructor Create(const AName: string; const CreateAsSignaled: boolean;
      const ManualReset: boolean; const Inheritable: boolean;
      const SecurityDescriptor: Pointer);
    end;

  TXPWinAutoEvent = class(TXPWinEvent, IXPWinAutoEvent)
    public

    constructor Create(const AName: string; const CreateAsSignaled: boolean;
      const Inheritable: boolean; const SecurityDescriptor: Pointer);
    end;

  TXPWinManualEvent = class(TXPWinEvent, IXPWinManualEvent)
    private

    //
    // IXPWinManualEvent implementation
    //

    procedure Reset;
    procedure Pulse;

    public

    constructor Create(const AName: string;  const CreateAsSignaled: boolean;
      const Inheritable: boolean; const SecurityDescriptor: Pointer);
    end;

constructor TXPWinEvent.Create(const AName: string;
  const CreateAsSignaled: boolean; const ManualReset: boolean;
  const Inheritable: boolean; const SecurityDescriptor: Pointer);
  begin
  inherited Create(AName, Inheritable, SecurityDescriptor);
{$IFDEF XPW32E}
  SetException(EXPWin32Event);
{$ENDIF}
  FHandle := Windows.CreateEvent(@FSecurityAttributes, ManualReset,
    CreateAsSignaled, PChar(GetName));

  if FHandle = 0 then
    Error('TXPWinEvent.Create: Windows.CreateEvent failure')
  else if Windows.GetLastError = 0 then
    FInstance := koCreated
  else if Windows.GetLastError = ERROR_ALREADY_EXISTS then
    FInstance := koOpened;

  end;

procedure TXPWinEvent.Signal;
  begin
  Windows.SetEvent(FHandle);
  end;

{ TXPWinAutoEvent }

constructor TXPWinAutoEvent.Create(const AName: string;
  const CreateAsSignaled: boolean; const Inheritable: boolean;
  const SecurityDescriptor: Pointer);
  const
  ManualReset = false;

  begin
  inherited Create(AName, CreateAsSignaled, ManualReset, Inheritable,
    SecurityDescriptor);
  end;

{ TXPWinManualEvent }

constructor TXPWinManualEvent.Create(const AName: string;
  const CreateAsSignaled: boolean; const Inheritable: boolean;
  const SecurityDescriptor: Pointer);
  const
  ManualReset = true;

  begin
  inherited Create(AName, CreateAsSignaled, ManualReset, Inheritable,
    SecurityDescriptor);
  end;

procedure TXPWinManualEvent.Pulse;
  begin
  Windows.PulseEvent(GetHandle);
  end;

procedure TXPWinManualEvent.Reset;
  begin
  Windows.ResetEvent(GetHandle);
  end;

//////////////////////////////////////////////////////////////////////////////
///   TXPWinMutex implementation
//////////////////////////////////////////////////////////////////////////////

type

  TXPWinMutex = class(TXPWinNamedKernelObject, IXPWinMutex, IXPWinSynchro)
    private

    //
    // IXPSynchro implementation
    //

    function Enter: boolean;
    function Leave: boolean;

    public

    constructor Create(const AName: string; const Inheritable: boolean;
      const SecurityDescriptor: Pointer);
    end;

constructor TXPWinMutex.Create(const AName: string; const Inheritable: boolean;
  const SecurityDescriptor: Pointer);
  const
  EnterOnCreate = false;

  begin
  inherited Create(AName, Inheritable, SecurityDescriptor);
{$IFDEF XPW32E}
  SetException(EXPWin32Mutex);
{$ENDIF}
  FHandle := Windows.CreateMutex(@FSecurityAttributes, EnterOnCreate,
    PChar(GetName));

  if FHandle = 0 then
    Error('TXPWinMutex.Create: Windows.CreateMutex failure')
  else if Windows.GetLastError = 0 then
    FInstance := koCreated
  else if Windows.GetLastError = ERROR_ALREADY_EXISTS then
    FInstance := koOpened;

  end;

function TXPWinMutex.Enter: boolean;
  begin
  Result := Wait;

  if not Result then
    SetLastContext('TXPWinMutex.Enter: ' + GetLastContext);

  end;

function TXPWinMutex.Leave: boolean;
  begin
  Result := Windows.ReleaseMutex(FHandle);

  if not Result then
    Error('TXPWinMutex.Leave: Windows.ReleaseMutex failure');

  end;

//////////////////////////////////////////////////////////////////////////////
///   TXPWinSemaphore implementation

⌨️ 快捷键说明

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