Delphi 高效读写锁

Delphi 高效读写锁,第1张

概述本人设计了一个高效读写锁,可实现多个线程读一个线程写的锁,应该比Delphi自带的读写锁高效,本人没有做对比测试。 本文的锁不可以在一个线程里重入,否则会锁死,另外读写锁最多支持65535个线程同时读。 // [email protected]// 跨平台简易高效锁 unit utLocker; interface type // 多读单写锁 // 1.写的时候阻塞其他所有写

本人设计了一个高效读写锁,可实现多个线程读一个线程写的锁,应该比Delphi自带的读写锁高效,本人没有做对比测试。

本文的锁不可以在一个线程里重入,否则会锁死,另外读写锁最多支持65535个线程同时读。

// [email protected]// 跨平台简易高效锁 unit utLocker; interface type  // 多读单写锁  // 1.写的时候阻塞其他所有写和读  // 2.读的时候不阻塞其他读,但阻塞所有写,当阻塞了一个或以上的写后,将阻塞所有后来新的读  TMultiReadSingleWriteLocker = class  protected    [Volatile]    FLocker: Integer;  public    procedure LockRead;    procedure UnLockRead; inline;    procedure LockWrite;    procedure UnLockWrite; inline;    function TryLockRead: Boolean; inline;    function TryLockWrite: Boolean; inline;    constructor Create;  end;   TSimpleLocker = class  protected    [Volatile]    FLocker: Integer;  public    procedure Lock;    procedure UnLock; inline;    function TryLock: Boolean; inline;  end; implementation uses System.SyncObJs,System.SysUtils,System.Classes; type  TSpinWait = record  private const    YIEldThreshold = 10;    Sleep1Threshold = 20;    Sleep0Threshold = 5;  private    FCount: Integer;    function GetNextSpinCycleWillYIEld: Boolean; inline;  public    procedure reset;inline;    procedure SpinCycle;inline;     property Count: Integer read FCount;    property NextSpinCycleWillYIEld: Boolean read GetNextSpinCycleWillYIEld;  end;   { TSpinWait } function TSpinWait.GetNextSpinCycleWillYIEld: Boolean;begin  Result := (FCount > YIEldThreshold) or (cpuCount = 1);end; procedure TSpinWait.reset;begin  FCount := 0;end; procedure TSpinWait.SpinCycle;var  SpinCount: Integer;begin  if NextSpinCycleWillYIEld then  begin    if FCount >= YIEldThreshold then      SpinCount := FCount - YIEldThreshold    else      SpinCount := FCount;    if SpinCount mod Sleep1Threshold = Sleep1Threshold - 1 then      TThread.Sleep(1)    else if SpinCount mod Sleep0Threshold = Sleep0Threshold - 1 then      TThread.Sleep(0)    else      TThread.YIEld;  end  else    TThread.SpinWait(4 shl FCount);  Inc(FCount);  if FCount < 0 then    FCount := YIEldThreshold + 1;end; { TMultiReadSingleWriteLocker } procedure TMultiReadSingleWriteLocker.LockRead;var  CurLock: Integer;  Wait: TSpinWait;begin  Wait.reset;  while True do  begin    CurLock := FLocker;    if CurLock <= $FFFF then    begin      if TInterlocked.CompareExchange(FLocker,CurLock + 1,CurLock) = CurLock      then        Exit;    end;    Wait.SpinCycle;  end;end; procedure TMultiReadSingleWriteLocker.LockWrite;var  CurLock: Integer;  Wait: TSpinWait;begin  Wait.reset;  while True do  begin    CurLock := FLocker;    if CurLock <= $FFFF then    begin      if TInterlocked.CompareExchange(FLocker,CurLock + $10000,CurLock) = CurLock      then        Exit;    end;    Wait.SpinCycle;  end;end; function TMultiReadSingleWriteLocker.TryLockRead: Boolean;var  CurLock: Integer;begin  CurLock := FLocker;  if CurLock <= $FFFF then    Result := TInterlocked.CompareExchange(FLocker,CurLock + 1,CurLock)      = CurLock  else    Result := False;end; function TMultiReadSingleWriteLocker.TryLockWrite: Boolean;var  CurLock: Integer;begin  CurLock := FLocker;  if CurLock <= $FFFF then    Result := TInterlocked.CompareExchange(FLocker,CurLock + $10000,CurLock)      = CurLock  else    Result := False;end; procedure TMultiReadSingleWriteLocker.UnLockWrite;begin  if FLocker < $10000 then    raise Exception.Create(TMultiReadSingleWriteLocker Error);   TInterlocked.Add(FLocker,-$10000);end; procedure TMultiReadSingleWriteLocker.UnLockRead;begin  TInterlocked.Decrement(FLocker);end; constructor TMultiReadSingleWriteLocker.Create;begin  FLocker := 0;end; { TSimpleLocker } procedure TSimpleLocker.Lock;var  Wait: TSpinWait;begin  Wait.reset;  while True do  begin    if FLocker = 0 then    begin      if TInterlocked.CompareExchange(FLocker,1,0) = 0 then        Exit;    end;    Wait.SpinCycle;  end;end; function TSimpleLocker.TryLock: Boolean;begin  if FLocker = 0 then  begin    Result := TInterlocked.CompareExchange(FLocker,0) = 0;  end  else    Result := False;end; procedure TSimpleLocker.UnLock;begin  if TInterlocked.CompareExchange(FLocker,0,1) <> 1 then    raise Exception.Create(TSimpleLocker Error);end; end.

 

一个简易 无锁池

1.所有读写无等待,不需要判断条件直接读写(除自动扩充容量时),效率是一般带锁或带条件判断池的两倍以上。

2.预先开辟2的幂大小容量,可自增,每次翻倍

3.仅提供思路,工程应用可靠性还不确定。

// 无锁池// hezihang @cnblogs.com// 20160228 增加代引用计数器内存块的池,增加编译指令POolGROW功能,可打开关闭池的自动翻倍增长功能// 20160225 修正Grow中FWritePtr没有增长BUG// 20140609 增加Grow临界区,减少等待时间// 20140608 修正可能存在同时Grow的BUGunit Iocp.AtomPool;interface{ .$define POolGROW }Uses  System.SysUtils,System.SyncObJs;Type  Int32 = Integer;  UInt32 = Cardinal;  TAtomPoolAbstract = class  private    FWritePtr: Int32;    FReadPtr: Int32;    FHighBound: UInt32;    FData: array of Pointer;{$IFDEF POolGROW}    FCs: TCriticalSection;    FLock: Int32;    procedure CheckGrow; inline;    procedure Grow; inline;{$ENDIF}  Protected    function AlLocitemResource: Pointer; virtual; abstract;    procedure FreeItemResource(Item: Pointer); virtual; abstract;    function GetCapacity: UInt32;    procedure FreeResources;  Public    procedure AllocResources;    function Get: Pointer;    procedure Put(Item: Pointer);    Constructor Create(Capacity: UInt32); Virtual;    Destructor Destroy; OverrIDe;    property Capacity: UInt32 read GetCapacity;  End;  TAtomPoolMem4K = class(TAtomPoolAbstract)    function AlLocitemResource: Pointer; overrIDe;    procedure FreeItemResource(Item: Pointer); overrIDe;  end;  // 内存块带引用计数器的池,池容量恒定不能增长  TAtomMemoryPoolRef = class  private    FMemory: PByteArray;    FWritePtr: Int32;    FReadPtr: Int32;    FHighBound: UInt32;    FMemSize: UInt32;    FData: array of Pointer;    FDataRef: array of Int32;  Protected    function GetCapacity: UInt32;    procedure AllocResources;    procedure FreeResources;  Public    function Get: Pointer;    procedure Put(Item: Pointer);    function IncRef(Item: Pointer): Int32;    function DecRef(var Item: Pointer): Int32;    Constructor Create(Capacity: UInt32; MemSize: UInt32);    Destructor Destroy; OverrIDe;    property Capacity: UInt32 read GetCapacity;    property MemSize:UInt32 read FMemSize;  End;Implementationconst  MAXTHREADCOUNT = 1000; // 从池中申请资源最大线程数  // 创建池,大小必须是2的幂,并且必须大于MAXTHREADCOUNTConstructor TAtomPoolAbstract.Create(Capacity: UInt32);var  OK: Boolean;Begin  inherited Create;  OK := (Capacity and (Capacity - 1) = 0);  OK := OK and (Capacity > MAXTHREADCOUNT);  if not OK then    raise Exception.Create(Format(池长度必须大于%d并为2的幂,[MAXTHREADCOUNT]));{$IFDEF POolGROW}  FCs := TCriticalSection.Create;{$ENDIF}  FHighBound := Capacity - 1;  FReadPtr := 0;End;Destructor TAtomPoolAbstract.Destroy;Begin  FreeResources;  SetLength(FData,0);{$IFDEF POolGROW}  FCs.Free;{$ENDIF}  inherited;End;procedure TAtomPoolAbstract.AllocResources;var  i: UInt32;begin  try    SetLength(FData,Capacity);    for i := 0 to FHighBound do      FData[i] := AlLocitemResource;  except    Raise Exception.Create(池申请内存失败);  end;end;procedure TAtomPoolAbstract.FreeResources;var  i: UInt32;begin  for i := FHighBound downto 0 do    Self.FreeItemResource(FData[i]);end;procedure TAtomPoolAbstract.Put(Item: Pointer);var  N: UInt32;begin{$IFDEF POolGROW}  CheckGrow;{$ENDIF}  N := TInterlocked.Increment(FWritePtr);  FData[N and FHighBound] := Item;end;Function TAtomPoolAbstract.Get: Pointer;var{$IFDEF POolGROW}  N,M,K: UInt32;{$ELSE}  N: UInt32;{$ENDIF}begin{$IFDEF POolGROW}  N := FWritePtr and FHighBound;  M := FReadPtr and FHighBound;  K := (M + MAXTHREADCOUNT) and FHighBound;  if (N > M) and (N < K) then  // if ((N > M) and (N < K)) or ((N < M) and (N > K)) then  begin    Grow  end;{$ENDIF}  N := TInterlocked.Increment(FReadPtr);  Result := FData[N and FHighBound];end;function TAtomPoolAbstract.GetCapacity: UInt32;begin  Result := FHighBound + 1;end;{$IFDEF POolGROW}procedure TAtomPoolAbstract.CheckGrow;begin  if TInterlocked.Add(FLock,0) > 0 then  begin    while FLock = 1 do      Sleep(0);    FCs.Enter;    FCs.Leave;  end;end;procedure TAtomPoolAbstract.Grow;var  i,N: Integer;begin  if TInterlocked.CompareExchange(FLock,0) = 0 then // 加锁  begin    FCs.Enter;    TInterlocked.Increment(FLock);    N := Length(FData);    SetLength(FData,N + N);    for i := N to High(FData) do      FData[i] := AlLocitemResource;    TInterlocked.Increment(FLock);    FHighBound := High(FData);    FWritePtr := FHighBound;    FCs.Leave;    TInterlocked.Exchange(FLock,0);  end  else    CheckGrow;end;{$ENDIF}{ TAtomPoolMem4K }function TAtomPoolMem4K.AlLocitemResource: Pointer;begin  GetMem(Result,4096);end;procedure TAtomPoolMem4K.FreeItemResource(Item: Pointer);begin  FreeMem(Item,4096);end;Constructor TAtomMemoryPoolRef.Create(Capacity: UInt32; MemSize: UInt32);var  OK: Boolean;Begin  inherited Create;  OK := (Capacity and (Capacity - 1) = 0);  OK := OK and (Capacity > MAXTHREADCOUNT);  if not OK then    raise Exception.Create(Format(池长度必须大于%d并为2的幂,[MAXTHREADCOUNT]));  if FMemSize and $10 <> 0 then    raise Exception.Create(内存块大小必须是16的倍数);  FMemSize := MemSize;  try    AllocResources;    FHighBound := Capacity - 1;    FWritePtr := FHighBound;    FReadPtr := 0;  except    Raise Exception.Create(池申请内存失败);  end;End;function TAtomMemoryPoolRef.DecRef(var Item: Pointer): Int32;var  N: Integer;begin  N := (NativeUInt(Item) - NativeUInt(FMemory)) div FMemSize;  if (N>=0) and (N<=FHighBound) then  begin    Result := TInterlocked.Decrement(FDataRef[N]);    if Result = 0 then    begin      Put(Item);      Item := nil;    end;  end  else Result:=-1;end;Destructor TAtomMemoryPoolRef.Destroy;Begin  FreeResources;  inherited;End;procedure TAtomMemoryPoolRef.AllocResources;var  i: UInt32;  P: PByteArray;begin  SetLength(FData,Capacity);  SetLength(FDataRef,Capacity);  FillChar(FDataRef[0],Capacity * Sizeof(FDataRef[0]),0);  GetMem(FMemory,Length(FData) * FMemSize); // 一次申请所有内存  P := FMemory;  for i := 0 to FHighBound do  begin    FData[i] := P;    Inc(P,FMemSize);  end;end;procedure TAtomMemoryPoolRef.FreeResources;begin  FreeMem(FMemory,Length(FData) * FMemSize);  SetLength(FData,0);  SetLength(FDataRef,0);end;procedure TAtomMemoryPoolRef.Put(Item: Pointer);var  N: UInt32;begin  N := TInterlocked.Increment(FWritePtr);  FData[N and FHighBound] := Item;end;Function TAtomMemoryPoolRef.Get: Pointer;var  N: UInt32;begin  N := TInterlocked.Increment(FReadPtr);  Result := FData[N and FHighBound];end;function TAtomMemoryPoolRef.GetCapacity: UInt32;begin  Result := FHighBound + 1;end;function TAtomMemoryPoolRef.IncRef(Item: Pointer): Int32;var  N: Integer;begin  N := (NativeInt(Item) - NativeInt(FMemory)) div FMemSize;  if (N>=0) and (N<=FHighBound) then    Result := TInterlocked.Increment(FDataRef[N])  else    Result:=-1;end;End.
简易高效的Delphi原子队列

本文提供Delphi一个基于原子 *** 作的无锁队列,简易高效。适用于多线程大吞吐量 *** 作的队列。

可用于AndroID系统和32,64位windows系统。

 

感谢歼10和qsl提供了修改建议!

有如下问题:

1.必须事先足够大开辟内存,大到不会出现队列溢出了。

2.队列大小必须是2的幂

3.不能压入空指针

4.本程序还未经过工程应用考验

unit Iocp.AtomQueue;interfaceUses  SysUtils,SyncObJs;Type  TAtomFIFO = Class  Protected    FWritePtr: Integer;    FReadPtr: Integer;    FCount:Integer;    FHighBound:Integer;    FisEmpty:Integer;    FData: array of Pointer;    function GetSize:Integer;  Public    procedure Push(Item: Pointer);    function Pop: Pointer;    Constructor Create(Size: Integer); Virtual;    Destructor Destroy; OverrIDe;    Procedure Empty;    property Size: Integer read GetSize;    property UsedCount:Integer read FCount;  End;Implementation//创建队列,大小必须是2的幂,需要开辟足够大的队列,防止队列溢出Constructor TAtomFIFO.Create(Size: Integer);var  i:NativeInt;  OK:Boolean;Begin  inherited Create;  OK:=(Size and (Size-1)=0);  if not OK then raise Exception.Create(FIFO长度必须大于等于256并为2的幂);  try    SetLength(FData,Size);    FHighBound:=Size-1;  except    Raise Exception.Create(FIFO申请内存失败);  end;End;Destructor TAtomFIFO.Destroy;Begin  SetLength(FData,0);  inherited;End;procedure TAtomFIFO.Empty;begin  while (TInterlocked.Exchange(FReadPtr,0)<>0) and  (TInterlocked.Exchange(FWritePtr,0)<>0) and  (TInterlocked.Exchange(FCount,0)<>0) do;end;function TAtomFIFO.GetSize: Integer;begin  Result:=FHighBound+1;end;procedure TAtomFIFO.Push(Item:Pointer);var  N:Integer;begin  if Item=nil then Exit;  N:=TInterlocked.Increment(FWritePtr) and FHighBound;  FData[N]:=Item;  TInterlocked.Increment(FCount);end;Function TAtomFIFO.Pop:Pointer;var  N:Integer;begin  if TInterlocked.Decrement(FCount)<0 then  begin    TInterlocked.Increment(FCount);    Result:=nil;  end  else  begin    N:=TInterlocked.Increment(FReadPtr) and FHighBound;    //假设线程A调用了Push,并且正好是第1个push,    //执行了N:=TInterlocked.Increment(FWritePtr) and FHighBound,    //还没执行FData[N]:=Item,被切换到其他线程    //此时假设线程B调用了Push,并且正好是第2个push,并且执行完毕,这样出现FCount=1,第2个Item不为空,而第一个Item还是nil(线程A还没执行赋值)    //假设线程C执行Pop,由于Count>0(线程B的作用)所以可以执行到这里,但此时FData[N]=nil(线程A还没执行赋值),    //因此线程C要等待线程A完成FData[N]:=Item后,才能取走FData[N]    //出现这种情况的概率应该比较小,基本上不会浪费太多cpu    while FData[N]=nil do Sleep(1);    Result:=FData[N];    FData[N]:=nil;  end;end;End.

