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:=A
end; 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;
End
End; 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的FIFO实现的更多相关文章
- 简易高效的Delphi原子队列
本文提供Delphi一个基于原子操作的无锁队列,简易高效.适用于多线程大吞吐量操作的队列. 可用于Android系统和32,64位Windows系统. 感谢歼10和qsl提供了修改建议! 有如下问题: ...
- (翻译)FIFO In Hardware
翻译一些自己觉得有价值的材料,工作中碰到英语大多数是读,基本没有写或者翻的,翻得不好不到位的敬请指摘. 同时也附原文以供参考. http://electronics.stackexchange.com ...
- 学习笔记:7z在delphi的应用
最近做个发邮件的功能,需要将日志文件通过邮件发送回来用于分析,但是日志文件可能会超级大,测算下来一天可能会有800M的大小.所以压缩是不可避免了,delphi中的默认压缩算法整了半天不太好使,就看了看 ...
- OS存储管理——FIFO,LRU,OPT命中率
课程设计课题 存储管理程序设计 摘 要 虚拟存储器作为现代操作系统中存储管理的一项重要技术,实现了内存扩充功能.而分页请求分页系统正好可以完美的支持虚拟存储器功能,它具有请求调页功能和页面置换功能.在 ...
- delphi连接sql存储过程
针对返回结果为参数的 一. 先建立自己的存储过程 ALTER PROCEDURE [dbo].[REName] ) AS BEGIN select ROW_NUMBER() over(order by ...
- 详解三种缓存过期策略LFU,FIFO,LRU(附带实现代码)
在学操作系统的时候,就会接触到缓存调度算法,缓存页面调度算法:先分配一定的页面空间,使用页面的时候首先去查询空间是否有该页面的缓存,如果有的话直接拿出来,如果没有的话先查询,如果页面空间没有满的时候, ...
- 页置换算法FIFO、LRU、OPT
页置换算法FIFO.LRU.OPT 为什么需要页置换 在地址映射过程中,若在页面中发现所要访问的页面不再内存中,则产生缺页中断.当发生缺页中断时操作系统必须在内存选择一个页面将其移出内存,以便为即将调 ...
- delphi 2010与delphi XE破解版的冲突
在系统中同时安装了Dephi 2010LITE版与Delphi XE lite后,总是会有一个有问题 是因为两者都是读取C:\ProgramData\Embarcadero目录下的license文件, ...
- [Delphi] Delphi版本号对照
VER300 Delphi Seattle / C++Builder Seattle 23 230 (Delphi:Win32/Win64/OSX/iOS32/iOS64/An ...
随机推荐
- java笔记--正则表达式的运用(包括电话,邮箱验证等)
正则表达式 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877402.html "谢谢-- 正则表达式符号:" ...
- LeetCode算法题 菜鸟总结
近期准备抽出一点时间,刷一些题防止手生,毕竟codemonkey,吃饭的手艺不能忘. ······································· 基本的题目都是基于java语言解答 ...
- Thinkphp 漏洞小试
首先确定这个网站使用thinkphp的框架 国内很多php开源项目的代码都是使用thinkphp框架编写的,但是thinkphp框架有很多版本,如何才能知道我们使用的框架是哪个版本的呢? 在URL后面 ...
- vs中添加工具cmder并自动定位到当前目录
有时在vs中为了使用git命令行,需要打开cmder工具,并让cmder自切换到当前目录: 方法1: 看下效果: 方法2:在文件夹中右键(添加到右键自行百度)
- Angular Reactive Form-响应式表单验证
内建验证规则 Angular中提供了一些內建的Validators,这些验证规则可以在Template-Driven或Reactive表单中使用. 目前 Angular 支持的内建 validator ...
- 前端——实用UI组件库
Angular UI 组件 ngx-bootstrap 是一套Bootstrap 组件 官网:https://valor-software.com/ngx-bootstrap/#/ github: h ...
- phonegap 启动背景设置
1.拷贝一张图片到Android项目的res目录的drawable-mdpi目录下 2.在主要的src下的java文件中编写代码 package com.study.hellomobileword1; ...
- 7、Dubbo-配置(2)
重试次数 通常配合timeout超时设置进行配置 <dubbo:reference "> </dubbo:reference> <dubbo:service i ...
- GPS-Graph Processing System Graph Coloring算法分析 (三)
HamaWhite 原创,转载请注明出处!欢迎大家增加Giraph 技术交流群: 228591158 Graph coloring is the problem of assignin ...
- [Python 网络编程] TCP编程/群聊服务端 (二)
群聊服务端 需求分析: 1. 群聊服务端需支持启动和停止(清理资源); 2. 可以接收客户端的连接; 接收客户端发来的数据 3. 可以将每条信息分发到所有客户端 1) 先搭架子: #TCP Serve ...