Delphi의 FIFO 실현
9827 단어 Delphi
이 단원의 경우:
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.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Delphi] TStringBuilder그리고 꼭 사용해야만 할까? 그림처럼 Heap 영역에 "Hello" 공간을 생성하고 포인팅을 한다. "Hello World" 공간을 새로 생성한 후 포인팅을 하게 된다. 결국 "Hello" 라는 String 객체가 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.