📄 u_share_ringbuffer.pas
字号:
unit u_Share_RingBuffer;
interface
uses Windows;
const
MAX_BUFFER_LEN = 4096;
type
//环形缓冲区类--可变数组缓冲区类
TRingBuffer = class(TObject)
private
FBuffer : array of Char; //缓冲区
FBufferLen : Longint; //缓冲区长度
FisWrap : Boolean; //是否返回头部
FCritical : TRTLCriticalSection; //临界区
FIsCritical : Boolean; //是否需要临界区
procedure Require(); //共享锁内存
procedure Release(); //共享解锁
function GetEmptyCount():Longint; //剩余空白数据量
public
FReadPos : LongInt; //读取点
FWritePos : LongInt; //写入点
function GetDataCount():Longint; //取得可用数据量
function Readbuffer(var Buffer; Count: Longint):Longint; //读取数据
function WriteBuffer(const Buffer; Count: Longint):Longint; //写入数据
function CopyBuffer(var Buffer; Count: Longint):Longint; //复制数据
function ResizeBuffer(ABufferLen:Longint):Boolean; //更改缓冲区大小
function ReSet():Boolean; //复位缓冲区
constructor Create(ABufferLen:Longint);
destructor Destory();
published
property BufferLen: Longint read FBufferLen; //缓冲区总小小
property IsCritical:Boolean read FIsCritical write FIsCritical; //多线程情况下需要考虑互斥访问共享缓冲区时使用
end;
//环形缓冲类–阻塞(同步)模式读写–继承自TRingBuffer
//适合于多线程读写
TRingBufferSyn = class(TRingBuffer)
private
FSynEvent : THandle; //同步读写事件句柄
public
function ReadbufferSyn(var Buffer; Count: Longint;TimeOut:Longint):Integer; //读取数据
function WriteBufferSyn(const Buffer; Count: Longint;TimeOut:Longint):Integer; //写入数据
constructor Create(ABufferLen:Longint);
destructor Destory();
end;
implementation
{ TRingBuffer }
constructor TRingBuffer.Create(ABufferLen:Longint);
begin
inherited Create();
FBufferLen := ABufferLen;
SetLength( FBuffer,ABufferLen );
FReadPos := 0;
FWritePos := 0;
FIsCritical := False;
FisWrap := False; //是否返回头部
InitializeCriticalSection(FCritical);
end;
destructor TRingBuffer.Destory;
begin
DeleteCriticalSection(FCritical);
inherited Destroy;
end;
procedure TRingBuffer.Require();
begin
if FIsCritical then
begin
EnterCriticalSection(FCritical);
end;
end;
procedure TRingBuffer.Release();
begin
if FIsCritical then
begin
LeaveCriticalSection(FCritical);
end;
end;
function TRingBuffer.CopyBuffer(var Buffer; Count: Longint):Longint; //复制数据
var
Li_RemainCount,Litemp : Integer;
tempbuf:array[0..MAX_BUFFER_LEN] of Char;
Datacount:Integer;
begin
try
Result := 0;
Require();
Datacount := GetDataCount(); //获取实际数据量
if (Datacount <= 0) or ( Count = 0 ) then //无数据可读的情况
begin
Result := 0;
Exit;
end;
FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
if Datacount >= Count then //有足够数据可读
begin
if FWritePos > FReadPos then
begin
Move(FBuffer[FReadPos],Buffer,Count);
Result := Count;
FisWrap := false;
end
else
begin
//先判断尾部剩余空间有多少可读数据
Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
if Count > Li_RemainCount then //尾部剩余数据都可读,把尾部数据全部读出
begin
Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
Litemp := Count - Li_RemainCount; //剩余要读的数据
Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp); //从头部读取剩余数据
Move(tempbuf,Buffer,Count);
Result := Count;
FisWrap := false;
end
else
begin //当可用数据不到尾部,则直接读取
Move(FBuffer[FReadPos],tempbuf,Count); //暂存数据到临时buf
Move(tempbuf,Buffer,Count);
Result := Count;
FisWrap := True;
end;
end;
end else begin //无足够数据可读,可读取剩余数据
if FWritePos > FReadPos then
begin
Move(FBuffer[FReadPos],Buffer,Datacount); //暂存数据到临时buf
Result := Datacount;
FisWrap := false;
end
else
begin
//先判断尾部剩余空间有多少可读数据
Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
Litemp := Datacount - Li_RemainCount; //剩余要读的数据
Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp);
Move(tempbuf,Buffer,Datacount);
Result := Datacount;
FisWrap := false;
end;
end;
finally
Release();
end;
end;
function TRingBuffer.ReSet():Boolean;
begin
FReadPos := 0;
FWritePos := 0;
FIsCritical := False;
FisWrap := False; //是否返回头部
fillchar(FBuffer[0],FBufferLen-1,0);
Result := True;
end;
{——————————————————————————-
过程名: Readbuffer
作者: 黄健
日期: 2007.08.25
参数: var Buffer 需要返回的数据;
Count: Integer 需要读取的数据
返回值: Longint类型, 返回实际读取的数据量 <=0 表示读取错误或缓冲区空
——————————————————————————-}
function TRingBuffer.Readbuffer(var Buffer; Count: Integer): Longint;
var
Li_RemainCount,Litemp : Integer;
tempbuf:array[0..MAX_BUFFER_LEN] of Char;
Datacount:Integer;
begin
try
Result := -1;
Require();
//if (Count < 0) or (Count > FBufferLen) then Exit;
Datacount := GetDataCount(); //获取实际数据量
if (Datacount <= 0) or ( Count = 0 ) then //无数据可读的情况
begin
Result := 0;
Exit;
end;
FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
if Datacount >= Count then //有足够数据可读
begin
if FWritePos > FReadPos then
begin
Move(FBuffer[FReadPos],Buffer,Count);
Inc(FReadPos,Count);
Result := Count;
FisWrap := false;
end
else
begin
//先判断尾部剩余空间有多少可读数据
Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
if Count > Li_RemainCount then //尾部剩余数据都可读,把尾部数据全部读出
begin
Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
Litemp := Count - Li_RemainCount; //剩余要读的数据
Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp); //从头部读取剩余数据
FReadPos := Litemp;
Move(tempbuf,Buffer,Count);
Result := Count;
FisWrap := false;
end
else
begin //当可用数据不到尾部,则直接读取
Move(FBuffer[FReadPos],tempbuf,Count); //暂存数据到临时buf
Inc(FReadPos,Count);
Move(tempbuf,Buffer,Count);
Result := Count;
FisWrap := True;
end;
end;
end
else
begin //无足够数据可读,可读取剩余数据
if FWritePos > FReadPos then
begin
Move(FBuffer[FReadPos],Buffer,Datacount); //暂存数据到临时buf
Inc(FReadPos,Datacount);
Result := Datacount;
FisWrap := false;
end
else
begin
//先判断尾部剩余空间有多少可读数据
Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
Litemp := Datacount - Li_RemainCount; //剩余要读的数据
Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp);
FReadPos := Litemp;
Move(tempbuf,Buffer,Datacount);
Result := Datacount;
FisWrap := false;
end;
end;
finally
Release();
end;
end;
{——————————————————————————-
过程名: WriteBuffer
作者: 黄健
日期: 2007.08.25
参数: const Buffer; 要写入的数据
Count: Integer 要写入数据大小
返回值: Longint 返回实际写入的数据量,<=0 表示写入错误或缓冲区满
——————————————————————————-}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -