博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delphi的FIFO实现
阅读量:4320 次
发布时间:2019-06-06

本文共 8835 字,大约阅读时间需要 29 分钟。

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

本单元中:

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

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

 

Unit UtFIFO;InterfaceUses  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;ImplementationFunction 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^, FBuffer[FWritePtr], Result);      if Result=Count then FWritePtr:= (FWritePtr+ Result) Mod FSize      else      Begin          N:= Min(Count- Result, FReadPtr);          Move(PByteArray(Buf)^[Result], FBuffer[0], 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], Buf^, 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], Min(Count, 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, 0, 0);  // 创建互斥对象,在写文件映射空间时用到它,以保持数据同步  FMutexHandle:= Windows.CreateMutex(Nil, False, PChar(FMapName+ '.Mtx'));  FPVHandle := CreateEvent(nil,True,False,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.

  

转载于:https://www.cnblogs.com/hezihang/p/3654516.html

你可能感兴趣的文章
海亮SC
查看>>
[Hibernate] - Generic Dao
查看>>
【Linux】一步一步学Linux——Linux系统常用快捷键(12) 待更新...
查看>>
Vue中computed和watch使用场景和方法
查看>>
laravel路由与控制器(资源路由restful)
查看>>
Html5移动端页面自适应布局详解(阿里rem布局)
查看>>
memoize-one在React中的应用
查看>>
SpringBoot整合JDBC数据库操作第二弹-配置基本数据库连接源
查看>>
nginx日志切割脚本
查看>>
ipvsadm添加虚拟服务器报错问题
查看>>
LVS-DR集群搭建脚本
查看>>
Docker拉取的镜像源更改为国内的镜像源
查看>>
LVS健康检查脚本
查看>>
PowerCLI 对vm批量关机
查看>>
拿来即用学PYTHON:序
查看>>
github+jenkins+maven+docker自动化构建部署
查看>>
前端禁止鼠标右键、禁止全选、复制、粘贴
查看>>
六. k8s--ingress学习笔记
查看>>
二. python数组和列表
查看>>
七. k8s--volumes之pv pvc学习笔记
查看>>