性能测试:

采用天地弦提供的评估程序,进行了一些修改,分别对使用不同的临界区的队列进行对比结果如下:

其中Swith是因队列读空,进行线程上下文切换的次数

 

 

Delphi的FIFO实现

FIFO主要用于多个不同线程或进程之间数据交换时做缓冲区用,尤其适合实时数据通讯应用中的数据缓冲,接收线程(进程)将数据写入FIFO,处理线程(进程)从FIFO取出数据

本单元中:

TMemoryFIFO类适用于单进程内不同线程之间交换数据

TMapfileFIFO类适用于不同进程之间交换数据

 

Unit UtFIFO; Interface Uses  windows,SysUtils,SyncObJs; Type  PFIFOStruct= ^TFIFOStruct;   TFIFOStruct= Record    FSize: Integer;    FWritePtr: Integer;    FReadPtr: Integer;    FBuffer: TByteArray;  End;   TFIFOReadFunc= Function(Buf: Pointer; Count: Integer): Integer;  TFIFOReadFuncOfObject= Function(const Buf;  Count: Integer): Integer Of Object;   TAbstractFIFO= Class  Protected    FSelfAccess: Boolean;    FDataStruct: PFIFOStruct; // 数据区指针    Procedure AllocateResource(Size: Integer); Virtual; Abstract;    Procedure FreeResources; Virtual; Abstract;    Procedure Lock; Virtual; Abstract;    Procedure UnLock; Virtual; Abstract;  Public    Function FIFOFreeSpace: Integer;    Function FIFOUsedspace: Integer;    Function CheckFIFOFull: Boolean;    Function CheckFIFOEmpty: Boolean;    Function WriteData(const Buf: Pointer; Count: Integer): Integer; Virtual;    Function ReadData(Buf: Pointer; Count: Integer): Integer; Virtual;    Function ReadDataByFunc(Func: TFIFOReadFuncOfObject;      Count: Integer): Integer; Virtual;    Constructor Create(Size: Integer); Virtual;    Destructor Destroy; OverrIDe;    Procedure Empty;    Function Size: Integer;  End;   TMemoryFIFO= Class(TAbstractFIFO)  Protected    FLocker: TCriticalSection;    Procedure AllocateResource(Size: Integer); OverrIDe;    Procedure FreeResources; OverrIDe;    Procedure Lock; OverrIDe;    Procedure UnLock; OverrIDe;  Public    Constructor Create(Size: Integer); OverrIDe;    Destructor Destroy; OverrIDe;  End;   TfileMapFIFO= Class(TAbstractFIFO)  Private    FMaster:Boolean;    FMapHandle: THandle; // 内存映射文件句柄    FMutexHandle: THandle; // 互斥句柄    FMapname: String; // 内存映射对象    FPVHandle: THandle;  Protected    Procedure AllocateResource(Size: Integer); OverrIDe;    Procedure FreeResources; OverrIDe;    Procedure Lock; OverrIDe;    Procedure UnLock; OverrIDe;  Public    Constructor Create(Const Mapname: String; Size: Integer;bMaster:Boolean); Overload;    Destructor Destroy; OverrIDe;    Function WriteData(const Buf: Pointer; Count: Integer): Integer; OverrIDe;    Function ReadData(Buf: Pointer; Count: Integer): Integer; OverrIDe;    property PVHandle:NativeUInt  read FPVHandle;  End; Implementation Function Min(Const A,B: Integer): Integer; inline;begin  if A>B then Result:=B else Result:=Aend; Constructor TAbstractFIFO.Create(Size: Integer);Begin  inherited Create;  AllocateResource(Size);   If Not Assigned(FDataStruct) Then    Raise Exception.Create(FIFO申请内存失败);End; Destructor TAbstractFIFO.Destroy;Begin  FreeResources;  inherited;End; Function TAbstractFIFO.FIFOFreeSpace;Begin  With FDataStruct^ Do  Begin    Lock;    If FWritePtr> FReadPtr Then      Result:= (FSize- FWritePtr)+ FReadPtr- 1    Else    If FWritePtr< FReadPtr Then      Result:= FReadPtr- FWritePtr- 1    Else      Result:= FSize;    UnLock;  End;End; Function TAbstractFIFO.FIFOUsedspace;Begin  With FDataStruct^ Do  Begin    Lock;    If FWritePtr> FReadPtr Then      Result:= FWritePtr- FReadPtr    Else    If FWritePtr< FReadPtr Then      Result:= (FSize- FReadPtr)+ FWritePtr    Else      Result:= 0;    UnLock;  End;End; Function TAbstractFIFO.CheckFIFOFull: Boolean;Begin  With FDataStruct^ Do  Begin    Lock;    If (FWritePtr= FSize- 1)And (FReadPtr= 0) Then      Result:= True    Else    If (FWritePtr+ 1= FReadPtr) Then      Result:= True    Else      Result:= False;    UnLock;  End;End; Function TAbstractFIFO.CheckFIFOEmpty: Boolean;Begin  With FDataStruct^ Do  Begin    Lock;    Result:= (FWritePtr= FReadPtr);    UnLock;  End;End; Function TAbstractFIFO.WriteData(const Buf: Pointer; Count: Integer): Integer;Var  N: Integer;Begin   Result:= 0;  If Count<= 0 Then    Exit;  With FDataStruct^ Do  Begin    Lock;    If FWritePtr< FReadPtr Then               //如果没有满或已满    Begin      Result:= Min(Count,FReadPtr- FWritePtr- 1);      Move(Buf^,FBuffer[FWritePtr],Result);      FWritePtr:= (FWritePtr+ Result)Mod FSize;    End    Else    If FWritePtr = FReadPtr Then //Buffer 空    Begin      Result:= Min(Count,FSize- 1);      Move(Buf^,FBuffer[0],Result);      FWritePtr:= Result;      FReadPtr:= 0;    End    Else    Begin      Result:= Min(Count,FSize- FWritePtr);      Move(Buf^,Result);      if Result=Count then FWritePtr:= (FWritePtr+ Result) Mod FSize      else      Begin          N:= Min(Count- Result,FReadPtr);          Move(PByteArray(Buf)^[Result],N);          FWritePtr:= N;          Result:= Result+ N;      End;    End;    UnLock;  End;End; Function TAbstractFIFO.ReadData(Buf: Pointer; Count: Integer): Integer;Var  N: Integer;Begin  Result:= 0;  If Count<= 0 Then    Exit;  With FDataStruct^ Do  Begin    Lock;    If FReadPtr< FWritePtr Then    Begin      Result:= Min(Count,FWritePtr- FReadPtr);      Move(FBuffer[FReadPtr],Buf^,Result);      FReadPtr:= (FReadPtr+ Result)Mod FSize;    End    Else if FReadPtr>FWritePtr Then    Begin      Result:= Min(Count,FSize- FReadPtr);      Move(FBuffer[FReadPtr],Result);      if Result=Count then FReadPtr:=(FReadPtr+Result) mod FSize      else      Begin          N:= Min(Count- Result,FWritePtr);          Move(FBuffer[0],PByteArray(Buf)[Result],N);          FReadPtr:= N;          Result:= Result+ N;      End;    End;    UnLock;  End;End; Function TAbstractFIFO.ReadDataByFunc(Func: TFIFOReadFuncOfObject;  Count: Integer): Integer;Var  N,M: Integer;Begin  Result:= 0;  If Count<= 0 Then    Exit;   With FDataStruct^ Do  Begin    Lock;    Try      If FReadPtr< FWritePtr Then      Begin        Result:= Func(FBuffer[FReadPtr],Min(Count,FWritePtr- FReadPtr));        FReadPtr:= (FReadPtr+ Result)Mod FSize;      End      Else if FReadPtr>FWritePtr Then      Begin        Result:= Func(FBuffer[FReadPtr],FSize- FReadPtr));        if Result=Count then FReadPtr:=(FReadPtr+Result) mod FSize        else        Begin            N:= Func(FBuffer[0],Min(Count- Result,FWritePtr));            FReadPtr:= N;            Result:= Result+ N;        End;      End;    Finally      UnLock;    End;  End;End; Procedure TAbstractFIFO.Empty;Begin  Lock;  With FDataStruct^ Do  Begin    FWritePtr:= 0;    FReadPtr:= 0;  End;  UnLock;End; Function TAbstractFIFO.Size: Integer;Begin  Result:= FDataStruct^.FSize- 1;End; Constructor TMemoryFIFO.Create(Size: Integer);Begin  inherited Create(Size);  FLocker:= TCriticalSection.Create;End; Destructor TMemoryFIFO.Destroy;Begin  FLocker.Free;  inherited;End; Procedure TMemoryFIFO.AllocateResource(Size: Integer);Begin  inherited;  GetMem(FDataStruct,Size+ 3* Sizeof(Integer));  With FDataStruct^ Do  Begin    FSize:= Size;    FWritePtr:= 0;    FReadPtr:= 0;  End;End; Procedure TMemoryFIFO.FreeResources;Begin  FreeMem(FDataStruct,FDataStruct^.FSize+ 3* Sizeof(Integer));  inherited;End; Procedure TMemoryFIFO.Lock;Begin  FLocker.Enter;End;Procedure TMemoryFIFO.UnLock;Begin  FLocker.Leave;End; // 构造函数Constructor TfileMapFIFO.Create(Const Mapname: String; Size: Integer;bMaster:Boolean);Begin  FMapname:= Mapname;  FMaster:=bMaster;  inherited Create(Size);End; Destructor TfileMapFIFO.Destroy;Begin  CloseHandle(FPVHandle);  inherited;End; Procedure TfileMapFIFO.AllocateResource(Size: Integer);Begin  inherited;  if FMaster then  begin    FMapHandle:= CreatefileMapPing($FFFFFFFF,Nil,PAGE_READWRITE,0,Size+ 3* Sizeof(Integer),PChar(FMapname));     If (FMapHandle= INVALID_HANDLE_VALUE)Or (FMapHandle= 0) Then      Raise Exception.Create(创建文件映射对象失败!);  end  else    FMapHandle:=OpenfileMapPing(file_MAP_ALL_ACCESS,False,PChar(FMapname));   FDataStruct:= MapVIEwOffile(FMapHandle,file_MAP_ALL_ACCESS,0);   // 创建互斥对象,在写文件映射空间时用到它,以保持数据同步  FMutexHandle:= windows.CreateMutex(Nil,PChar(FMapname+ .Mtx));  FPVHandle := CreateEvent(nil,True,PChar(FMapname + .PV));  If (FMutexHandle= 0)or(FPVHandle = 0) Then    Raise Exception.Create(创建互斥对象失败);   // 判断是否已经建立文件映射了  If (FMapHandle <> 0)And (GetLastError = ERROR_ALREADY_EXISTS) Then  Begin  End  Else  Begin    FillChar(FDataStruct^,Size+ 3* Sizeof(Integer),0);    FDataStruct^.FSize:= Size;  EndEnd; Procedure TfileMapFIFO.FreeResources;Begin  UnmapVIEwOffile(FDataStruct);  CloseHandle(FMutexHandle);  CloseHandle(FMapHandle);  inherited;End;Procedure TfileMapFIFO.Lock;Begin  WaitForSingleObject(FMutexHandle,INFINITE); // =WAIT_OBJECT_0)End; Procedure TfileMapFIFO.UnLock;Begin  ReleaseMutex(FMutexHandle);End; Function TfileMapFIFO.WriteData(const Buf: Pointer; Count: Integer): Integer;Begin  Lock;  Result:= inherited WriteData(Buf,Count);  SetEvent(FPVHandle);  UnLock;End; Function TfileMapFIFO.ReadData(Buf: Pointer; Count: Integer): Integer;Begin  Lock;  Result:= inherited ReadData(Buf,Count);  UnLock;End; End.
总结

以上是内存溢出为你收集整理的Delphi 高效读写锁全部内容,希望文章能够帮你解决Delphi 高效读写锁所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1274462.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存